Flutter позволяет вам писать простые и понятные тесты для разных частей приложения.
Сегодня мы попробуем написать несколько unit тестов, которые используются для тестирования классов, методов и отдельных функций.
Также мы попробуем использовать библиотеку Mockito, которая позволяет создавать фейковые реализации.
Ну что ж, приступаем к тестированию!
Наш план
-
Часть 1 — введение в разработку, первое приложение, понятие состояния;
-
Часть 2 — файл pubspec.yaml и использование flutter в командной строке;
-
Часть 3 — BottomNavigationBar и Navigator;
-
Часть 4 — MVC. Мы будем использовать именно этот паттерн, как один из самых простых;
-
Часть 5 — http пакет. Создание Repository класса, первые запросы, вывод списка постов;
-
Часть 6 — работа с формами, текстовые поля и создание поста.
-
Часть 7 — работа с картинками, вывод картинок в виде сетки, получение картинок из сети, добавление своих в приложение;
-
Часть 8 — создание своей темы, добавление кастомных шрифтов и анимации;
-
Часть 9 (текущая статья) — немного о тестировании;
Добавления необходимых зависимостей
Нам понадобиться два дополнительных пакета mockito и build_runner, поэтому добавим их:
# зависимости для разработки # в данном случае подключено тестирование dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.10 build_runner: ^2.0.4
Теперь мы можем приступать к тестированию
Пишем первый тест
В качестве объекта тестирования будет небольшой класс Stack:
class Stack<T> { final stack = <T>[]; void push(T t) { stack.add(t); } T? pop() { if (isEmpty) { return null; } return stack.removeLast(); } bool get isEmpty => stack.isEmpty; }
Обратите внимание: класс Stack является обобщенным.
В корневой директории нашего проекта есть папка test, которая предназначена для тестов.
Создадим в ней новый файл stack_test.dart:
import 'package:flutter_test/flutter_test.dart'; import 'package:json_placeholder_app/helpers/stack.dart'; void main() { // группа тестов group("Stack", () { // первый тест на пустой стек test("Stack should be empty", () { // expect принимает текущее значение // и сравнивает его с правильным // если значения не совпадают, тест не пройден expect(Stack().isEmpty, true); }); test("Stack shouldn't be empty", () { final stack = Stack<int>(); stack.push(5); expect(stack.isEmpty, false); }); test("Stack should be popped", () { final stack = Stack<int>(); stack.push(5); expect(stack.pop(), 5); }); test("Stack should be work correctly", () { final stack = Stack<int>(); stack.push(1); stack.push(2); stack.push(5); expect(stack.pop(), 5); expect(stack.pop(), 2); expect(stack.isEmpty, false); }); }); }
Довольно просто! Не правда ли?
На самом деле, это один из типов тестирования, который называется unit (модульное).
Также Flutter поддерживает:
-
Widget тестирование
-
Интеграционное тестирование
В данной статье мы рассмотрим только unit тестирование.
Давайте выполним наши тесты командой flutter test test/stack_test.dart:

Успешно!
Тестируем получение постов
Сначала видоизменим метод fetchPosts:
Future<PostList> fetchPosts({http.Client? client}) async { // сначала создаем URL, по которому // мы будем делать запрос final url = Uri.parse("$SERVER/posts"); // делаем GET запрос final response = (client == null) ? await http.get(url) : await client.get(url); // проверяем статус ответа if (response.statusCode == 200) { // если все ок то возвращаем посты // json.decode парсит ответ return PostList.fromJson(json.decode(response.body)); } else { // в противном случае вызываем исключение throw Exception("failed request"); } }
Теперь переходим к написанию самого теста.
Мы будем использовать mockito для создания фейкового http.Client'а
Создадим файл post_test.dart в папке tests:
import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart' as http; import 'package:json_placeholder_app/data/repository.dart'; import 'package:json_placeholder_app/models/post.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; // данный файл будет сгенерирован import 'post_test.mocks.dart'; // аннотация mockito @GenerateMocks([http.Client]) void main() { // создаем наш репозиторий final repo = Repository(); group("fetchPosts", () { test('returns posts if the http call completes successfully', () async { // создаем фейковый клиент final client = MockClient(); // ответ на запрос when(client.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'))) .thenAnswer((_) async => http.Response('[{"userId": 1, "id": 2, "title": "Title", "content": "Content"}]', 200)); // проверяем корректность работы fetchPosts // при удачном выполнении final postList = await repo.fetchPosts(client: client); expect(postList, isA<PostList>()); expect(postList.posts.length, 1); expect(postList.posts.first.title, "Title"); }); test('throws an exception if the http call completes with an error', () { final client = MockClient(); // генерация ошибки when(client.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'))) .thenAnswer((_) async => http.Response('Not Found', 404)); // проверка на исключение expect(repo.fetchPosts(client: client), throwsException); }); }); }
Перед запуском теста необходимо сгенерировать post_test.mocks.dart файл:
flutter pub run build_runner build
После этого выполняем наши тесты командой flutter test test/post_test.dart:

Вуаля!
Заключение
Мы разобрали один из самых простых и известных типов тестирования — unit (модульное).
Как уже было отмечено, Flutter позволяет отдельно тестировать виджеты, а также проводить полноценное тестирование с применением интеграционных тестов.
Полезные ссылки:
Всем хорошего кода!
ссылка на оригинал статьи https://habr.com/ru/post/562352/
Добавить комментарий