Alura > Cursos de Mobile > Cursos de Flutter > Conteúdos de Flutter > Primeiras aulas do curso Flutter: implementando testes de integração

Flutter: implementando testes de integração

Realizando teste de integração - Apresentação

Boas-vindas ao nosso curso de Flutter: Testes de integração! Meu nome é Caio Couto Moreira, mas você pode me chamar de Kako.

Autodescrição: Sou um homem branco com nariz longo e olhos castanhos esverdeados. Meus cabelos são curtos e cacheados e, no momento, estão pintados de vermelho. Ao fundo, há uma parede com iluminação roxa e rosa.

Para quem é este curso?

Este curso é para pessoas que:

Antes de continuar, vamos conferir a interface do aplicativo de banco que usaremos ao longo deste curso.

O aplicativo

A tela inicial é uma página de clientes em branco. No topo, há uma barra azul com o título "Clientes". No canto esquerdo da barra, há um ícone de menu, que exploraremos em breve.

No canto inferior direito da tela, há um botão flutuante redondo e azul com o símbolo de mais (floating action button). Ao clicar nele, uma caixa de diálogo surgirá no centro da tela com um formulário e podemos preenchê-lo para adicionar um cliente. Como exemplo, vamos adicionar o cliente Kako, informando seu e-mail e o tipo de cliente "Diamond":

Clicando no botão "Salvar" no canto inferior direito do formulário, o cliente "Kako (Diamond)" instantanemente será listado na página de clientes.

A seguir, pressionaremos o ícone de menu no canto superior esquerdo, para abrir o Drawer na lateral esquerda da tela. Esse menu facilitará nossa navegação para outras telas do aplicativo. Nele, temos listados:

Vamos navegar até a tela "Tipos de clientes", onde há uma lista padrão de tipos de clientes:

No canto inferior direito, vamos clicar no floating action button para acessar o formulário de adição de um novo tipo de cliente. Usaremos o nome "Bronze" e selecionaremos o ícone de uma pessoa correndo. Ao pressionar o botão "Salvar" no canto inferior direito, o novo tipo será instantaneamente listado na tela "Tipos de cliente".

Este é o nosso aplicativo! Ele não parece complexo, mas o funcionamento dele requer muitos conhecimentos (inclusive, de gerenciamento). Nosso objetivo será testar esse aplicativo de ponta a ponta, usando testes de integração!

Dica para acompanhar o curso

A melhor forma de estudar este curso é assistir aos vídeos, fazer as atividades e, depois, tentar replicar os resultados por conta própria, sem acompanhar o material. Caso você tenha dúvidas, então você pode voltar ao vídeo para revisar e descobrir quais pontos esqueceu.

Se tiver dúvidas, você pode nos acionar no fórum ou no Discord! O engajamento com outros alunos te ajudará no seu crescimento profissional e no desenvolvimento de habilidades para o mercado de trabalho.

Vamos mergulhar em novo projeto?

Realizando teste de integração - Conhecendo o projeto

Antes de começar a explorar os testes de integração, é importante revisar conceitos sobre testes de unidade e testes de widget. Eles precisam estar bem frescos na nossa memória para conseguirmos produzir testes de integração e entender a importância deles. Além disso, precisamos contextualizar nosso aprendizado. Vamos usar um exemplo concreto, por meio do storytelling.

Você se lembra da Dandara? Ela é nossa persona que conhecia apenas lógica de programação e se propôs a estudar Dart do início, passando por todos os cursos da Formação de Dart.

Ela foi evoluindo seus conhecimentos e também fez todos os cursos de Flutter. Agora, Dandara começou a se inserir no mercado de trabalho como freelancer — isto é, com trabalhos autônomos. Navegando pela internet, ela encontrou uma pessoa que fez o seguinte pedido:

Eu tenho um aplicativo de banco, pronto, bem simples. Eu quero garantir a qualidade do meu aplicativo, desenvolvendo testes. Só que eu não tenho tempo, então posso te pagar para você fazer esses testes para mim. Pode ser?

Assim, a Dandara conseguiu uma demanda, um freela! Então, nossa missão é realizar testes em um aplicativo que já está pronto. Não precisamos implementar novas funcionalidades, apenas garantir que o que foi implementado continue funcionando com a melhor qualidade possível.

Qual será nosso primeiro passo? Explorar o aplicativo e entender como ele funciona! O download dele está disponível na plataforma.

Vale ressaltar que já estamos em um nível mais intermediário de Flutter. Caso necessário, você pode voltar aos cursos anteriores da Formação de Flutter para revisar alguns conteúdos dos quais falaremos adiante.

Explorando o aplicativo

Vamos abrir o Android Studio e usar o emulador para explorar o aplicativo. Ele consiste em apenas duas páginas, com alguns diálogos e algumas informações sendo gerenciadas. Vamos analisá-lo em detalhes, a seguir.

A tela inicial é a página de clientes, atualmente vazia, com o fundo branco:

Página inicial do aplicativo, também chamada de tela de clientes. A descrição é feita na transcrição, a seguir.

No canto inferior direito, temos um floating action button (ou "FAB") azul para adicionar clientes, com o símbolo de mais. No topo, há uma barra azul com o título "Clientes". No canto superior esquerdo, há um ícone de menu.

Ao clicar no ícone de menu, o widget Drawer será aberto na lateral esquerda do aplicativo. Trata-se de um menu para navegação, onde temos listados:

Menu de navegação lateral do aplicativo, também chamado Drawer. Na parte superior, há uma área azul com o título "Menu". Abaixo, há uma área com fundo branco, onde temos a lista de telas navegáveis.

Clicando em "Gerenciar clientes", voltamos para a página inicial de clientes. Clicando em "Tipos de clientes", somos redirecionados para a página "Tipos de clientes". Ou seja, acontece uma navegação, então é importante termos noções de navegação.

Na tela "Tipos de clientes", temos uma lista padrão de tipos sobre um fundo branco:

Tela de tipos de clientes. No topo, há uma barra azul com o título "Tipos de clientes". No canto superior esquerdo, temos o ícone de menu. Na parte principal da tela, temos a lista de tipos. Cada tipo tem um ícone laranja à esquerda. No canto direito inferior, há um botão laranja redondo com símbolo de mais.

No canto inferior direito, há um floating action button (FAB) laranja, para adicionar um novo tipo de cliente. Clicando nesse botão, uma caixa de diálogo (alert dialog) surgirá no centro da tela com um formulário.

Como exemplo, vamos criar um tipo com o nome "Ferro" e selecionar o primeiro ícone — um gift card com um laço na parte superior. Na parte inferior da caixa de diálogo, temos os botões "Salvar" e "Cancelar" Clicando em "Salvar", o tipo "Ferro" será adicionado instantaneamente ao final da lista na tela "Tipos de clientes".

Como a atualização foi instantânea, sabemos que há algum mecanismo que faz nossa tela ser rebuildada quando um tipo de cliente é criado! Ou seja, também é importante termos noções de gerenciamento de estados, mais especificamente, o Provider.

Utilizando o menu lateral, voltaremos para a página de clientes. Atualmente, a tela está vazia, então vamos interagir com o FAB no canto inferior direito para criar um cliente.

Uma caixa de diálogo será aberta no centro da tela, com um formulário para cadastro de novo cliente:

Na parte inferior do formulário, clicaremos no botão "Salvar" e o cliente "Kako (Ferro)" será adicionado instantaneamente à lista. À direita dele, há um ícone que corresponde ao tipo Ferro.

Por fim, vamos acessar o menu lateral e selecionar a opção "Sair". Como esperado, o aplicativo será fechado.

Assim, conseguimos interagir com o aplicativo, conhecer suas funcionalidades e ter um melhor entendimento do projeto como um todo.

O código

Já checamos como o aplicativo funciona no dispositivo, então o próximo passo é explorar o código! Como estamos em um nível intermediário de conhecimento de Flutter e já temos experiência em análise de códigos, recomendamos que você explore o código por conta própria.

Neste vídeo, vamos conferir rapidamente alguns desses arquivos e indicar alguns pontos para serem avaliados.

Na pasta "lib", vamos abrir o main.dart. Esse arquivo possui um MultiProvider, então é importante que tenhamos conhecimentos sobre ele.

Temos também as pastas de telas, componentes e modelos. Como essas telas funcionam, como essas páginas navegam entre si? Será que é por rota, pelo Navigator com os métodos push() e pop()? É um ponto importante para se avaliar.

Na pasta "models", temos os modelos de clientes — como cada um deles funciona, como são adicionados ou modificados. Na linha 4 do arquivo clients.dart, reparamos que ele possui um ChangeNotifier, então é necessário compreender gerenciamento de estados com Provider.

Analisando os arquivos client.dart e client_type.dart, notamos que são modelos simples de informações que vamos manipular.

Portanto, recomendamos que você confira todos os arquivos e leia o código para ter uma ideia de como o projeto funciona. Caso não tenha familiaridade com algum elemento, você pode nos perguntar no fórum!

Após essa avaliação, nossa missão (e a da Dandara) será criar testes que garantam que o aplicativo funcione como deve funcionar! Começaremos com os testes mais simples (os testes de unidade) e depois escalaremos até os testes de integração!

Realizando teste de integração - Criando testes de unidade

Vamos começar com os testes mais fáceis: os testes de unidade.

Além de ser uma boa estratégia começar com o mais e progredir para o mais complexo, os testes de unidade garantem a qualidade da base do aplicativo. Se não garantirmos a base, todo o resto pode desmoronar! Logo, é importante fazer testes de unidade nos modelos do nosso projeto.

Vamos abrir nosso projeto no Android Studio. Na estrutura de arquivos à esquerda, temos uma pasta chamada "models" com quatro modelos:

  1. client.dart
  2. client_type.dart
  3. clients.dart
  4. types.dart

No arquivo client.dart, temos um modelo simples que recebe um nome, um e-mail e um tipo. Essas informações são obrigatórias.

No arquivo clients.dart, temos uma lista de clientes. Nós podemos manipulá-la, adicionando ou removendo clientes de algumas posições da lista.

No arquivo client_type.dart, temos uma classe que recebe um nome e um ícone, correspondente ao tipo do cliente.

No arquivo types.dart, temos uma lista de tipos que podemos manipular, adicionando ou removendo elementos, conforme seu index.

Criando testes de unidade

A seguir, realizaremos testes de unidade nesses modelos. Não vamos fazer o passo a passo desse processo, pois trata-se de um assunto que já estudamos no curso Flutter: aplicando testes de unidade, de Widget e Mocks.

Em vez disso, vamos revisar rapidamente o código já pronto para recapitular como esses testes são estruturados. Na pasta "test", criaremos um arquivo chamado unit_test.dart com o seguinte conteúdo:

import 'package:client_control/models/client.dart';
import 'package:client_control/models/client_type.dart';
import 'package:client_control/models/clients.dart';
import 'package:client_control/models/types.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  group('Clients Test', () {
    final kako = Client(
        name: 'Kako',
        email: 'kako@alura.com.br',
        type: ClientType(name: 'Gold', icon: Icons.star));

    test('Clients model should add new client', () {
      var clients = Clients(clients: []);
      clients.add(kako);
      clients.add(kako);
      expect(clients.clients, [kako, kako]);
    });

    test('Clients model should remove old client', () {
      var clients = Clients(clients: [kako, kako, kako]);
      clients.remove(0);
      clients.remove(1);
      expect(clients.clients, [kako]);
    });
  });

  group('Types Test', () {
    final gold = ClientType(name: 'Gold', icon: Icons.star);

    test('Types model should add new type', () {
      var types = Types(types: []);
      types.add(gold);
      types.add(gold);
      expect(types.types, [gold, gold]);
    });
    test('Types model should remove old type ', () {
      var types = Types(types: [gold, gold, gold]);
      types.remove(0);
      types.remove(1);
      expect(types.types, [gold]);
    });
  });
}

A seguir, vamos conferir esse código por partes.

Da linha 1 a 6, temos todos as importações necessárias para que os testes funcionem — todos os clientes, o material.dart e o flutter_test.dart:

import 'package:client_control/models/client.dart';
import 'package:client_control/models/client_type.dart';
import 'package:client_control/models/clients.dart';
import 'package:client_control/models/types.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

A partir da linha 8, temos o void main(), no qual criamos dois grupos de testes:

No primeiro grupo, criamos o cliente kako. Seu nome é "Kako", seu e-mail é "kako@alura.com.br" e seu tipo é "Gold", com o ícone de uma estrela:

// ...

void main() {
  group('Clients Test', () {
    final kako = Client(
        name: 'Kako',
        email: 'kako@alura.com.br',
        type: ClientType(name: 'Gold', icon: Icons.star));

// ...

O primeiro teste serve para garantir que é possível adicionar um cliente na lista de clientes. Criamos uma variável chamada clients, que é uma lista de clientes Clients(). Inicialmente, a lista está vazia.

Nas linhas 17 e 18, usamos o método add() para adicionar o cliente kako duas vezes. Na linha 19, indicamos que o resultado esperado é que a variável clients tenha dois elementos kako na lista:

// ...

test('Clients model should add new client', () {
    var clients = Clients(clients: []);
    clients.add(kako);
    clients.add(kako);
    expect(clients.clients, [kako, kako]);
});

// ...

O segundo teste serve para garantir que é possível remover clientes. Criamos uma lista de clientes com três clientes kako. Nas linhas 24 e 25, usamos o método remove() para remover os clientes das posições 0 e 1. Por fim, indicamos que o resultado esperado é uma lista com apenas um cliente kako:

// ...

test('Clients model should remove old client', () {
    var clients = Clients(clients: [kako, kako, kako]);
    clients.remove(0);
    clients.remove(1);
    expect(clients.clients, [kako]);
});

// ...

Na sequência, temos o grupo de testes de tipo, que têm lógicas semelhantes às que acabamos de conferir. De início, criamos um tipo chamado "Gold", com o ícone de estrela:

// ...

group('Types Test', () {
    final gold = ClientType(name: 'Gold', icon: Icons.star);

// ...

O primeiro teste checa se é possível adicionar um novo tipo à lista de tipos. Começamos com uma lista vazia e adicionamos o tipo "gold" duas vezes. Depois, indicamos que o resultado esperado é que a lista de tipos tenha dois elementos "gold":

// ...

test('Types model should add new type', () {
    var types = Types(types: []);
    types.add(gold);
    types.add(gold);
    expect(types.types, [gold, gold]);
});

// ...

O segundo teste checa a funcionalidade de remoção de tipos. Criamos uma lista com três tipos "gold"; removemos os elementos das posições 0 e 1; e espera-se que sobre apenas um tipo "gold":

// ...

test('Types model should remove old type ', () {
    var types = Types(types: [gold, gold, gold]);
    types.remove(0);
    types.remove(1);
    expect(types.types, [gold]);
});

// ...

Esses são nossos testes de unidade! Nosso objetivo era passar rapidamente pelo código, então sinta-se à vontade para analisá-lo com calma e em detalhes.

Executando testes de unidade

A seguir, executaremos os testes para conferir se eles passarão. No canto esquerdo da linha 8, vamos clicar no ícone verde de play e selecionar "Run tests in unit_test.dart". Alternativamente, podemos usar o atalho "Ctrl + Shift + F10". No terminal, após alguns segundos, notaremos que os quatro testes passaram!

Vale lembrar que não vamos alterar o projeto! O projeto não é nosso, somos responsáveis apenas por desenvolver os testes!

Para entender melhor, vamos pensar em um exemplo. Vamos supor que a pessoa responsável pelo projeto decidiu alterar o modelo de cliente e inserir um campo booleano obrigatório para informar se a pessoa cliente é canhota ou destra. Por exemplo:

// CÓDIGO DE EXEMPLO

import 'package:client_control/models/client_type.dart';

class Client {
  String name;
  String email;
  ClientType type;
  bool destro;

  Client({
    required this.name,
    required this.email,
    required this.type,
    required this.destro
  });
}

Com essa mudança, os testes que desenvolvemos param de passar. Na linha 10 do arquivo unit_test.dart, a palavra Client fica sublinhada em vermelho como indicação de erro, pois o parâmetro destroé obrigatório, mas não o informamos.

Em outras palavras, caso haja alterações no futuro, os testes nos avisarão se é possível fazer determinadas alterações e garantir que tudo continuará funcionando.

No caso, este foi só um exemplo. Não vamos implementar esse campo no projeto! O arquivo client.dart continua assim:

import 'package:client_control/models/client_type.dart';

class Client {
  String name;
  String email;
  ClientType type;

  Client({
    required this.name,
    required this.email,
    required this.type
  });
}

Portanto, realizamos os testes de unidade. O próximo passo é fazer testes de widget para conferir se tudo está funcionando como esperado.

Sobre o curso Flutter: implementando testes de integração

O curso Flutter: implementando testes de integração possui 141 minutos de vídeos, em um total de 41 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:

Aprenda Flutter acessando integralmente esse e outros cursos, comece hoje!

Plus

De
R$ 1.800
12X
R$109
à vista R$1.308
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

Matricule-se

Pro

De
R$ 2.400
12X
R$149
à vista R$1.788
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Luri, a inteligência artificial da Alura

    Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com Luri até 100 mensagens por semana.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

Matricule-se
Conheça os Planos para Empresas

Acesso completo
durante 1 ano

Estude 24h/dia
onde e quando quiser

Novos cursos
todas as semanas