- Notas de Versão
- Introdução
- Configuração e Instalação
- Projetos de automação
- Dependências
- Tipos de fluxos de trabalho
- Comparação de arquivos
- Melhores Práticas de Automação
- Design do fluxo de trabalho
- Automação de Interface Gráfica
- Organização de projetos
- Ciclo de Vida da Automação
- Metodologia para reutilizar componentes da IU
- Integração de controle de origem
- Depuração
- A ferramenta de diagnóstico
- Analisador de Fluxo de Trabalho
- Sobre o Analisador de Fluxo de Trabalho
- STN MG-001 - Convenção de nomenclatura de variáveis
- STN MG-002 - Convenção de nomenclatura de argumentos
- STN MG-004 - Duplicação de Nome de Exibição
- STN MG-005 - Variável substitui variável
- STN MG-006 - Variável substitui argumento
- STN MG-008 - Comprimento de variável excedido
- STN MG-009 - Variáveis Catablema de prefixo
- STN MG-011 - Argumentos Catablema de prefixo
- STN MG-012 - Valores padrão de argumentos
- STN MG-016 - Comprimento do argumento excedido
- SR-DB-002 - Contagem alta de argumentos
- SR-DB-003 - Esvaziar bloco catechu
- SR-DB-007 - Múltiplas camadas Com fluxograma
- SR-DB-020 - Propriedades de saída indefinidas
- SR-DB-023 - Fluxo de trabalho vazio
- SR-DB-024 - Verificação da atividade Persistente
- SR-DB-025 - Pré-requisito de serialidade de variáveis
- SR-DB-026 - Uso da atividade Dela
- SR-DB-027 - Melhores práticas de persistência
- SR-DB-028 - Pré-requisito de serialidade de argumentos
- SR-US-005 - Argumentos de atividades embutidos em código
- SR-US-009 - Variáveis não utilizadas
- SR-US-010 - Dependências não utilizadas
- SR-US-014 - Restrições de pacotes
- SR-US-020 - Mensagens de logue mínimas
- SR-US-024 - Não utilizado e postergado
- SR-US-025 - Uso incorreto do valor salvo
- SR-US-026 - Restrições da atividade
- SR-US-027 - Pacotes necessários
- ST-USG-28 — restringir modelos de invocação de arquivos
- Variáveis
- Argumentos
- Namespaces Importados
- Gravação
- Elementos de Interface Gráfica
- Fluxo de controle
- Seletores
- Repo. de Objetos
- Extração de Dados
- Automação de imagem e texto
- Automação de tecnologias Citrino
- Automação RDP
- Automação da Salesforce
- Automação SAP
- Automação do Varear Horizonte
- Geração de logs
- A ferramenta ScreenScrapeJavaSupport
- O protocolo Servodrive
- Test Suite — Studio
- Extensões
- Solução de problemas
- Sobre a solução de problemas
- Suporte e limitações do Microsoft Apo-V
- Solução de problemas do Internet Explorer x64
- Problemas do Microsoft Office
- Como identificar elementos de EU em PDF com opções de acessibilidade
- Reparando o suporte da Active Accessibility
- Solução de problemas de aplicativos do JxBrowser
- Monitoração de eventos de usuário
- Solução de problemas da Citrix
- Automação de aplicativos em execução com um usuário diferente do Windows
![](https://docs.uipath.com/_next/static/media/grid.05ebd128.png?w=3840&%3Bq=100)
Metodologia para reutilizar componentes da IU
Os projetos da UiPath têm duas camadas principais:
- Camada lógica — contém todas as validações e processamentos de dados, bem como quaisquer outras instruções lógicas necessárias para o fluxo do processo.
- Camada de interação com a GUI — usada para extrair e inserir dados no aplicativo.
Para evitar problemas relacionados à manutenção e reusabilidade dos componentes, você pode separar a camada de interação com a GUI criando uma série de bibliotecas com componentes reutilizáveis dedicados exclusivamente à interação com as interfaces do usuário. Dessa forma, você pode criar uma biblioteca versátil, bastante robusta e fácil de manter (que contém apenas elementos de interação com a GUI e nenhuma outra lógica dependente do processo) e extremamente reutilizável (é muito provável que um processo diferente que automatiza o mesmo aplicativo possa reutilizar pelo menos alguns do componentes).
Além disso, o Repositório de Objetos introduzido no Studio v2020.10 trouxe uma maneira completamente nova de criar e gerenciar elementos usados na automação de IU, tornando-o um divisor de águas na construção de automações de IU escaláveis e altamente reutilizáveis.
Este artigo define uma metodologia para permitir a utilização de bibliotecas e o Repositório de Objetos para criar código reutilizável e de fácil manutenção; descreve os princípios arquitetônicos e as melhores práticas por trás deles; e oferece um detalhamento das etapas necessárias para criar componentes reutilizáveis, bem como diversos exemplos que usam o aplicativo Web ACME.
Há uma variedade de princípios de desenvolvimento de software que podem ser aplicados, independentemente da linguagem de programação ou da plataforma utilizada, e que podem ser muito úteis no contexto do desenvolvimento de RPA com o UiPath Studio.
Este é o principal princípio a ser abordado. A separação de conceitos (SoC) diz que um programa deve ser separado em diferentes seções, para que cada seção aborde um conceito separado. No nosso caso, precisamos criar nossa solução em camadas, ou seja, cada seção deve se tornar uma camada. Separar uma solução em camadas possibilita testar as camadas individualmente. Para um aplicativo de software normal, geralmente temos três camadas distintas:
-
Camada de apresentação diz respeito à interação com o usuário, exibindo dados e os apresentando ao usuário. Essa camada não deve conter lógica de negócios.
No contexto de um projeto de RPA, a camada de interação com a GUI substitui essa camada, visto que o principal objetivo de uma automação é interagir com outros aplicativos e não com um usuário real.
-
Camada de domínio diz respeito à lógica do domínio, que é o domínio geral do problema/situação de negócios que o aplicativo soluciona.
No contexto de um projeto de RPA, é a Camada lógica que está preocupada com a lógica do aplicativo.
-
Camada de persistência é onde os dados requeridos pelo aplicativo são armazenados.
Essa não é uma camada obrigatória num projeto de RPA, pois há casos de uso em que não existe armazenamento permanente de dados. Dado o escopo deste artigo, deixaremos essa camada de fora.
Outro princípio que precisamos considerar ao projetar um projeto RPA é o princípio da responsabilidade única. Isso significa que um arquivo XAML só deve fazer uma coisa e nada além disso. Esse princípio está associado ao princípio do baixo acoplamento e alta coesão. Isso significa que o código deve ser modular, mesmo que esteja em camadas. Portanto, podemos ter vários módulos para uma única camada.
- Baixo acoplamento significa que um módulo deve depender de outro módulo o mínimo possível. Em um projeto da UiPath, a modularização é alcançada usando bibliotecas (você pode encontrar mais informações sobre isso na seção Método).
- Alta coesão significa que as ações associadas ao mesmo aplicativo devem ser mantidas no mesmo módulo.
Um processo de RPA pode ser simplesmente definido como uma combinação de dados, manipulação de dados e interação de aplicativos.
- Dados — tipos de dados predefinidos selecionados ao definir variáveis ou argumentos, ou seus próprios tipos que você pode importar e usar no Studio. Além disso, a funcionalidade Data Service introduzida na v2020.10 oferece um local centralizado onde você pode criar tipos de dados e reutilizá-los em automações.
- Manipulação de dados - Isso pode ser feito por meio de atividades que são os blocos de construção de expressões de automação e/ou manipulação de dados. As atividades estão disponíveis em pacotes que você pode instalar no Studio. Você também pode criar suas próprias atividades personalizadas quando certas funcionalidades não são cobertas pelos pacotes disponíveis. Para obter mais informações sobre como criar atividades UiPath personalizadas, consulte Criação de uma Atividade Personalizada.
- Interação de aplicativos - Isso pode ser feito por meio de Automação de Interface Gráfica ou integrações/APIs. A Automação de Interface Gráfica pode ser usada para a maioria dos aplicativos disponíveis hoje. Os componentes de interação de interface gráfica podem ser reutilizados com a ajuda de bibliotecas ou do Repositório de Objetos.
O Repositório de Objetos possui uma estrutura hierárquica em que cada nó representa telas ou elementos, todos abaixo do nível do aplicativo. A estrutura é a seguinte:
- Um Aplicativo de interface gráfica é um aplicativo direcionado que pode ter várias versões, cada qual podendo ter várias telas.
- Tela é um escopo da IU que agrupa vários elementos pertencentes à mesma tela. O escopo da IU é extraído de atividades dentro do fluxo de trabalho ou gerado no momento da captura do elemento.
- O Elemento de interface gráfica contém seletores de elementos totais ou parciais, seletores de âncoras, contexto de captura de telas e imagens de elementos, além de outros metadados que descrevem o elemento na tela.
- Descritores de IU é um superconjunto de seletores que carrega informações para identificar elementos na tela de maneira única. Eles são extraídos de atividades no fluxo de trabalho e adicionados ao esquema estruturado que os agrupa por Aplicativo, Versão do Aplicativo, Telas e Elementos de IU. Em toda a estrutura taxonômica, apenas Telas e Elementos carregam informações do descritor, enquanto os restantes são usados para agrupamento e sua função é garantir o sucesso de atualizações entre versões de um aplicativo.
Por exemplo, na imagem abaixo, podemos identificar:
- Aplicativo de IU: ACME versão 1.0.0.
- Telas: painel de controle, faturas, login.
-
Elementos de IU: e-mail, botão de login.
Para cada elemento e tela no Repositório de Objetos, forneça os seguintes detalhes:
- O nome exato da tela, página ou elemento, como aparece na IU (por exemplo, Botão de login).
- O tipo, por exemplo, Botão ou Entrada (apenas para elementos).
- Uma descrição opcional. Recomendamos adicionar um resumo rápido de como o elemento pode ser usado (por exemplo, Clique em Login para concluir o processo de login).
-
Descritor de IU — informação que identifica o elemento de forma única. Incorpora seletores clássicos, seletores difusos e automação baseada em imagens. Recomendamos usar a automação baseada em imagens apenas se os outros métodos não funcionarem.
Consulte Sobre o Repositório de Objetos para obter mais informações sobre como usar o Repositório de Objetos.
O Repositório de Objetos pode impactar significativamente a facilidade e a eficiência na construção de automações de IU. No entanto, para aproveitar ao máximo esse recurso, você pode incorporar elementos do Repositório de Objetos num projeto de biblioteca separado que também inclua todas as interações de IU a serem construídas. Isso permite construir projetos que não contêm nenhuma interação de IU e incluir apenas a lógica dasautomações.
Recomendamos a construção de uma biblioteca para cada aplicativo que você planeja automatizar e a inclusão de todas as interações de IU e elementos do Repositório de Objetos nela. A atividade da biblioteca pode então ser chamada de um arquivo de fluxo de trabalho que faz parte da camada lógica (o projeto principal). Isso garante que:
- Alterações na interação da IU não afetarão a lógica do aplicativo. Isso pode ser comparado à separação entre modelo/exibição/controlador. Em nosso caso, a camada do modelo está preocupada principalmente com os dados passados do controlador para a exibição.
- Assim que uma biblioteca é publicada e um pacote é criado, eles podem ser referenciados em diferentes projetos sem precisarem ser reescritos toda vez e sem a necessidade de usar o copiar e colar entre vários projetos. Se uma alteração ocorrer na interação da IU, a biblioteca pode ser atualizada, uma nova versão pode ser publicada e todos os projetos podem ser atualizados para usar a versão mais recente. Além disso, as alterações que venham a ocorrer na camada de lógica não afetarão a interação da IU.
- Como o Orchestrator pode armazenar várias versões da mesma biblioteca, se uma versão anterior precisar ser usada novamente, ela poderá ser facilmente recuperada. Dessa forma, diferentes versões da mesma biblioteca podem ser usadas em projetos diferentes, e um único projeto de automação pode alternar instantaneamente entre diferentes versões da mesma biblioteca.
Usando essa metodologia, o projeto de automação principal (o controlador) conterá toda a lógica dependente do processo e interagirá com a IU através do uso dos fluxos de trabalho dentro da biblioteca (o que pode ser interpretado como uma pseudoexibição). Por fim, o modelo é representado pelos argumentos que nos ajudam a passar dados entre esses dois componentes.
Siga estas etapas para criar uma biblioteca de IU conforme descrito acima:
1. Analise seu processo e o divida nas etapas que ele contém
Recomendamos criar um diagrama de fluxo para visualizar o processo.
2. Atribua cada uma das etapas a uma categoria
Com base na camada a que pertence, atribua cada etapa à categoria camada de GUI ou à categoria camada de lógica. Por exemplo:
-
Atribua etapas como Clicar, Digitar e Obter Texto à camada de interação com a GUI.
Dica: não adicione atividades únicas na biblioteca; adicione apenas ações mais complexas, como clicar até algo aparecer na IU, percorrer todas as páginas de uma tabela e extrair todas as colunas, ou uma ação mais complexa como fazer login, que consiste em várias partes de interação com a GUI. Como uma regra geral, cada componente que você adiciona a uma biblioteca deve ser uma ação, uma parte mais complexa da automação envolvendo várias atividades, em vez de uma única atividade de automação de IU.
- Atribua ações como o processamento de arquivos, a validação e filtragem de dados ou a manipulação de exceções de negócios à camada de lógica. Não se esqueça de que a camada de lógica deve chamar a camada de GUI para executar suas etapas.
3. Crie uma biblioteca separada para cada aplicativo usado na automação
4. Preencha e publique as bibliotecas de IU
Para cada biblioteca que você criar, faça o seguinte:
-
Crie o objeto do aplicativo e as telas necessárias no Repositório de Objetos.
-
Para cada tela no Repositório de Objetos, crie os elementos necessários e construa seus descritores.
Observação: se você não puder usar o Repositório de Objetos, siga o mesmo procedimento, mas pule as duas etapas anteriores (4-1 e 4-2). -
Desenvolva um arquivo XAML para cada ação necessária. Como telas e elementos podem ser adicionados à medida que novos arquivos de fluxo de trabalho são criados, esta etapa pode ser realizada de forma intercambiável com as duas anteriores.
Por exemplo, estes são alguns dos componentes criados para automatizar os Processos de teste do Acme.
- Publique a biblioteca no Orchestrator ou num feed local do NuGet.
5. Instale as bibliotecas nos seus projetos de automação
Instale as bibliotecas necessárias na janela Gerenciar Pacotes para adicioná-las como dependências do projeto. Cada fluxo de trabalho dentro das bibliotecas está disponível como uma atividade no painel Atividades. Você pode as arrastar e soltar no fluxo de trabalho do projeto e as usar da mesma maneira que usaria qualquer atividade.
Argumentos
- Argumentos de nome usando o padrão PascalCase. Esse é o padrão usado para parâmetros de atividades em bibliotecas do UiPath Studio.
-
Não inclua prefixos
in_
,out_,
io_` nos nomes de argumentos, porque aparecerão como propriedades das atividades na biblioteca.Por exemplo, os argumentos podem ser como na imagem abaixo. Analisando seu componente publicado, você pode ver que os argumentos já estão separados em diferentes categorias com base no seu tipo, ou seja, adicionar o prefixo seria redundante.
- Todos os fluxos de trabalho dentro de uma biblioteca de GUI que abrem/iniciam o aplicativo para automatizar (por exemplo, uma atividade que abre e faz login no aplicativo) devem retornar a janela do aplicativo resultante usando um argumento de saída do tipo UiPath.Core.UiElement para a experiência moderna de design, ou UiPath.Core.Window ou UiPath.Core.Browser para a experiência clássica. Além disso, para ambas as experiências, todas as outras atividades no pacote devem ter um argumento do tipo UiPath.Core.Window ou UiPath.Core.Browser que indica a janela correta em que a ação atual deve ser executada. Isso é extremamente útil se várias instâncias de um aplicativo forem abertas durante o tempo de execução dos processos. Se você estiver usando a experiência de design clássica, não envie seletores como argumentos.
O desenvolvimento de uma biblioteca de componentes de automação para o site do ACME (você pode baixar uma biblioteca de exemplo abaixo) requer um componente para abrir o navegador e executar a operação de login. Essa atividade deve receber como argumentos o nome de usuário, senha, URL do site e retornar o elemento Navegador. Como alternativa, para suportar um cenário em que o login ocorre em uma janela já existente, o navegador pode ser enviado como um argumento In/Out.
O elemento Navegador é do tipo UiPath.Core.UiElement:
Os argumentos devem se parecer com isto:
Ao construir o fluxo de trabalho que abre o navegador (por exemplo, o fluxo de trabalho Login), você deve primeiro verificar se o argumento Navegador é nulo e, caso o seja, deve abrir <https://acme-test.uipath.com/> num novo navegador num fluxo de trabalho separado:
Após o login ser executado e o elemento Navegador ser transmitido de volta para o processo, todas as outras atividades dessa biblioteca necessitarão desse parâmetro. Por exemplo, a atividade que baixa todas as faturas do site terá os seguintes parâmetros:
Se um navegador válido não é transmitido a essa atividade, a execução resulta num erro.
Tratamento de Erro
- Dentro de uma biblioteca, sempre gere erros conforme aparecem — não os sinalize por meio de argumentos de saída.
- No final de um componente de biblioteca, recomendamos a validação do seu resultado. Verifique se a ação desejada ocorreu e gere uma exceção caso não tenha acontecido.
Exemplo
false
, isso significa que o processo de autenticação não foi bem-sucedido e uma exceção será gerada:
Estrutura e nomenclatura
Se você criar um componente para cada atividade, sua biblioteca ficará muito grande muito rapidamente. Para permitir que seus desenvolvedores as identifiquem com facilidade no painel Atividades, é essencial definir um padrão de nomenclatura para os seus componentes. O padrão que recomendamos para nomear componentes é {Ação} {Entidade Usada pela Atividade}. Esse padrão:
- Permite que os desenvolvedores pesquisem um componente por seu nome, pela ação executada por essa atividade ou pela entidade usada durante essa ação.
- Facilita o entendimento de para que o componente pode ser usado e com que páginas do aplicativo ele interage.
Em alguns caso, você pode usar simplesmente {Ação}. Você pode fazer isso se a ação não é executada em uma entidade (por exemplo, Login). Se precisar fornecer mais informações usando o nome, adicione a ele mais atributos separados por espaços.
Além disso, recomendamos criar uma estrutura de pastas dentro do projeto da biblioteca e agrupar os componentes semelhantes na mesma pasta. Uma boa regra geral é ter uma pasta para cada entidade principal com a qual você interage dentro da camada de GUI. Se houver um grande número de entidades com as quais você pode interagir em um aplicativo, uma estrutura de pastas em várias camadas pode ser usada. Isso melhora muito a coesão da sua biblioteca e facilita a visualização das ações possíveis para cada entidade.
Você pode nomear as pastas usando o nome da entidade com a qual os componentes interagem {Entidade Usada pela Atividade} ou a atividade geral que realiza a {Ação}. Por exemplo, se você deseja criar uma pasta na qual vai armazenar todos os componente que navegam pelas páginas de um aplicativo Web, você pode chamá-la de Navegação.
Uma convenção de nomenclatura também precisa ser aplicada às entidades do Repositório de Objetos, como telas e elementos, preferencialmente a mesma usada para fluxos de trabalho e pastas, PascalCase.
Exemplo
O site do ACME (https://acme-test.uipath.com/) contém várias páginas que permitem que usuários interajam com entidades, como Itens de Trabalho, Verificações, Contas, Fornecedores, Faturas etc.
Ao criar uma biblioteca com componentes que interagem com os itens mencionados acima no site do ACME, você pode criar uma estrutura de pastas e nomear os fluxos de trabalho na biblioteca como na imagem abaixo:
Em projetos de automação maiores, diversos componentes dentro de uma biblioteca podem ter um código muito semelhante ou mesmo idêntico. Nesse caso, você deve isolar esse componente em um fluxo de trabalho separado e, se não quiser que esse fluxo de trabalho seja acessível de fora da biblioteca, marque-o para ser ignorado da publicação para torná-lo privado.
Além disso, é possível que a mesma lógica precise ser implementada entre vários processos. Nesse caso, a peça de lógica reutilizável deve ser isolada em uma biblioteca separada.
O diagrama a seguir fornece um resumo geral de como pode ser uma solução como essa:
- Crie apenas uma camada sem interferir com a outra.
- Reutilize código existente sem precisar reescrevê-lo toda vez que é usado.
- Altere facilmente a interação com a IU quando uma atualização ocorre no aplicativo e envie a mudança para todos os processos usando a biblioteca sem precisar republicá-los.
- Compartilhar a camada de interação com a IU entre vários processos significa que o mesmo módulo é testado mais cuidadosamente e que qualquer correção pode ser feita para todos os processos ao mesmo tempo, o que resulta em automações bastante robustas e confiáveis.
- Ter uma biblioteca de interação com a GUI dedicada facilita a construção de projetos dedicados com o Testar Automação para testar a automação de IU para aplicativos específicos, garantindo assim que o código pode ser facilmente testado e que alterações problemáticas sejam detectadas rapidamente.
Para exemplificar a criação e o uso de uma biblioteca usando o Repositório de Objetos, criamos um caso de uso com o aplicativo Web do ACME.
A biblioteca Acme_ObjectRepository contém todas as atividades de automação do ACME. Apesar de a biblioteca ser um módulo focado na interação com o aplicativo Web ACME, ela também é modularizada e organizada em múltiplas pastas baseadas em sua finalidade:
Aqui está um detalhamento rápido dos componentes da biblioteca:
-
Login Acme.xaml — faz login no aplicativo. Contém os seguintes argumentos:
- Quatro argumentos de entrada (URL, Nome de Usuário, Senha, TempoLimiteDesejado).
-
O argumento In/Out do Navegador do tipo UiPath.Core.UiElement. Esse componente se anexará a qualquer janela do ACME que já esteja aberta, ou abrirá uma nova janela de navegador se nenhuma estiver aberta e executará o login. O parâmetro do navegador retornará a janela do navegador e essa variável será transmitida para todos os componentes da biblioteca.
- Logout Acme.xaml — invoca o fluxo de trabalho Navegar para a página inicial do módulo Navegação e, em seguida, finaliza a sessão atual.
-
Módulo Opções do Usuário — contém as opções que podem alterar as configurações da conta atual dentro do aplicativo Web do ACME.
- Reset test data.xaml — redefine os dados de teste usados no aplicativo do ACME.
-
Módulo Faturas — contém as ações executadas nas faturas encontradas nos dados de teste.
- Download all invoices.xaml — extrai todos os itens da tabela de faturas dentro do aplicativo e os devolve como um
DataTable
. - Download invoices by vendor tax ID.xaml — navega por toda a tabela de faturas até encontrar uma fatura com um ID de tributação específico, que é retornada.
- Download all invoices.xaml — extrai todos os itens da tabela de faturas dentro do aplicativo e os devolve como um
-
Módulo Navegação — contém fluxos de trabalho que navegam pelas diferentes páginas do aplicativo Web.
- Os componentes deste módulo são usados principalmente por outros fluxos de trabalho da biblioteca e geralmente não devem ser invocados diretamente do processo principal. No entanto, eles estão marcados como Publicáveis porque podem ser úteis em processos assistidos onde pode ser interessante o robô navegar até uma página específica para, em seguida, permitir que o usuário interaja com o aplicativo.
-
Módulo Itens de Trabalho — contém as ações que ocorrem nos itens de trabalho encontrados no aplicativo.
- Download all work items.xaml — baixa todos os itens de trabalho nos dados de teste.
O projeto principal AcmeProcess_ObjectRepository é composto de quatro casos de uso diferentes. Ele requer que o usuário crie uma credencial do Windows do tipo Genérica chamada ACMETest, que salva o nome de usuário e a senha com os quais o robô fará login no aplicativo Web do ACME.
Os componentes do caso de uso deste processo realizam várias tarefas usando os múltiplos componentes construídos na biblioteca Componentes de IU do ACME.
Quando o fluxo de trabalho Main.xaml é invocado, o robô faz login no aplicativo do ACME, em seguida, uma caixa de diálogo solicita que o usuário selecione um dos casos de uso e, então, o robô invoca o fluxo de trabalho corresponde à escolha do usuário:
O projeto de teste Test_UiPath.AcmeProcess_ObjectRepository consiste em cinco casos de teste diferentes que testam diferentes funcionalidades do processo: login/logout, baixar todas as faturas / baixar faturas por id de tributação do fornecedor, baixar itens de trabalho.
- Princípios gerais
- Separação em conceitos
- Responsabilidade única
- Aproveitando o Repositório de Objetos
- Como escalar combinando bibliotecas de fluxo de trabalho e o Repositório de Objetos
- Publicando uma biblioteca de IU
- Melhores práticas
- Abordagem para soluções maiores
- Benefícios
- Projetos de exemplo
- Biblioteca
- Processo
- Projeto de teste