Pull to refresh

Comments 5

О, ровно по этой же проблеме вопрос, может чего интересного подскажете.
Данные очень часто нужны прям 1в1 на нужный кейс, когда зависимости между сущностями из разряда A->B->C->D и такие данные никто кроме нашего конкретного теста переиспользовать не может.
В итоге, на сотню другую тестов у нас оказывается порядка 30-40 наборов данных для тестов и они внезапно всё равно создаются копипастой (или дурацкими переусложнёнными билдерами, которые зато спасают от копипасты местами).
Так вот, к чему я всё пишу — при внезапном изменении модели и\или бизнес логики все эти сотни тестов и десятки наборов данных всё равно становятся неактуальными или битыми, проверять почему посыпались тесты всё равно приходится руками. Или у вас другой опыт?

В случае, если наборы данных более-менее одинаковые (общего больше, чем различий), то неплохо помогает следующий паттерн их создания. Сначала всегда создаём "базовый набор данных", одинаковый и неизменный для всех тестов. Затем каждый индивидуальный тест накладывает свои "патчи" на этот набор данных. Основные плюсы такие:


  1. Тесты становятся гораздо более наглядными — становится ясно, какие именно данные приводят к требуемому изменению поведения.
  2. Новые тесты становится писать гораздо проще.
  3. При изменении требований к базовому набору нужно делать правки только в одном месте, а не во всех.

Для небольших проектов вариант может хорошо заходить, но с увеличением проекта и количества тестов базовый набор будет расти, и правки в нем могут каскадно валить кучу тестов.

У меня был как раз такой опыт. Меняем контракты — ничего не компилится и нужно править тесты в 20 местах. Или еще хуже, компилится, но тесты вываливаются с какой-нибудь общей проблемой, типа HTTP 500 или неинформативным исключением.


Один из способов с этим справиться — по максимуму убирать все неважные детали данных за пределы тестов. Самое сложное — описать свою схему/модель такой структурой, которая бы с одной стороны была полной, т.е. покрывала все сущности и удовлетворяла все зависимости, а с другой — не принимала в себя ничего лишнего, ну и чтобы с ней было удобно работать.


В моем примере, это PackageEntry, который содержит только связи других сущностей с Package. В теле теста мы описываем только табличку значений, из которых делаем PackageEntry — по сути, только говорим сколько и каких дефолтных объектов нам нужно — и оверрайды полей, а все остальные трансформации происходят за пределами теста. Этот пример будет хорошо работать с неплотными данными, если бОльшая часть полей в бОльшей части объектов не имеет значение в конкретном тесте (справочные данные, а не какая-нибудь хардкорная статистика).


Если модель поменяется некардинально (изменятся какие-то поля или добавятся новые сущности), то фикстуры, в целом, останутся актуальными — нужно будет только поправить конвертацию ключей в строки (Enrich) и линзы для оверрайдов. Если изменения такие, что прям таблицы удаляются из базы, то будут проблемы, но мне кажется такое бывает крайне редко. Если поменяется бизнес-логика — правим табличку с данными.


А от того, чтобы проверять руками, почему посыпались тесты, неплохо спасают подробные логи. Чем больше тесты несут читабельной информации о себе и о системе, тем легче с ними работать и тем они полезнее.

Примерно так же стараемся делать, но это дофига накладных на всё вокруг, что печалит.

Да, логи хорошо помогают, причем логи нужны не хуже продуктовых, понятные, простые, подробные.
Sign up to leave a comment.