"Não adianta! Não consigo fazer um teste ponta a ponta com os testes de integração do Flutter", exclamou um de nossos clientes há cerca de 9 meses. Perguntei qual era o problema e eles explicaram que estavam usando o Google Authentication para fazer login e usaram o pacote google_sign_in , mas não foi possível usar os testes de integração do Flutter para interagir com as telas de login. Eu ainda não entendi muito bem qual era o problema e então cliquei: este plugin usa componentes de UI nativos com os quais os testes de integração não funcionam.
Fiquei bastante desapontado por não poder oferecer uma solução na época e tive que deixar por isso mesmo. No entanto, avançando até hoje, uma nova solução incrível se apresentou, chamada "Patrol" por
Uma das principais razões pelas quais as equipes de desenvolvimento usam serviços de integração contínua (CI), como
Existem quatro métodos principais de teste que podem ser automatizados como parte do seu fluxo de trabalho de CI. O teste é um tópico em si, então serei breve, mas usar uma combinação desses métodos de teste ajudará você a melhorar a qualidade do seu aplicativo e detectar problemas mais cedo ou mais tarde.
Em primeiro lugar, existe o "teste de unidade" , que é comumente usado para testar suas funções e métodos isoladamente para garantir que funcionem conforme o esperado. Testes unitários também podem ser escritos para garantir que sua lógica de negócios funcione em diferentes cenários sem resultados inesperados.
A seguir, temos os "testes de widget" do Flutter, que permitem testar seus componentes de IU e garantir que eles sejam renderizados corretamente e funcionem conforme o esperado.
Depois, há o "teste de integração" , onde você testa se as unidades e componentes do seu aplicativo funcionam juntos conforme o esperado.
Finalmente, há o "teste de UI ponta a ponta" , onde você testa o aplicativo como se estivesse sendo usado por um usuário real. Em um fluxo de trabalho de CI, isso geralmente é automatizado usando simuladores ou emuladores para testar diferentes caminhos em seu aplicativo para garantir que não haja problemas após você fazer alterações em seu código.
É aqui que o cliente de quem falei no início ficou preso porque não conseguiu executar os testes de IU ponta a ponta porque não foi possível fazer login no aplicativo. Na época eles testaram uma versão ‘dev’ que contornava a parte de login.
No entanto, isso não é mais necessário agora que "Patrol" está disponível!
Então, antes de mais nada, o que é Patrulha? Bem, acho que os documentos dizem melhor:
Patrol é uma estrutura de teste de UI nova e de código aberto para Flutter desenvolvida pela LeanCode. Ele se baseia nas ferramentas de teste existentes do Flutter para permitir que você faça coisas que antes eram impossíveis. Patrol permite acessar recursos nativos da plataforma em que o aplicativo Flutter está sendo executado.
A parte mais importante aqui é que ele permite acessar os recursos nativos da plataforma em que seu aplicativo Flutter está sendo executado.
Isso significa que agora você pode fazer coisas como:
Ok, isso parece ótimo, mas qual é o truque?
Bem, não há um! E mais, não é apenas gratuito , mas também
Além disso, o Patrol também apresenta 'localizadores personalizados' que fornecem uma sintaxe mais concisa para escrever seus testes. Você pode ler mais sobre eles
Para começar a usar o Patrol, você precisará instalar a CLI, adicionar a dependência do Patrol ao seu pubspec.yaml e definir algumas configurações em seus projetos iOS e Android.
LeanCode criou uma ótima documentação
Se você tiver algum problema, o melhor lugar para obter ajuda é no servidor Patrol Community Discord , no qual você pode ingressar
Se você encontrar algum bug, poderá levantar um problema
Para começar a usar o Patrol, você precisará instalar a CLI, adicionar a dependência do Patrol ao seu pubspec.yaml e definir algumas configurações em seus projetos iOS e Android.
LeanCode criou uma ótima documentação
Se você tiver algum problema, o melhor lugar para obter ajuda é no servidor Patrol Community Discord , no qual você pode ingressar
Se você encontrar algum bug, poderá levantar um problema
Agora que está tudo pronto, vamos começar a testar alguns recursos nativos. Para experimentar sozinho, configurei um aplicativo Flutter simples com um botão elevado que, quando clicado, abre uma caixa de diálogo de alerta nativa .
Clicar em “OK” ou “Cancelar” simplesmente descarta a caixa de diálogo.
Novamente, eu recomendaria usar a documentação do próprio Patrol, que você pode encontrar
Então, para o meu teste, eu queria clicar no botão elevado que contém o texto "Clique em mim!". É um widget Flutter padrão, portanto pode ser tocado usando o seguinte localizador de patrulha:
await $('Click me!').tap();
A caixa de diálogo nativa deve então ser exibida, para que possamos começar a interagir com um componente de UI nativo. Então, vamos adicionar o localizador nativo que nos permitirá tocar no botão "OK":
await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK'));
Essa foi fácil! Também quero testar o botão "Cancelar", então vamos tocar no botão "Clique em mim!" botão novamente e, em seguida, toque no botão "Cancelar" da caixa de diálogo nativa adicionando mais algumas linhas da seguinte maneira:
await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'Cancel'));
Seu arquivo de teste concluído deve ficar assim:
import 'package:cmpatrol/main.dart'; import 'package:patrol/patrol.dart'; void main() { patrolTest( 'Native tests', nativeAutomation: true, ($) async { await $.pumpWidgetAndSettle(const MyApp()); await $('Click me!').tap(); await $.native.tap(Selector(text: 'OK')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'Cancel')); await $('Click me!').tap(); await $.native.tap(Selector(text: 'NO')); }, ); }
Agora você deve conseguir executar esse teste em seu emulador ou em um dispositivo real usando o comando para iniciar o teste. Meu arquivo de teste de integração se chamava "button_test" , então iniciei os testes no Terminal da seguinte maneira:
patrol test -t integration_test/button_test.dart
Você verá se seus testes foram aprovados ou reprovados diretamente no Terminal. Se os testes falharem, você receberá um link para o relatório de teste completo. Como alternativa, se você estiver executando seus testes no Android como eu fiz, você poderá acessar o relatório clicando em index.html no seguinte diretório:
./build/app/reports/androidTest/connected
Você pode experimentar outros recursos nativos, como abrir a bandeja de notificações, desativar o wifi, ativar o modo escuro, minimizar e maximizar o aplicativo:
// minimize app await $.native.pressHome(); await $.native.openNotifications(); await $.native.disableWifi(); await $.native.enableDarkMode(); // maximize app await $.native.openApp();
⚠️ Observe que não é possível fechar completamente seu aplicativo e reabri-lo, pois isso encerraria todo o teste e, portanto, faria com que ele falhasse.
Consulte a Patrulha
Para incorporar o Patrol em seus fluxos de trabalho, primeiro você terá que instalar o Patrol CLI na máquina de construção. Isso leva apenas alguns segundos e, uma vez feito isso, você pode executar seu script de teste. Abaixo está um exemplo de como você adicionaria essas etapas à seção "scripts" do seu arquivo de configuração codemagic.yaml . Eu recomendaria executar o script para instalar o Patrol CLI como uma das primeiras etapas do script e então você pode executar seus testes Patrol imediatamente depois disso ou após qualquer outro teste que você também queira executar anteriormente.
Antes de executar os testes do Patrol, você precisará iniciar o emulador, então adicionaremos um script para iniciar o emulador e esperar que ele seja totalmente inicializado. Observe que os emuladores Android não estão disponíveis em máquinas que usam máquinas Apple Silicon M1 ou M2 devido ao Apple Virtualization Framework não oferecer suporte à virtualização aninhada. Portanto, eu recomendaria usar uma instância Linux ao testar aplicativos Android.
A seção de scripts do seu codemagic.yaml deve ser semelhante a esta:
scripts: ... - name: Install Patrol CLI script: dart pub global activate patrol_cli - name: Launch Android emulator script: | cd $ANDROID_HOME/tools emulator -avd emulator & adb wait-for-device - name: Run tests with Patrol script: patrol test -t integration_test/your_test.dart ignore_failure: true ...
Os resultados do teste Patrol também estão disponíveis no formato JUnit XML , o que significa que podem ser exibidos nos logs de construção na tela de visão geral de construção do Codemagic. Você só precisa adicionar a propriedade test_report no caminho para o arquivo JUnit XML que é gerado. Você pode usar a propriedade ignore_failure com um booleano para controlar se deseja que o restante do fluxo de trabalho continue em execução ou não. Se quiser fazer upload de seus resultados para um sistema de gerenciamento de testes conforme descrito na próxima seção, você deve definir isso como true .
Aqui está um exemplo de como seu script deve ser:
scripts: ... - name: Run tests with Patrol script: | patrol test -t integration_test/your_test.dart test_report: build/app/outputs/androidTest-results/connected/*.xml ignore_failure: true ...
Um teste com falha pode ser algo assim:
Uma coisa adicional que você pode querer fazer é reunir a saída do relatório de teste como um artefato de construção para poder visualizar o relatório completo caso ocorra algum erro. Isso disponibilizará o relatório para download como um arquivo zip na tela de visão geral da construção, na seção "Artefatos" no lado esquerdo. A maneira mais fácil de fazer isso é copiar o diretório em que os arquivos de relatório estão para o diretório que o Codemagic usa para exportar artefatos. Há uma variável de ambiente integrada chamada $CM_EXPORT_DIR que faz referência a este diretório que você pode usar em seu script.
O script para fazer isso deve ser assim:
scripts: ... - name: Export Patrol test report script: | cp -r build/app/reports/androidTests/connected $CM_EXPORT_DIR/report ...
O Patrol finalmente superou o problema de execução de testes de UI e integração que envolvem recursos nativos. Agora é possível testar recursos nativos e interagir com fluxos de autenticação, diálogos nativos e até mesmo alternar recursos nativos como wifi, celular, modo escuro e até mesmo minimizar e maximizar seu aplicativo. Além disso, é gratuito e de código aberto e fornece uma solução para um problema real que existe desde o lançamento do Flutter. Além do mais, é fácil adicioná-lo e usá-lo em seus fluxos de trabalho Codemagic. Se você quiser apoiar o excelente trabalho que o LeanCode está fazendo, dê um like no Patrol em pub.dev
Este artigo foi escrito por Kevin Suhajda, chefe de engenharia de soluções da
Também publicado aqui .