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:
client.dartclient_type.dartclients.darttypes.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: '[email protected]',
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:
- a partir da linha 9, o grupo de testes de cliente
- a partir da linha 29, o grupo de testes de tipos
No primeiro grupo, criamos o cliente kako. Seu nome é "Kako", seu e-mail é "[email protected]" e seu tipo é "Gold", com o ícone de uma estrela:
// ...
void main() {
group('Clients Test', () {
final kako = Client(
name: 'Kako',
email: '[email protected]',
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.