Olá, pessoal! Meu nome é Ricarth Lima e serei a pessoa instrutora em mais um curso no maravilhoso mundo do Flutter.
Audiodescrição: Ricarth é um homem de pele dourada com cabelo crespo. Tem o rosto oval com olhos castanhos escuro e nariz e boca largos. Tem uma barba curta e usa óculos de armação retangular preta. Está com uma camisa de cor azul-marinho com o logo Alura.
Agora que já nos conhecemos, boas-vindas ao curso de testes de integração com Flutter!
Para este curso, será utilizado novamente o Listin, conhecido das formações de Flutter. Se você não conhece o Listin, ele é um projeto de gerenciamento de compras, útil para quando você vai fazer compras mensais ou semanais.
Podemos criar uma nova lista contendo os produtos e adicionar novos produtos a ela. Uma das características mais interessantes do listin é que ele mostra o total previsto para a compra quando um produto é marcado como comprado.
No entanto, não criaremos telas nem lógicas para esse aplicativo neste projeto, o que é uma situação bastante comum. É como se uma equipe diferente tivesse entregue o aplicativo já pronto para nós, e agora vamos cobri-lo com testes de integração.
Para fazer isso, precisamos ter uma boa base de Dart (linguagem de programação), Flutter e testes de unidade de widget no Flutter.
Vamos começar o curso para praticar.
Até lá!
Agora que nos conhecemos, precisamos discutir alguns pontos importantes para tornar o curso o mais agradável possível.
As versões das ferramentas que estamos usando podem variar. Por exemplo, estou usando o PowerShell (terminal de comando), mas poderia ser qualquer terminal aberto, e irei rodar um Flutter para verificar a versão.
flutter --version
Estou usando a versão Flutter 3.19.6
e o Dart 3.3.4
para gravar. Idealmente, você deve ter, pelo menos, essa versão ou uma superior. No entanto, o ideal seria que usássemos a mesma versão tanto de Dart quanto de Flutter para evitar problemas.
Logo em seguida, em uma atividade, será explicado como transformar a sua versão para essa versão específica. Se você estiver com uma versão muito antiga, pode simplesmente rodar um flutter upgrade
em qualquer terminal, e isso funcionará. No meu caso, não farei isso agora.
Depois de resolver a questão da versão do Flutter, vamos analisar o projeto. Fechamos o PowerShell e abrimos o projeto. Teclamos "Ctrl + B" para abrir o explorador do lado esquerdo, clicamos o arquivo pubspec.yaml
, porque esse projeto já está funcionalmente pronto.
Muitas coisas já estão instaladas: vários pacotes estéticos, pacotes relacionados ao Firebase e pacotes do curso anterior de teste. Cada um deles tem uma versão indicada ao lado direito de sua linha, que você idealmente deve seguir.
Se precisar, pode pausar o vídeo, mas as versões já estarão definidas no arquivo, dentro do pacote que entregaremos na atividade "Preparando o ambiente".
Outro detalhe muito importante: ao contrário do último curso, onde usamos o Listin para testes, é obrigatória a configuração do Firebase na sua máquina e no seu projeto. Caso contrário, você não conseguirá avançar. Isso significa que há arquivos de configuração específicos do Firebase que você precisa configurar com o seu próprio projeto Firebase. Caso contrário, você estará conectando-se com o meu projeto.
Se eu pressionar "Ctrl + B", ao abrir o arquivo .gitignore
, os últimos arquivos listados são ignorados pelo Git. Esses arquivos estão relacionados ao Firebase com a minha configuração. Portanto, preciso que você faça isso na sua configuração também.
.gitignore
// comentário omitido
# Firebase
android/app/google-services.json
ios/firebase_app_id_file.json
ios/Runner/GoogleService-Info.plist
lib/firebase_options.dart
firebase.json
Você pode estar se perguntando se este é um curso de testes de integração ou um curso sobre Firebase. Este não é um curso sobre Firebase, mas é uma questão comum no dia a dia da pessoa desenvolvedora. Frequentemente, você precisará testar aplicações que já utilizam outras dependências.
No caso, o servidor utiliza Firebase. Portanto, é necessário configurar o Firebase para realizar testes mais abrangentes na aplicação.
Leia a atividade "Configurando o Firebase" e siga os passos para configurá-lo no seu projeto.
Agora que tudo está alinhado, começamos a trabalhar. Já discutimos sobre o projeto e suas versões, então configuramos o projeto atual para suportar testes de integração.
Para isso, abrimos o VSCode e fechamos o arquivo .gitignore
, pois não precisaremos mais dele.
No canto inferior esquerdo, localizamos o arquivo pubspec.yaml
e pressionamos "Ctrl + B" para fechar o Explorer. Analisaremos as dependências de desenvolvimento.
pubspec.yaml
# código omitido
# Dependências de desenvolvimento
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.2
test: ^1.24.9
mockito: ^5.4.4
build_runner: ^2.4.9
# código omitido
É nessa seção que inserimos o pacote de testes de integração.
Após o dev_dependencies
, pressionamos "Enter" e adicionamos integration_test:
. Mas não era só colocar aquele flutter pubmed integration test
com a tag de dev
e rodar? Não exatamente.
Este pacote não é como aqueles que encontramos no pub.dev
. Ele se assemelha mais ao flutter_test
. Observe nas linhas 30 e 31 que o flutter_test
é um pacote que vem incluído quando criamos um projeto Flutter. No caso do integration_test
, não é assim.
Qual é a diferença? O integration_test
não possui um número de versão específico, como flutter_lints
, test
ou mockito
, porque já está integrado ao SDK do Flutter. Só precisamos habilitá-lo neste projeto.
integration_test
Para fazer isso, na linha 29, teclamos "Enter". Assim como no flutter_test
, inserimos sdk: flutter
.
# código omitido
# Dependências de desenvolvimento
dev_dependencies:
integration_test
sdk: flutter
flutter_test:
sdk: flutter
flutter_lints: ^3.0.2
test: ^1.24.9
mockito: ^5.4.4
build_runner: ^2.4.9
# código omitido
Note que há uma pequena diferença: não estamos passando um número de versão. A versão da dependência de teste de integração está diretamente relacionada à nossa versão do SDK do Flutter. Por isso, é crucial que tenhamos versões semelhantes ou idênticas.
Ao salvar agora, ele executará o flutter pub get
automaticamente. Se tudo estiver correto, nenhum erro ocorrerá e pronto.
Nossa aplicação está preparada para os testes de integração!
Com tudo configurado, realizaremos o primeiro teste.
Primeiro, é necessário pensar em qual será o teste. Com o emulador aberto, um bom teste inicial para o fluxo de testes de integração é a tela inicial que aparece ao abrir o Listin.
Essa tela permite que a pessoa usuária entre com uma conta ou faça o cadastro. Precisamos verificar se o fluxo de mudança de entrar para cadastrar está funcionando corretamente.
integration_test
Com o emulador aberto, vamos para o VSCode e fechamos o arquivo pubspec.yaml
. Fechamos a main.dart
também, por enquanto. Pressionamos "Ctrl + B" para abrir o explorador e criamos uma nova pasta para os testes de integração.
Os testes de integração não ficam na pasta test
.
O recomendado é ter uma pasta separada para os testes de integração.
Portanto, criamos a nova pasta na raiz do projeto, fora da lib
. Selecionamos a raiz do projeto e criamos a nova pasta clicando no segundo ícone de pasta na parte superior esquerda que representa "New folder" ("Nova pasta").
Escrevemos integration_test
e teclamos "Enter".
app_test.dart
Dentro desta pasta, criamos um arquivo chamado app_test.dart
. Para isso, clicamos com o botão direito sobre a pasta e escolhemos a opção "New File", digitamos o nome desejado e teclamos "Enter".
No arquivo app_test
podemos fazer os testes de integração.
app_test.dart
Primeiro, adicionamos as importações. Na linha 1, escrevemos import
e importamos integration_test
. Ao digitarmos, será exibido um menu flutuante em que iremos buscar pelo "integration_test/integration_test".
app_test.dart
import "package:integration_test/integration_test.dart";
Logo após, digitamos void main() {}
:
import "package:integration_test/integration_test.dart";
void main() {
}
Por enquanto, ele está exibindo um erro. Isso acontece às vezes, mas não há nenhum erro real. Ele diz que está esperando um ponto e vírgula e não encontra integration
, mas não é porque escrevemos errado. O problema é que o analisador do Dart (responsável pela verificação) está lento. Isso tem acontecido com frequência, e não sabemos se está relacionado à internet ou à máquina. Se isso acontecer com você, não se preocupe.
Podemos continuar.
Para realizar testes de integração na main()
, digitamos "In" e o VSCode sugeriu IntegrationTestWidgetsFlutterBinding
. Clicamos nesta opção. Em seguida, colocamos um ponto, onde haverá apenas uma opção: ensureInitialized()
("inicialização segura").
import "package:integration_test/integration_test.dart";
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
}
Para realizar testes de integração, é necessário implementar essas alterações na main
.
Logo na sequência, criamos um grupo digitando "group()". No menu flutuante exibido, selecionamos a primeira opção do pacote flutter_test
. Assim, teremos a seguinte estrutura: group("description", () {});
. Em description
digitamos "Fluxo de autenticação".
Dentro das chaves, faremos o primeiro teste.
Digitamos "test" e no menu exibido selecionamos a primeira opção "tet(…) -> void". Assim, obtemos a seguinte estrutura: test("description", () => null)
. Em description
, digitamos "Telas de entrar e cadastrar".
# código omitido
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group("Fluxo de autenticação", () {
test("Telas de entrar e cadastrar", () => null);
});
}
No entanto, há um detalhe muito importante. Nós colocamos test()
, mas lidar diretamente com a tela pode exigir mais do que apenas um teste. Testar unidades dentro da integração funcionaria. Mas, como desejamos interagir efetivamente com a tela, vamos mudar para testWidgets()
. Nesse caso, é necessário ter um tester
e garantir que esse callback seja assíncrono. Alteramos de uma arrow function para uma função normal com chaves "{}
".
A única diferença foi na linha 5, que garantimos uma inicialização segura.
# código omitido
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group("Fluxo de autenticação", () {
testWidgets("Telas de entrar e cadastrar", (tester) async {
});
});
}
Dentro da função, podemos escrever os testes.
Primeiro, subimos o aplicativo com await tester.pumpWidget(MyApp())
. Assim, subimos o MyApp()
inteiro, dado que estamos simulando toda a aplicação. Na linha seguinte, esperamos o app carregar com await tester.pumpAndSettle()
.
# código omitido
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group("Fluxo de autenticação", () {
testWidgets("Telas de entrar e cadastrar", (tester) async {
await tester.pumpWidget(MyApp());
await tester.pumpAndSettle();
});
});
}
Estamos criando um pouco mais rápido devido ao fato de que esses são assuntos já tratados no curso anterior.
Logo na sequência, verificamos se ele acha dois TextFormFields
com o expect(actual, matcher)
, que são o de entrar e o de senha. No actual
digitamos find.byType()
passando TextFormField
.
No matcher
precisamos encontrar dois widgets usando findsNWidgets()
passando o valor 2
. Isso para indicar que é preciso buscar por um número "N" de widgets.
# código omitido
group("Fluxo de autenticação", () {
testWidgets("Telas de entrar e cadastrar", (tester) async {
await tester.pumpWidget(MyApp());
await tester.pumpAndSettle();
expect(find.byType(TextFormField), findsNWidgets(2));
});
});
}
Com essa instrução, estamos verificando se há dois TextFormField
sendo exibidos.
Na sequência, verificamos se há um botão de entrar visível usando o expect()
.
Estamos testando nossa tela real para garantir que os elementos necessários estejam presentes.
Dentro do expect()
digitamos find.text("Entrar")
para buscar por um botão com esse texto. No matcher
inserimos findOneWidget
.
# código omitido
group("Fluxo de autenticação", () {
testWidgets("Telas de entrar e cadastrar", (tester) async {
await tester.pumpWidget(MyApp());
await tester.pumpAndSettle();
expect(find.byType(TextFormField), findsNWidgets(2));
expect(find.text("Entrar"), findsOneWidget);
});
});
}
Ele deve dar aquele clique para mudar de tela. Na tela de entrada, ele passa para a subtela de cadastro. Usaremos await tester.tap()
para buscar o botão diretamente pelo texto usando find.text("")
. Dentro de text("")
passamos Ainda não tem conta?\nClique aqui para cadastrar.
. Dessa forma, ele buscará um botão com esse texto e irá clicar.
Ao clicar, precisamos que a tela carregue mais uma vez. Portanto, usamos await tester.pumpAndSettle();
.
# código omitido
group("Fluxo de autenticação", () {
testWidgets("Telas de entrar e cadastrar", (tester) async {
await tester.pumpWidget(MyApp());
await tester.pumpAndSettle();
expect(find.byType(TextFormField), findsNWidgets(2));
expect(find.text("Entrar"), findsOneWidget);
await tester
.tap(find.text("Ainda não tem conta?\nClique aqui para cadastrar."));
await tester.pumpAndSettle();
});
});
}
Por último, verificamos se agora há quatro TextFormFields
em vez de dois. Para isso, copiamos a linha 15 com "Ctrl + C". Na linha 24, colamos com "Ctrl + V". Agora, em vez de dois, esperamos ver quatro campos. O botão também deve ter mudado de "entrar" para "cadastrar". Copiamos com "Ctrl + C" e colamos na linha 26. Substituímos "Entrar" por "Cadastrar".
# código omitido
await tester
.tap(find.text("Ainda não tem conta?\nClique aqui para cadastrar."));
await tester.pumpAndSettle();
expect(find.byType(TextFormField), findsNWidgets(4));
expect(find.text("Cadastrar"), findsOneWidget);
});
});
}
Agora, podemos rodar os testes.
No entanto, testes de integração não serão executados no ambiente de teste abstrato como fazíamos nos testes de widget e de unidade. Para esses testes, é necessário um emulador.
O teste ocorrerá no emulador para capturar as especificidades de tela, sistema operacional e hardware via teste de integração.
Já que estamos executando a aplicação no emulador, vamos pausá-la clicando no ícone de quadrado na parte superior direita. Ao abrirmos e verificamos no emulador, observamos que está vazio.
Agora, verificamos se funciona. Por estar demorando, voltamos ao VSCode e teclamos "Ctrl + J" para abrir o terminal e clicamos na aba "DEBUG CONSOLE" na parte superior do terminal.
Abrimos o emulador para verificar se funciona.
Na primeira execução pode ser que demore um pouco.
Notamos no terminal que começou a funcionar, aplica o build
, instala e abre o Listin no emulador.
O teste começou a rodar e obtemos uma mensagem:
Exception has occurred.
FirebaseException ([core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()) ("Uma exceção ocorreu. Nenhum aplicativo Firebase '[DEFAULT]' foi criado - chame Firebase.initializeApp()).
Interrompemos o teste clicando no canto superior direito.
Fechamos o terminal com "Ctrl + J" e abrimos o explorador com "Ctrl + B". Navegamos para "lib/main", onde temos a aplicação principal e não no teste. Das linhas 11 a 13 inicializamos o Firebase.
main.dart
# código omitido
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
# código omitido
Precisamos fazer o mesmo no teste de integração. Copiamos com "Ctrl + C". Fechamos a main
e voltamos ao app_test
. Adicionamos isso como um setup, já que precisa acontecer em todos os testes.
Na linha 9, no grupo, digitamos o "setup" e escolhemos a segunda opção: setUp(() => null)
. Transformamos a função de seta em uma função normal com chaves ("{}
") e chamamos o Firebase. Observe que há um sublinhado em vermelho indicando um erro. Para corrigir, colocamos o setUp()
como assíncrono.
app_test
# código omitido
setUp(() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
# código omitido
Além disso, precisamos importar o Firebase. Pressionamos "Ctrl + ponto" sobre Firebase
e o VSCode sugere a importação "import library 'package:firebasecore/firebasecore.dart'".
O mesmo vale para o arquivo de configuração DefaultFirebaseOptions
. Pressionamos "Ctrl + ponto" na linha 13 para importar e selecionamos a opção "import library 'package:flutterlistin/firebaseoptions.dart'".
Salvamos as alterações.
Agora sim, vamos rodar e ver o que acontece.
Mais uma vez, abrimos o "Debug Console" e o emulador. Está parado na tela de listin, devido à inicialização anterior. Mas não tem problema, ele vai fechar e abrir novamente.
Começou a carregar. Fechou e está abrindo o listin novamente. Agora ele deve estar fazendo o setup. Os testes começaram no terminal e abriu a aplicação no emulador, mudou de tela e desapareceu. Ele mudou automaticamente.
Essa é a essência do teste de integração. Não se trata apenas de verificar se as coisas funcionam no ambiente abstrato, mas de executá-las realmente, como se alguém estivesse interagindo. No caso, foi um teste simples para verificar se os TextFormFields
e os botões de entrar e cadastrar estavam conforme o esperado.
Vamos continuar praticando?
O curso Flutter: dominando testes de integração possui 152 minutos de vídeos, em um total de 56 atividades. Gostou? Conheça nossos outros cursos de Flutter em Mobile, ou leia nossos artigos de Mobile.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.