Como testar um app do Flutter

O Flutter é um kit de ferramentas de IU do Google para criar apps incríveis e nativos para dispositivos móveis, Web e computadores com uma única base de código.

Neste codelab, você criará e testará um app simples do Flutter. Ele usará o pacote Provider (link em inglês) para gerenciar o estado.

O que você aprenderá

  • Como criar testes usando o framework de testes de widgets.
  • Como criar um teste de integração para testar a IU e o desempenho do app usando o pacote integration_test (link em inglês).
  • Como testar classes de dados (provedores) com a ajuda de testes de unidade.

O que você criará

Neste codelab, você começará criando um aplicativo simples com uma lista de itens. Fornecemos o código-fonte para que você consiga pular direto para os testes. O app é compatível com as seguintes operações:

  • Adicionar itens aos favoritos
  • Visualizar a lista de favoritos
  • Remover itens da lista de favoritos

Depois que o app estiver pronto, você criará os seguintes testes:

  • Testes de unidade para validar as operações de inclusão e remoção
  • Testes de widgets para as página inicial e de favoritos
  • Testes de IU e desempenho para o app todo usando testes de integração

GIF do app executado no Android

O que você quer aprender neste codelab?

Ainda não conheço bem o assunto e quero ter uma boa visão geral. Conheço um pouco sobre esse assunto, mas quero me atualizar. Estou procurando exemplos de código para usar no meu projeto. Estou procurando uma explicação de algo específico.

Você precisa de dois softwares para concluir este codelab: o SDK do Flutter e um editor (links em inglês).

É possível completar este codelab usando qualquer um dos seguintes dispositivos:

  • Um dispositivo físico (Android ou iOS) conectado ao computador e configurado para o modo de desenvolvedor.
  • O iOS Simulator, que requer a instalação de ferramentas do Xcode (link em inglês).
  • O Android Emulator, que requer configuração no Android Studio.

Criar um novo app do Flutter e atualizar as dependências

O foco deste codelab é testar um app do Flutter para dispositivos móveis. Você criará rapidamente o app que será testado, usando arquivos de origem que podem ser copiados e colados. O restante do codelab tem o objetivo de ensinar diferentes tipos de testes.

b2f84ff91b0e1396.png Crie um app de modelo simples do Flutter usando as instruções em Primeiros passos com seu primeiro app do Flutter (link em inglês). Nomeie o projeto como testing_app, em vez de myapp. Você modificará esse app inicial para criar o final.

b2f84ff91b0e1396.png No ambiente de desenvolvimento integrado ou no editor, abra o arquivo pubspec.yaml. Adicione as seguintes dependências marcadas como new e salve o arquivo. É possível excluir os comentários para deixar o arquivo mais legível.

pubspec.yaml (link em inglês)

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.3
  provider: ^4.1.3            # new

dev_dependencies:
  flutter_test:
    sdk: flutter
  integration_test: ^1.0.1    # new
  test: ^1.14.4               # new
  1. Clique no botão Pub get no ambiente de desenvolvimento integrado ou, na linha de comando, execute flutter pub get na parte superior do projeto.

Caso isso gere um erro, confira se o recuo no bloco dependencies está exatamente igual ao mostrado acima usando espaços, e não a tecla Tab. Os arquivos YAML são sensíveis a espaços em branco.

Em seguida, você criará o app para testá-lo. O app contém os seguintes arquivos:

  • lib/main.dart: arquivo principal em que o app é iniciado.
  • lib/screens/home.dart: cria uma lista de itens.
  • lib/screens/favorites.dart: cria o layout da lista de favoritos.
  • lib/models/favorites.dart: cria a classe de modelo para a lista de favoritos.

Substituir o conteúdo do lib/main.dart

b2f84ff91b0e1396.png Substitua o conteúdo do lib/main.dart pelo seguinte código:

lib/main.dart (link em inglês)

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:testing_app/models/favorites.dart';
import 'package:testing_app/screens/favorites.dart';
import 'package:testing_app/screens/home.dart';

void main() {
  runApp(TestingApp());
}

class TestingApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<Favorites>(
      create: (context) => Favorites(),
      child: MaterialApp(
        title: 'Testing Sample',
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        routes: {
          HomePage.routeName: (context) => HomePage(),
          FavoritesPage.routeName: (context) => FavoritesPage(),
        },
        initialRoute: HomePage.routeName,
      ),
    );
  }
}

Adicionar a página inicial ao lib/screens/home.dart

b2f84ff91b0e1396.png Crie um novo diretório, screens, no lib e nele crie um novo arquivo chamado home.dart. No lib/screens/home.dart, adicione o seguinte código:

lib/screens/home.dart (link em inglês)

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:testing_app/models/favorites.dart';
import 'package:testing_app/screens/favorites.dart';

class HomePage extends StatelessWidget {
  static String routeName = '/';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Testing Sample'),
        actions: <Widget>[
          TextButton.icon(
            style: TextButton.styleFrom(primary: Colors.white),
            onPressed: () {
              Navigator.pushNamed(context, FavoritesPage.routeName);
            },
            icon: Icon(Icons.favorite_border),
            label: Text('Favorites'),
          ),
        ],
      ),
      body: ListView.builder(
        itemCount: 100,
        cacheExtent: 20.0,
        padding: const EdgeInsets.symmetric(vertical: 16),
        itemBuilder: (context, index) => ItemTile(index),
      ),
    );
  }
}

class ItemTile extends StatelessWidget {
  final int itemNo;

  const ItemTile(
    this.itemNo,
  );

  @override
  Widget build(BuildContext context) {
    var favoritesList = Provider.of<Favorites>(context);

    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: ListTile(
        leading: CircleAvatar(
          backgroundColor: Colors.primaries[itemNo % Colors.primaries.length],
        ),
        title: Text(
          'Item $itemNo',
          key: Key('text_$itemNo'),
        ),
        trailing: IconButton(
          key: Key('icon_$itemNo'),
          icon: favoritesList.items.contains(itemNo)
              ? Icon(Icons.favorite)
              : Icon(Icons.favorite_border),
          onPressed: () {
            !favoritesList.items.contains(itemNo)
                ? favoritesList.add(itemNo)
                : favoritesList.remove(itemNo);
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text(favoritesList.items.contains(itemNo)
                    ? 'Added to favorites.'
                    : 'Removed from favorites.'),
                duration: Duration(seconds: 1),
              ),
            );
          },
        ),
      ),
    );
  }
}

Adicionar a página de favoritos ao lib/screens/favorites.dart

b2f84ff91b0e1396.png No diretório lib/screens, crie outro arquivo chamado favorites.dart. Nesse arquivo, adicione o seguinte código:

lib/screens/favorites.dart (link em inglês)

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:testing_app/models/favorites.dart';

class FavoritesPage extends StatelessWidget {
  static String routeName = '/favorites_page';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Favorites'),
      ),
      body: Consumer<Favorites>(
        builder: (context, value, child) => ListView.builder(
          itemCount: value.items.length,
          padding: const EdgeInsets.symmetric(vertical: 16),
          itemBuilder: (context, index) => FavoriteItemTile(value.items[index]),
        ),
      ),
    );
  }
}

class FavoriteItemTile extends StatelessWidget {
  final int itemNo;

  const FavoriteItemTile(
    this.itemNo,
  );

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: ListTile(
        leading: CircleAvatar(
          backgroundColor: Colors.primaries[itemNo % Colors.primaries.length],
        ),
        title: Text(
          'Item $itemNo',
          key: Key('favorites_text_$itemNo'),
        ),
        trailing: IconButton(
          key: Key('remove_icon_$itemNo'),
          icon: Icon(Icons.close),
          onPressed: () {
            Provider.of<Favorites>(context, listen: false).remove(itemNo);
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text('Removed from favorites.'),
                duration: Duration(seconds: 1),
              ),
            );
          },
        ),
      ),
    );
  }
}

Por fim, criar o modelo Favorites no lib/models/favorites.dart

b2f84ff91b0e1396.png Crie um novo diretório models e nele crie um novo arquivo chamado favorites.dart. Nesse arquivo, adicione o seguinte código:

lib/models/favorites.dart (link em inglês)

import 'package:flutter/material.dart';

/// The [Favorites] class holds a list of favorite items saved by the user.
class Favorites extends ChangeNotifier {
  final List<int> _favoriteItems = [];

  List<int> get items => _favoriteItems;

  void add(int itemNo) {
    _favoriteItems.add(itemNo);
    notifyListeners();
  }

  void remove(int itemNo) {
    _favoriteItems.remove(itemNo);
    notifyListeners();
  }
}

O app está concluído, mas ainda não foi testado.

b2f84ff91b0e1396.png Execute o app clicando no ícone Run 6869d41b089cc745.png no editor. Isso pode demorar um pouco quando o app é executado pela primeira vez. Ele ficará mais rápido nas etapas posteriores. Ele ficará parecido com a seguinte captura de tela:

be938199b599b605.png

O app exibe uma lista de itens. Toque no ícone em formato de coração em qualquer linha para preencher o coração e adicionar o item à lista de favoritos. O botão Favorites na AppBar leva a uma segunda tela que contém a lista de favoritos.

Agora o app está pronto para ser testado. Você dará início aos testes na próxima etapa.

Comece fazendo um teste de unidade do modelo favorites. O que é esse teste? Um teste de unidade verifica se cada unidade individual do software, que geralmente é uma função, executa a tarefa pretendida de modo correto.

Todos os arquivos de teste de um app do Flutter, exceto os testes de integração, são colocados no diretório test.

Remover o test/widget_test.dart

b2f84ff91b0e1396.png Antes de iniciar o teste, exclua o arquivo widget_test.dart. Você adicionará seus próprios arquivos de teste.

Criar um novo arquivo de teste

Primeiro, você testará o método add() no modelo Favorites para verificar se um novo item foi adicionado à lista e se ela reflete essa mudança. Por convenção, a estrutura de diretórios no diretório test imita a do diretório lib e os arquivos Dart têm o mesmo nome, mas com o anexo _test.

b2f84ff91b0e1396.png Crie um diretório models no test. Nesse novo diretório, crie um arquivo favourites_test.dart com o seguinte conteúdo:

test/models/favorites_test.dart (link em inglês)

import 'package:test/test.dart';
import 'package:testing_app/models/favorites.dart';

void main() {
  group('App Provider Tests', () {
    var favorites = Favorites();

    test('A new item should be added', () {
      var number = 35;
      favorites.add(number);
      expect(favorites.items.contains(number), true);
    });
  });
}

O framework de testes do Flutter permite vincular testes semelhantes, que são relacionados entre si, em um grupo. Podem existir vários grupos em um único arquivo de teste destinados a testar partes diferentes do arquivo correspondente no diretório /lib.

O método test() usa dois parâmetros de posicionamento: a description do teste e o callback em que o teste é criado.

b2f84ff91b0e1396.png Teste a remoção de um item da lista. Copie e cole o teste a seguir no mesmo grupo. Adicione o seguinte código ao arquivo de teste:

test/models/favorites_test.dart (link em inglês)

test('An item should be removed', () {
  var number = 45;
  favorites.add(number);
  expect(favorites.items.contains(number), true);
  favorites.remove(number);
  expect(favorites.items.contains(number), false);
});

Executar o teste

b2f84ff91b0e1396.png Se o app estiver em execução no emulador ou dispositivo, feche-o antes de continuar.

b2f84ff91b0e1396.png Na linha de comando, navegue até o diretório raiz do projeto e digite o seguinte comando:

$ flutter test test/models/favorites_test.dart

Se tudo funcionar, você verá uma mensagem parecida com a seguinte:

00:06 +2: All tests passed!

Veja o arquivo de teste completo: test/models/favorites_test.dart (link em inglês).

Para ver mais informações sobre o teste de unidade, acesse Introdução ao teste de unidade (link em inglês).

Nesta etapa, você fará testes de widget. Os testes de widget são exclusivos do Flutter. Com eles, é possível testar individualmente cada widget escolhido. Nesta etapa, as telas HomePage e FavoritesPage serão testadas separadamente.

O teste de widget usa a função testWidget(), e não a test(). Ele também usa dois parâmetros: a description, e o callback. No entanto, aqui o callback usa um WidgetTester como argumento.

Os testes de widget usam a TestFlutterWidgetsBinding, uma classe que oferece os mesmos recursos que os widgets teriam em um app em execução (como informações sobre o tamanho da tela, a capacidade de programar animações, entre outras), mas sem o app real. Em vez disso, um ambiente virtual é usado para executar e medir o widget e, depois, testar os resultados. Aqui, o pumpWidget inicia o processo instruindo o framework a ativar e medir um widget específico, da mesma forma que seria feito em um aplicativo completo.

O framework de teste de widget fornece finders para encontrar widgets, como text(), byType() e byIcon(), além de matchers para analisar os resultados.

Comece testando o widget HomePage.

Criar um novo arquivo de teste

O primeiro teste verifica se a rolagem da HomePage funciona corretamente.

b2f84ff91b0e1396.png Crie um novo arquivo no diretório test e nomeie-o como home_test.dart. Adicione o seguinte código no arquivo criado:

test/home_test.dart (link em inglês)

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';
import 'package:testing_app/models/favorites.dart';
import 'package:testing_app/screens/home.dart';

Widget createHomeScreen() => ChangeNotifierProvider<Favorites>(
      create: (context) => Favorites(),
      child: MaterialApp(
        home: HomePage(),
      ),
    );

void main() {
  group('Home Page Widget Tests', () {
    testWidgets('Testing Scrolling', (tester) async {
      await tester.pumpWidget(createHomeScreen());
      expect(find.text('Item 0'), findsOneWidget);
      await tester.fling(find.byType(ListView), Offset(0, -200), 3000);
      await tester.pumpAndSettle();
      expect(find.text('Item 0'), findsNothing);
    });
  });
}

A função createHomeScreen() é usada para criar um app que carrega o widget a ser testado em um MaterialApp, envolvido em um ChangeNotifierProvider. O widget da página inicial precisa que os dois estejam presentes acima dele na árvore de widgets, para que ele consiga herdar e ter acesso aos dados fornecidos por eles. Essa função é transmitida como um parâmetro para a função pumpWidget().

Em seguida, teste se o framework consegue encontrar uma ListView renderizada na tela.

b2f84ff91b0e1396.png Adicione o seguinte snippet de código a home_test.dart:

test/home_test.dart (link em inglês)

group('Home Page Widget Tests', () {

  // BEGINNING OF NEW CONTENT
  testWidgets('Testing if ListView shows up', (tester) async {
    await tester.pumpWidget(createHomeScreen());
    expect(find.byType(ListView), findsOneWidget);
  });
  // END OF NEW CONTENT

  testWidgets('Testing Scrolling', (tester) async {
    await tester.pumpWidget(createHomeScreen());
    expect(find.text('Item 0'), findsOneWidget);
    await tester.fling(find.byType(ListView), Offset(0, -200), 3000);
    await tester.pumpAndSettle();
    expect(find.text('Item 0'), findsNothing);
  });
});

Executar o teste

É possível executar testes de widget da mesma forma que os testes de unidade, mas usando um dispositivo ou emulador que permita assistir o teste. Isso também possibilita usar a recarga dinâmica.

b2f84ff91b0e1396.png Conecte o dispositivo ou inicie o emulador.

b2f84ff91b0e1396.png Na linha de comando, navegue até o diretório raiz do projeto e digite o seguinte comando:

$ flutter run test/home_test.dart

Se tudo funcionar, você verá uma resposta parecida com a seguinte:

Launching test/home_test.dart on Mi A3 in debug mode...
Running Gradle task 'assembleDebug'...
Running Gradle task 'assembleDebug'... Done                        62.7s
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...                 5.8s
Waiting for Mi A3 to report its views...                            16ms
I/flutter ( 1616): 00:00 +0: Home Page Widget Tests Testing if ListView shows up
Syncing files to device Mi A3...
I/flutter ( 1616): 00:02 +1: Home Page Widget Tests Testing Scrolling
Syncing files to device Mi A3...                                                 4,008ms (!)

Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h Repeat this help message.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).
An Observatory debugger and profiler on Mi A3 is available at:
http://127.0.0.1:40433/KOsGesHSxR8=/
I/flutter ( 1616): 00:00 +0: Home Page Widget Tests Testing if ListView shows up
I/flutter ( 1616): 00:02 +1: Home Page Widget Tests Testing Scrolling
I/flutter ( 1616): 00:09 +3: All tests passed!

Faça mudanças no arquivo de teste e digite Shift + R para fazer uma recarga dinâmica do app. Depois, execute todos os testes novamente.

b2f84ff91b0e1396.png Adicione mais testes ao grupo que testa os widgets da página inicial. Copie o teste a seguir e cole no arquivo:

test/home_test.dart (link em inglês)

testWidgets('Testing IconButtons', (tester) async {
  await tester.pumpWidget(createHomeScreen());
  expect(find.byIcon(Icons.favorite), findsNothing);
  await tester.tap(find.byIcon(Icons.favorite_border).first);
  await tester.pumpAndSettle(Duration(seconds: 1));
  expect(find.text('Added to favorites.'), findsOneWidget);
  expect(find.byIcon(Icons.favorite), findsWidgets);
  await tester.tap(find.byIcon(Icons.favorite).first);
  await tester.pumpAndSettle(Duration(seconds: 1));
  expect(find.text('Removed from favorites.'), findsOneWidget);
  expect(find.byIcon(Icons.favorite), findsNothing);
});

Esse teste verifica se, com um toque, o IconButton muda de Icons.favorite_border (coração vazio) para Icons.favorite (coração preenchido) e volta para Icons.favorite_border com outro toque.

b2f84ff91b0e1396.png Digite Shift + R. Isso faz uma recarga dinâmica do app e executa todos os apps novamente.

Veja o arquivo de teste completo em: test/home_test.dart. (link em inglês).

b2f84ff91b0e1396.png Use o mesmo processo para testar a FavoritesPage com o código a seguir. Siga as mesmas etapas e execute o teste.

test/favorites_test.dart (link em inglês)

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:provider/provider.dart';
import 'package:testing_app/models/favorites.dart';
import 'package:testing_app/screens/favorites.dart';

Favorites favoritesList;

Widget createFavoritesScreen() => ChangeNotifierProvider<Favorites>(
      create: (context) {
        favoritesList = Favorites();
        return favoritesList;
      },
      child: MaterialApp(
        home: FavoritesPage(),
      ),
    );

void addItems() {
  for (var i = 0; i < 10; i += 2) {
    favoritesList.add(i);
  }
}

void main() {
  group('Favorites Page Widget Tests', () {
    testWidgets('Test if ListView shows up', (tester) async {
      await tester.pumpWidget(createFavoritesScreen());
      addItems();
      await tester.pumpAndSettle();
      expect(find.byType(ListView), findsOneWidget);
    });

    testWidgets('Testing Remove Button', (tester) async {
      await tester.pumpWidget(createFavoritesScreen());
      addItems();
      await tester.pumpAndSettle();
      var totalItems = tester.widgetList(find.byIcon(Icons.close)).length;
      await tester.tap(find.byIcon(Icons.close).first);
      await tester.pumpAndSettle();
      expect(tester.widgetList(find.byIcon(Icons.close)).length,
          lessThan(totalItems));
      expect(find.text('Removed from favorites.'), findsOneWidget);
    });
  });
}

Este teste verifica se um item desaparece quando o botão Fechar (remover) é pressionado.

Para ver mais informações sobre testes de widgets, acesse (links em inglês):

Os testes de integração são usados para testar a forma como as partes individuais de um app funcionam em conjunto. O pacote integration_test (link em inglês) é usado para fazer testes de integração no Flutter. Essa é a versão do Flutter do Selenium WebDrive (Web), Protrator (Angular), Espresso (Android) ou Earl Gray (iOS). O pacote usa o flutter_driver (link em inglês) internamente para conduzir o teste em um dispositivo.

Instrumentar o app

Para criar um teste de integração, primeiro é necessário instrumentar o app. Isso significa configurá-lo para que o driver possa acessar a GUI e as funções para criar e executar um teste automatizado. Os testes de integração são colocados em um diretório chamado integration_test. Nesta etapa, você adicionará os seguintes arquivos para criar o teste de integração:

  • integration_test/driver.dart: instrumenta o app.
  • integration_test/app_test.dart: executa os testes no app.

b2f84ff91b0e1396.png Crie um diretório chamado integration_test no diretório raiz do projeto. Nesse diretório, crie um arquivo driver.dart e adicione o código a seguir:

integration_test/driver.dart (link em inglês)

import 'package:integration_test/integration_test_driver.dart';

Future<void> main() => integrationDriver();

Esse código ativa o driver do teste de integração e aguarda a execução do teste. Os dados de resposta são armazenados em um arquivo chamado integration_response_data.json depois que os testes são executados.

Criar o teste

b2f84ff91b0e1396.png Crie um novo arquivo e nomeie-o como app_test.dart.

integration_test/app_test.dart (link em inglês)

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:testing_app/main.dart';

void main() {
  group('Testing App Performance Tests', () {
    final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized()
        as IntegrationTestWidgetsFlutterBinding;

    binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
  });
}

A função ensureInitialized() verifica se o driver do teste de integração foi inicializado ou não e reinicia o driver se necessário. A framePolicy é mais adequada para testar casos com muitas animações quando definida como fullyLive na enumeração LiveTestWidgetsFlutterBindingFramePolicy (link em inglês).

Em seguida, teste o desempenho da rolagem do app e registre o resultado usando a função watchPerformance().

b2f84ff91b0e1396.png Cole o seguinte código no grupo de teste que você acabou de criar:

integration_test/app_test.dart (link em inglês)

testWidgets('Scrolling test', (tester) async {
  await tester.pumpWidget(TestingApp());

  final listFinder = find.byType(ListView);

  await binding.watchPerformance(() async {
    await tester.fling(listFinder, Offset(0, -500), 10000);
    await tester.pumpAndSettle();

    await tester.fling(listFinder, Offset(0, 500), 10000);
    await tester.pumpAndSettle();
  }, reportKey: 'scrolling_summary');
});

Este teste percorre a lista de itens com muita rapidez e, em seguida, rola a página para cima até o início. A função watchPerformance() registra as ações e gera um resumo da linha do tempo, que é reenviado como dados de resposta para o driver de teste no arquivo driver.dart.

Em seguida, teste as operações add e remove.

b2f84ff91b0e1396.png Cole o seguinte teste no mesmo grupo:

integration_test/app_test.dart (link em inglês)

testWidgets('Favorites operations test', (tester) async {
  await tester.pumpWidget(TestingApp());

  final iconKeys = [
    'icon_0',
    'icon_1',
    'icon_2',
  ];

  for (var icon in iconKeys) {
    await tester.tap(find.byKey(ValueKey(icon)));
    await tester.pumpAndSettle(Duration(seconds: 1));

    expect(find.text('Added to favorites.'), findsOneWidget);
  }

  await tester.tap(find.text('Favorites'));
  await tester.pumpAndSettle();

  final removeIconKeys = [
    'remove_icon_0',
    'remove_icon_1',
    'remove_icon_2',
  ];

  for (final iconKey in removeIconKeys) {
    await tester.tap(find.byKey(ValueKey(iconKey)));
    await tester.pumpAndSettle(Duration(seconds: 1));

    expect(find.text('Removed from favorites.'), findsOneWidget);
  }
});

Executar o teste

b2f84ff91b0e1396.png Conecte o dispositivo ou inicie o emulador.

b2f84ff91b0e1396.png Na linha de comando, navegue até o diretório raiz do projeto e digite o seguinte comando:

$ flutter drive --driver integration_test/driver.dart --target integration_test/app_test.dart --profile

Se tudo funcionar, você verá uma resposta parecida com a seguinte:

Running "flutter pub get" in step_07...                            930ms
Running Gradle task 'assembleProfile'...
Running Gradle task 'assembleProfile'... Done                      31.3s
✓ Built build/app/outputs/flutter-apk/app-profile.apk (11.3MB).
Installing build/app/outputs/flutter-apk/app.apk...                277ms
VMServiceFlutterDriver: Connecting to Flutter application at http://127.0.0.1:62862/K6QKjUNab8c=/
VMServiceFlutterDriver: Isolate found with number: 1935648057883071
VMServiceFlutterDriver: Isolate is paused at start.
VMServiceFlutterDriver: Attempting to resume isolate
I/flutter (24385): 00:00 +0: Testing App Performance Tests Scrolling test
VMServiceFlutterDriver: Connected to Flutter application.
I/flutter (24385): 00:08 +1: Testing App Performance Tests Favorites operations
test
I/flutter (24385): 00:17 +2: Testing App Performance Tests (tearDownAll)
I/flutter (24385): 00:17 +3: All tests passed!
All tests passed.

Quando o teste for concluído, o diretório build na raiz do projeto terá um arquivo chamado integration_response_data.json. Ele contém os dados de resposta enviados pelo teste durante a execução; nesse caso, o scrolling_summary. Abra o arquivo com qualquer editor de texto para visualizar as informações. Com uma configuração mais avançada, é possível salvar um resumo sempre que o teste é executado e criar um gráfico com os resultados.

Veja o arquivo de teste completo em: integration_test/app_test.dart. (link em inglês).

Para ver mais informações sobre os testes de integração com o driver do Flutter, acesse (links em inglês):

Você concluiu o codelab e aprendeu formas diferentes de testar um app do Flutter.

O que você aprendeu

  • Como testar widgets usando o framework de testes de widgets.
  • Como testar a IU do app usando testes de integração.
  • Como testar o desempenho do app usando testes de integração.
  • Como testar provedores com a ajuda dos testes de unidade

Para saber mais sobre os testes no Flutter, acesse (links em inglês):