1. Введение
Flutter — это набор инструментов пользовательского интерфейса Google для создания красивых, скомпилированных в собственном коде приложений для мобильных устройств, Интернета и настольных компьютеров из единой базы кода.
В этой лаборатории кода вы создадите и протестируете простое приложение Flutter. Приложение будет использовать пакет Provider для управления состоянием.
Что вы узнаете
- Как создавать тесты виджетов с помощью платформы тестирования виджетов
- Как создать интеграционный тест для проверки пользовательского интерфейса и производительности приложения с помощью библиотеки
integration_test
- Как тестировать классы данных (провайдеры) с помощью модульных тестов
Что ты построишь
В этой лаборатории кода вы начнете с создания простого приложения со списком элементов. Мы предоставляем вам исходный код, чтобы вы могли сразу приступить к тестированию. Приложение поддерживает следующие операции:
- Добавление товаров в избранное
- Просмотр списка избранного
- Удаление элементов из списка избранного
Как только приложение будет завершено, вы напишете следующие тесты:
| GIF-изображение приложения, работающего на Android |
Что бы вы хотели узнать из этой кодовой лаборатории?
2. Настройте среду разработки Flutter.
Для выполнения этой лабораторной работы вам понадобятся два программного обеспечения — Flutter SDK и редактор .
Вы можете запустить кодовую лабораторию, используя любое из этих устройств:
- Физическое устройство Android или iOS , подключенное к вашему компьютеру и переведенное в режим разработчика.
- Симулятор iOS (требуется установка инструментов Xcode).
- Эмулятор Android (требуется установка в Android Studio).
- Браузер (для отладки необходим Chrome).
- В качестве настольного приложения для Windows , Linux или macOS . Вы должны разрабатывать на платформе, на которой планируете развернуть. Итак, если вы хотите разработать классическое приложение для Windows, вам необходимо разработать его в Windows, чтобы получить доступ к соответствующей цепочке сборки. Существуют требования, специфичные для операционной системы, которые подробно описаны на docs.flutter.dev/desktop .
3. Начало работы
Создайте новое приложение Flutter и обновите зависимости.
Эта лаборатория посвящена тестированию мобильного приложения Flutter. Вы быстро создадите приложение для тестирования, используя исходные файлы, которые вы скопируете и вставите. Остальная часть лаборатории кода фокусируется на изучении различных видов тестирования.
Создайте простое приложение Flutter по шаблону, используя инструкции в разделе «Начало работы с первым приложением Flutter» или в командной строке, как показано ниже.
$ flutter create --empty testing_app Creating project testing_app... Resolving dependencies in `testing_app`... Downloading packages... Got dependencies in `testing_app`. Wrote 128 files. All done! You can find general documentation for Flutter at: https://docs.flutter.dev/ Detailed API documentation is available at: https://api.flutter.dev/ If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev In order to run your empty application, type: $ cd testing_app $ flutter run Your empty application code is in testing_app/lib/main.dart.
Добавьте зависимости паба в командной строке.
-
provider
для простого управления состоянием, -
integration_test
для самостоятельного тестирования кода Flutter на устройствах и эмуляторах, -
flutter_driver
для расширенного API для тестирования приложений Flutter, которые работают на реальных устройствах и эмуляторах, -
test
общего испытательного инструментария, -
go_router
для управления навигацией по приложению.
$ cd testing_app $ flutter pub add provider go_router dev:test 'dev:flutter_driver:{"sdk":"flutter"}' 'dev:integration_test:{"sdk":"flutter"}' Resolving dependencies... Downloading packages... + _fe_analyzer_shared 67.0.0 (68.0.0 available) + analyzer 6.4.1 (6.5.0 available) + args 2.5.0 + convert 3.1.1 + coverage 1.7.2 + crypto 3.0.3 + file 7.0.0 + flutter_driver 0.0.0 from sdk flutter + flutter_web_plugins 0.0.0 from sdk flutter + frontend_server_client 4.0.0 + fuchsia_remote_debug_protocol 0.0.0 from sdk flutter + glob 2.1.2 + go_router 14.0.2 + http_multi_server 3.2.1 + http_parser 4.0.2 + integration_test 0.0.0 from sdk flutter + io 1.0.4 + js 0.7.1 leak_tracker 10.0.4 (10.0.5 available) leak_tracker_flutter_testing 3.0.3 (3.0.5 available) + logging 1.2.0 material_color_utilities 0.8.0 (0.11.1 available) meta 1.12.0 (1.14.0 available) + mime 1.0.5 + nested 1.0.0 + node_preamble 2.0.2 + package_config 2.1.0 + platform 3.1.4 + pool 1.5.1 + process 5.0.2 + provider 6.1.2 + pub_semver 2.1.4 + shelf 1.4.1 + shelf_packages_handler 3.0.2 + shelf_static 1.1.2 + shelf_web_socket 1.0.4 + source_map_stack_trace 2.1.1 + source_maps 0.10.12 + sync_http 0.3.1 + test 1.25.2 (1.25.4 available) test_api 0.7.0 (0.7.1 available) + test_core 0.6.0 (0.6.2 available) + typed_data 1.3.2 + watcher 1.1.0 + web 0.5.1 + web_socket_channel 2.4.5 + webdriver 3.0.3 + webkit_inspection_protocol 1.2.1 + yaml 3.1.2 Changed 44 dependencies! 9 packages have newer versions incompatible with dependency constraints. Try `flutter pub outdated` for more information.
Следующие зависимости должны быть добавлены в ваш pubspec.yaml :
pubspec.yaml
name: testing_app description: "A new Flutter project." publish_to: 'none' version: 0.1.0 environment: sdk: '>=3.4.0-0 <4.0.0' dependencies: flutter: sdk: flutter go_router: ^14.0.2 provider: ^6.1.2 dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^3.0.0 test: ^1.25.2 flutter_driver: sdk: flutter integration_test: sdk: flutter flutter: uses-material-design: true
Откройте проект в выбранном вами редакторе кода и запустите приложение. Альтернативно, запустите его из командной строки следующим образом.
$ flutter run
4. Создайте приложение
Далее вы создадите приложение, чтобы его можно было протестировать. Приложение содержит следующие файлы:
-
lib/models/favorites.dart
— создает класс модели для списка избранного. -
lib/screens/favorites.dart
— создает макет списка избранного. -
lib/screens/home.dart
— создает список элементов -
lib/main.dart
— основной файл, из которого запускается приложение.
Сначала создайте модель Favorites
в lib/models/favorites.dart
Создайте новый каталог с именем models
в каталоге lib
, а затем создайте новый файл с именем favorites.dart
. В этот файл добавьте следующий код:
lib/модели/фавориты.dart
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();
}
}
Добавьте страницу «Избранное» в lib/screens/favorites.dart
Создайте новый каталог с именем screens
в каталоге lib
и в этом каталоге создайте новый файл с именем favorites.dart
. В этот файл добавьте следующий код:
lib/экраны/favorites.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/favorites.dart';
class FavoritesPage extends StatelessWidget {
const FavoritesPage({super.key});
static String routeName = 'favorites_page';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const 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 {
const FavoriteItemTile(this.itemNo, {super.key});
final int 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: const Icon(Icons.close),
onPressed: () {
Provider.of<Favorites>(context, listen: false).remove(itemNo);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Removed from favorites.'),
duration: Duration(seconds: 1),
),
);
},
),
),
);
}
}
Добавьте домашнюю страницу в lib/screens/home.dart
В каталоге lib/screens
создайте еще один новый файл с именем home.dart
. В lib/screens/home.dart
добавьте следующий код:
библиотека/экраны/home.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import '../models/favorites.dart';
import 'favorites.dart';
class HomePage extends StatelessWidget {
static String routeName = '/';
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Testing Sample'),
actions: <Widget>[
TextButton.icon(
onPressed: () {
context.go('/${FavoritesPage.routeName}');
},
icon: const Icon(Icons.favorite_border),
label: const 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, {super.key});
@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)
? const Icon(Icons.favorite)
: const 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: const Duration(seconds: 1),
),
);
},
),
),
);
}
}
Замените содержимое lib/main.dart
Замените содержимое lib/main.dart
следующим кодом:
библиотека/main.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'models/favorites.dart';
import 'screens/favorites.dart';
import 'screens/home.dart';
void main() {
runApp(const TestingApp());
}
final _router = GoRouter(
routes: [
GoRoute(
path: HomePage.routeName,
builder: (context, state) {
return const HomePage();
},
routes: [
GoRoute(
path: FavoritesPage.routeName,
builder: (context, state) {
return const FavoritesPage();
},
),
],
),
],
);
class TestingApp extends StatelessWidget {
const TestingApp({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Favorites>(
create: (context) => Favorites(),
child: MaterialApp.router(
title: 'Testing Sample',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
),
useMaterial3: true,
),
routerConfig: _router,
),
);
}
}
Приложение готово, но не протестировано.
Запустите приложение. Это должно выглядеть как на следующем снимке экрана:
Приложение показывает список предметов. Коснитесь значка в форме сердца в любой строке, чтобы заполнить сердце и добавить элемент в список избранного. Кнопка «Избранное» на AppBar
переводит вас на второй экран, содержащий список избранного.
Теперь приложение готово к тестированию. Вы начнете тестировать приложение на следующем этапе.
5. Юнит-тестирование провайдера
Вы начнете с модульного тестирования модели favorites
. Что такое модульный тест? Юнит-тест проверяет, что каждая отдельная единица программного обеспечения, будь то функция, объект или виджет, правильно выполняет поставленную задачу.
Все тестовые файлы в приложении Flutter, за исключением интеграционных тестов, размещаются в test
каталоге.
Удалить test/widget_test.dart
Прежде чем начать тестирование, удалите файл widget_test.dart
. Вы добавите свои собственные тестовые файлы.
Создайте новый тестовый файл
Сначала вы протестируете метод add()
в модели Favorites
, чтобы убедиться, что в список добавляется новый элемент и что список отражает это изменение. По соглашению, структура каталогов в test
каталоге имитирует структуру каталога lib
и файлов Dart, имеющих одно и то же имя с добавлением _test
.
Создайте каталог models
в test
каталоге. В этом новом каталоге создайте файл favorites_test.dart
со следующим содержимым:
test/models/favorites_test.dart
import 'package:test/test.dart';
import 'package:testing_app/models/favorites.dart';
void main() {
group('Testing App Provider', () {
var favorites = Favorites();
test('A new item should be added', () {
var number = 35;
favorites.add(number);
expect(favorites.items.contains(number), true);
});
});
}
Платформа тестирования Flutter позволяет связывать похожие тесты, связанные друг с другом, в группу. В одном тестовом файле может быть несколько групп, предназначенных для тестирования различных частей соответствующего файла в каталоге lib
.
Метод test()
принимает два позиционных параметра: description
теста и callback
, в котором вы фактически пишете тест.
Проверьте удаление элемента из списка. Вставьте следующий тест в ту же группу Testing App Provider
:
test/models/favorites_test.dart
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);
});
Запустить тест
В командной строке перейдите в корневой каталог проекта и введите следующую команду:
$ flutter test test/models/favorites_test.dart
Если все работает, вы должны увидеть сообщение, подобное следующему:
00:06 +2: All tests passed!
Полный тестовый файл: test/models/favorites_test.dart
.
Дополнительные сведения о модульном тестировании см. на странице Введение в модульное тестирование .
6. Тестирование виджета
На этом этапе вы добавите код для тестирования виджетов. Тестирование виджетов уникально для Flutter: вы можете тестировать каждый виджет изолированно. На этом этапе экраны HomePage
и FavoritesPage
тестируются по отдельности.
При тестировании виджетов используется функция testWidget()
вместо функции test()
. Как и функция test()
, функция testWidget()
принимает два параметра: description,
и callback
, однако обратный вызов принимает WidgetTester
в качестве аргумента.
Тесты виджетов используют TestFlutterWidgetsBinding
, класс, который предоставляет вашим виджетам те же ресурсы, что и в работающем приложении, например, информацию о размере экрана, возможность планировать анимацию, но без запуска внутри приложения. Вместо этого для создания экземпляра виджета используется виртуальная среда, а затем тестируются результаты. Здесь pumpWidget
запускает процесс, сообщая платформе смонтировать и измерить конкретный виджет так же, как это было бы в приложении.
Платформа тестирования виджетов предоставляет средства поиска для поиска виджетов, например text()
, byType()
и byIcon().
Платформа также предоставляет средства сопоставления для проверки результатов.
Начните с тестирования виджета HomePage
.
Создайте новый тестовый файл
Первый тест проверяет, правильно ли работает прокрутка HomePage
.
Создайте новый файл в test
каталоге и назовите его home_test.dart
. Во вновь созданный файл добавьте следующий код:
тест/home_test.dart
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: const 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),
const Offset(0, -200),
3000,
);
await tester.pumpAndSettle();
expect(find.text('Item 0'), findsNothing);
});
});
}
Функция createHomeScreen()
используется для создания приложения, которое загружает виджет для тестирования в MaterialApp, завернутый в ChangeNotifierProvider. Виджету HomePage необходимо, чтобы оба этих виджета присутствовали над ним в дереве виджетов, чтобы он мог наследовать от них и получать доступ к предлагаемым ими данным. Эта функция передается в качестве параметра функции pumpWidget()
.
Затем проверьте, может ли платформа найти ListView
отображаемый на экране.
Добавьте следующий фрагмент кода в home_test.dart
:
тест/home_test.dart
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),
const Offset(0, -200),
3000,
);
await tester.pumpAndSettle();
expect(find.text('Item 0'), findsNothing);
});
});
Запустить тест
Сначала запустите тест так же, как и модульный тест, с помощью команды:
$ flutter test test/home_test.dart
Тест должен выполниться быстро, и вы должны увидеть сообщение, подобное этому:
00:02 +2: All tests passed!
Вы также можете запускать тесты виджетов с помощью устройства или эмулятора, что позволяет вам наблюдать за выполнением теста. Это также дает вам возможность использовать горячий перезапуск.
Подключите устройство или запустите эмулятор. Вы также можете запустить тест как настольное приложение.
В командной строке перейдите в корневой каталог проекта и введите следующую команду:
$ flutter run test/home_test.dart
Возможно, вам придется выбрать устройство для запуска теста. В этом случае следуйте инструкциям и выберите устройство:
Multiple devices found:
Linux (desktop) • linux • linux-x64 • Ubuntu 22.04.1 LTS 5.15.0-58-generic
Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119
[1]: Linux (linux)
[2]: Chrome (chrome)
Please choose one (To quit, press "q/Q"):
Если все работает, вы должны увидеть вывод, аналогичный следующему:
Launching test/home_test.dart on Linux in debug mode...
Building Linux application...
flutter: 00:00 +0: Home Page Widget Tests Testing if ListView shows up
Syncing files to device Linux... 62ms
Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).
💪 Running with sound null safety 💪
An Observatory debugger and profiler on Linux is available at: http://127.0.0.1:35583/GCpdLBqf2UI=/
flutter: 00:00 +1: Home Page Widget Tests Testing Scrolling
The Flutter DevTools debugger and profiler on Linux is available at:
http://127.0.0.1:9100?uri=http://127.0.0.1:35583/GCpdLBqf2UI=/
flutter: 00:02 +2: All tests passed!
Затем вы внесете изменения в тестовый файл и нажмите Shift + R
, чтобы перезапустить приложение и повторно запустить все тесты. Не останавливайте приложение.
Добавьте больше тестов в группу, которая тестирует виджеты HomePage. Скопируйте следующий тест в свой файл:
тест/home_test.dart
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(const 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(const Duration(seconds: 1));
expect(find.text('Removed from favorites.'), findsOneWidget);
expect(find.byIcon(Icons.favorite), findsNothing);
});
Этот тест проверяет, что нажатие IconButton
меняется с Icons.favorite_border
(открытое сердце) на Icons.favorite
(заполненное сердце), а затем обратно на Icons.favorite_border
при повторном нажатии.
Введите Shift + R
. Этот горячий перезапускает приложение и повторно запускает все тесты.
Полный тестовый файл: test/home_test.dart
.
Используйте тот же процесс для проверки FavoritesPage
с помощью следующего кода. Выполните те же действия и запустите его.
тест/favorites_test.dart
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';
late Favorites favoritesList;
Widget createFavoritesScreen() => ChangeNotifierProvider<Favorites>(
create: (context) {
favoritesList = Favorites();
return favoritesList;
},
child: const 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);
});
});
}
Этот тест проверяет, исчезает ли элемент при нажатии кнопки закрытия (удаления).
Для получения дополнительной информации о тестировании виджетов посетите:
7. Тестирование пользовательского интерфейса приложения с помощью интеграционных тестов.
Интеграционные тесты используются для проверки того, как отдельные части приложения работают вместе в целом. Библиотека integration_test
используется для выполнения интеграционных тестов во Flutter. Это версия Selenium WebDriver, Protractor, Espresso или Earl Grey от Flutter. Пакет внутренне использует flutter_driver
для проведения теста на устройстве.
Написание интеграционных тестов во Flutter похоже на написание тестов виджетов, за исключением того, что интеграционные тесты запускаются на мобильном устройстве, браузере или настольном приложении, называемом целевым устройством.
Написать тест
Создайте каталог с именем integration_test
в корневом каталоге проекта и в этом каталоге создайте новый файл с именем app_test.dart
.
Integration_test/app_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:testing_app/main.dart';
void main() {
group('Testing App', () {
testWidgets('Favorites operations test', (tester) async {
await tester.pumpWidget(const TestingApp());
final iconKeys = [
'icon_0',
'icon_1',
'icon_2',
];
for (var icon in iconKeys) {
await tester.tap(find.byKey(ValueKey(icon)));
await tester.pumpAndSettle(const 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(const Duration(seconds: 1));
expect(find.text('Removed from favorites.'), findsOneWidget);
}
});
});
}
Запустить тест
Подключите устройство или запустите эмулятор. Вы также можете запустить тест как настольное приложение.
В командной строке перейдите в корневой каталог проекта и введите следующую команду:
$ flutter test integration_test/app_test.dart
Если все работает, вы должны увидеть вывод, аналогичный следующему:
Multiple devices found:
Linux (desktop) • linux • linux-x64 • Ubuntu 22.04.1 LTS 5.15.0-58-generic
Chrome (web) • chrome • web-javascript • Google Chrome 109.0.5414.119
[1]: Linux (linux)
[2]: Chrome (chrome)
Please choose one (To quit, press "q/Q"): 1
00:00 +0: loading /home/miquel/tmp/testing_app/integration_test/app_test.dart B00:08 +0: loading /home/miquel/tmp/testing_app/integration_test/app_test.dart
00:26 +1: All tests passed!
8. Тестирование производительности приложения с помощью Flutter Driver
Напишите тест производительности
Создайте новый тестовый файл с именем perf_test.dart в папке Integration_test со следующим содержимым:
Integration_test/perf_test.dart
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', () {
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
testWidgets('Scrolling test', (tester) async {
await tester.pumpWidget(const TestingApp());
final listFinder = find.byType(ListView);
await binding.traceAction(() async {
await tester.fling(listFinder, const Offset(0, -500), 10000);
await tester.pumpAndSettle();
await tester.fling(listFinder, const Offset(0, 500), 10000);
await tester.pumpAndSettle();
}, reportKey: 'scrolling_summary');
});
});
}
Функция ensureInitialized()
проверяет, инициализирован ли драйвер интеграционного теста, и при необходимости инициализирует его повторно. Установка для framePolicy
значения fullyLive
удобна для тестирования анимированного кода.
Этот тест очень быстро прокручивает список элементов, а затем прокручивает его до конца вверх. Функция traceAction()
записывает действия и генерирует сводку по временной шкале.
Фиксируйте результаты производительности
Чтобы получить результаты, создайте папку с именем test_driver
с файлом с именем perf_driver.dart
и добавьте следующий код:
test_driver/perf_driver.dart
import 'package:flutter_driver/flutter_driver.dart' as driver;
import 'package:integration_test/integration_test_driver.dart';
Future<void> main() {
return integrationDriver(
responseDataCallback: (data) async {
if (data != null) {
final timeline = driver.Timeline.fromJson(
data['scrolling_summary'] as Map<String, dynamic>);
final summary = driver.TimelineSummary.summarize(timeline);
await summary.writeTimelineToFile(
'scrolling_summary',
pretty: true,
includeSummary: true,
);
}
},
);
}
Запустить тест
Подключите устройство или запустите эмулятор.
В командной строке перейдите в корневой каталог проекта и введите следующую команду:
$ flutter drive \
--driver=test_driver/perf_driver.dart \
--target=integration_test/perf_test.dart \
--profile \
--no-dds
Если все работает, вы должны увидеть вывод, аналогичный следующему:
Running "flutter pub get" in testing_app...
Resolving dependencies...
archive 3.3.2 (3.3.6 available)
collection 1.17.0 (1.17.1 available)
js 0.6.5 (0.6.7 available)
matcher 0.12.13 (0.12.14 available)
meta 1.8.0 (1.9.0 available)
path 1.8.2 (1.8.3 available)
test 1.22.0 (1.23.0 available)
test_api 0.4.16 (0.4.18 available)
test_core 0.4.20 (0.4.23 available)
vm_service 9.4.0 (11.0.1 available)
webdriver 3.0.1 (3.0.2 available)
Got dependencies!
Running Gradle task 'assembleProfile'... 1,379ms
✓ Built build/app/outputs/flutter-apk/app-profile.apk (14.9MB).
Installing build/app/outputs/flutter-apk/app-profile.apk... 222ms
I/flutter ( 6125): 00:04 +1: Testing App Performance (tearDownAll)
I/flutter ( 6125): 00:04 +2: All tests passed!
All tests passed.
После успешного завершения теста каталог сборки в корне проекта содержит два файла:
-
scrolling_summary.timeline_summary.json
содержит сводку. Откройте файл в любом текстовом редакторе, чтобы просмотреть содержащуюся в нем информацию. -
scrolling_summary.timeline.json
содержит полные данные временной шкалы.
Для получения более подробной информации об интеграционном тестировании посетите:
9. Поздравляем!
Вы завершили работу над кодом и узнали различные способы тестирования приложения Flutter.
Что вы узнали
- Как тестировать провайдеров с помощью модульных тестов
- Как тестировать виджеты с помощью среды тестирования виджетов
- Как протестировать пользовательский интерфейс приложения с помощью интеграционных тестов
- Как проверить производительность приложения с помощью интеграционных тестов
Чтобы узнать больше о тестировании во Flutter, посетите