Пишем golden-тесты для генераторов кода на Dart

от автора

Некоторое время назад я доработал пакет source_gen_test Кевина Мура и добавил поддержку внешних golden‑файлов. Этот пакет используют, чтобы писать тесты для таких генераторов кода как json_serializable. Для этого используют аннотацию ShouldGenerate из этого пакета:

@ShouldGenerate(   r''' <Dart code to generate> ''', ) @TestAnnotation() class Foo {}

У этого было две проблемы:

  • Тяжело читать, если генерируется много кода.

  • Генерируемый код нельзя проверить на ошибки. Чтобы всё‑таки проверить, нужно копировать этот код во внешний файл и писать тесты на него. Потом эти две копии кода могут разойтись.

Я сделал аннотацию ShouldGenerateFile, которая позволяет положить ожидаемый код сразу во внешний файл .dart. Она проверит, что генератор выдаёт именно такой код, и вместе с этим вы можете писать тесты на этот код:

@ShouldGenerateFile(   'goldens/foo.dart',   partOfCurrent: true, ) @TestAnnotation() class Foo {}

Реальный пример: enum_map

Реальный пример тестирования генератора таким образом — в пакете enum_map.

Для заданного enum этот пакет генерирует специализированный класс Map с гарантией на этапе компиляции, что все константы этого enum присутствуют там как ключи:

@enumMap enum Fruit { apple, orange, banana }  final map = FruitMap(   apple: 1,   orange: 2,   banana: 3, );

В сгенерированном классе больше 190 строк, поэтому хранить его во внешнем файле — единственный разумный способ.

Тест будет вот таким простым:

import 'package:enum_map/enum_map.dart'; import 'package:source_gen_test/annotations.dart';  part 'output.dart';  @ShouldGenerateFile('output.dart', partOfCurrent: true) @enumMap enum Fruit {   apple,   orange,   banana, }  // Здесь обычные тесты, чтобы проверить, что класс FruitMap // ведёт себя, как обычный Map.

(На самом деле enum_map использует мой временный форк source_gen_test_golden, потому что мы с Кевином долго обсуждали некоторые мелочи, и мне пришлось опубликовать свой форк как отдельный пакет. Но с тех пор он подтянул мою правку в свой оригинальный пакет, поэтому мой форк больше не поддерживается. Используйте пакет Кевина.)

Между делом я переписал пакет enum_map с использованием макросов, и это убрало саму необходимость таких тестов (пока нет инструментов, чтобы писать golden‑тесты на код, генерируемый макросами, но сгенерированный ими код добавляется в текущую библиотеку и, во‑первых, ломает компиляцию при синтаксических ошибках, а во‑вторых, на него сразу же можно писать тесты без дополнительных инструментов). Поэтому предлагаю опробовать и новый enum_map тоже (см. версию пре‑релиз).

Не пропускайте мои статьи, добавляйтесь в Телеграм‑канал: ainkin_com
Русские переводы реже и с задержкой здесь: ainkin_com_ru


ссылка на оригинал статьи https://habr.com/ru/articles/863118/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *