Не понимаю, как применить TDD в проекте

Всем доброго времени суток!

Уже который год в компании пытаемся начать использовать TDD. Всё время останавливаемся по одной и той же причине: очень много логики завязано на данные.

Вот текущий пример: мы делаем систему по отслеживанию расходов сотрудников компании на определённые нужды. Ежемесячно на веб-сайт загружаются счета, парсятся, информация по расходам (кто, сколько, куда) аккуратненько раскладывается по нескольким табличкам. Каждый сотрудник может зайти на страничку, увидеть свои ежемесячные расходы, сравнить с лимитом, расстроиться при его превышении. Начальник может посмотреть информацию по всем своим подчинённым и т.д. Есть интерфейс загрузки новых счетов и просмотра деталей по старым, отчёты (с экспортом в Excel), админка, права-роли.

Звучит на словах просто, но багов и кода — не так уж и мало. С какой стороны подойти к разработке тестов? 90% функционала опирается на данные в БД, которые нужно где-то брать. Если у кого-нибудь есть опыт в подобном, подскажите!
  • Вопрос задан
  • 5840 просмотров
Пригласить эксперта
Ответы на вопрос 7
Inori
@Inori
Используйте фейковые данные, подогнанные специально под тесты. Обычно fixtures называются.
Ответ написан
ishua
@ishua
Для юнит тестов обычно много данных не нужно, для того кол-ва что есть, создаются mock objects с фиктивными данными.
Ответ написан
LeoCcoder
@LeoCcoder
я так понимаю проект уже готов? поэтому применять TDD уже поздно, потому что основной девелопинг уже закончился.
Как бы я поступил:
Вы нашли баг, разобрались в каком компоненте системы он происходит, поняли какие входные данные нужно подсунуть компоненту, чтобы произошле баг, поняли какие данные должны получится на выходе компонента, если бы бага не было, пишете тест:
берете тестовые данные, запускаете на них ваш компонент, смотрите что получилось на выходе.

testData =…
expectedResult =…
result = youtSytemComponent.superProcessor(testData);
if (result == expectedResult) return TestSucces;
else return TestFail;

так постепенно у вас будут накапливаться тесты и вы уже не испортите, то что уже исправляли.
Базу данных настоящую использовать не обязательно, можно для тестов написать обманку, которая будет притворяться базой. Компоненты системы желательно выбирать как можно меньше, например, компонент обычно это какойто класс, созданные для определенных целей, нужно проверить правильно ли он их решает.

не все можно провестировать с помощью TDD, BDD тоже полезная вещь.
Ответ написан
pfa
@pfa
Когда я впервые познакомился с ТДД — тоже было желание впихнуть его везде.
Прежде всего надо понимать, что ТДД — не панацея и в условиях современных проектов имеет достаточно узкую применимость, потому как хорошо работает только там, где бизнес-логика хорошо локализована и код при этом слабосвязанный.

У вас, как я понял:
1) часть бизнес-логики унесена в хранимки
2) сложная доменная модель
3) есть UI

В этом случае я бы советовал без фанатизма покрывать юнит-тестами то, что покрывается в процессе работы над текущими задачами, а основной упор сделать на интеграционные и UI-тесты.
Ответ написан
creage
@creage
Не уверен, на сколько мой пост будет полезен, но хочу отметить, что юнит-тестами стоит покрывать только публичные методы, public API, т.е. тот код, от которого зависят другие компоненты системы.

К примеру — есть код, который принимает что-то, и генерит что-то. Вот тут тестируем то, что он правильно принял, и вывел. Всю сопутствующую логику можно опустить.

По крайней мере мы делаем именно так.
Ответ написан
Комментировать
pletinsky
@pletinsky
Во первых Вас следует разобраться что вообще такое модульные тесты. Как правило если речь о классическим модульных тестов в рамках TDD — то это тесты на методы класса в полном отрыве от внешнего окружения. Это значит что не только данные из базы там не могут оказаться, а вообще не должно быть каких либо вызовов за пределы класса. Все мокируется. Как правило TDD (если его умеют готовить) ускоряет написание кода (хотя вы можете услышать и иное мнение — но оно неверно). И имеет массу полезных побочных эффектов, но недешево в поддержке (хотя окупается за счет большей стабильности системы).
Такие тесты требуют архитектурной готовности системы. Например ваши бизнес энтити из базы должны реализовывать какой то интерфейс для мокирования. Чаще всего юнит тесты не окупятся на уже написанном проекте.

Поймите, чего вы хотите добиться. Если Вам нужна стабильность работы каких то определенных «злых» модулей программы пишите интеграционные тесты.
Если вы хотите добиться стабильности системы по отношению к требованиям — пишите системные тесты, которые работают с приложением как с черным ящиком. Есть много наработок в этой области в рамках BDD подхода.
Если у вам не формализованы требования — первым делом этим и займитесь — иначе никакие тесты вам не помогут.
Ответ написан
@meettya
ИМХО — проблема сложности написания тестов обычно вытекает из размеров тестируемого кода.
Сложно написать тесты на кусок в 2 csloc, который разве что кофе не варит.
Если изначально с кодом не сложилось и у вас легаси, то тесты можно будет прикрутить только после рефакторинга.
Расщепляете логику на небольшие куски, которые делают мало работы и покрываете эти куски тестами.

А сейчас у вас классическая проблема — вы пытаететь съесть слона целиком :)

PS. Интеграционные тесты — штука хрупкая, можно намучится, особенно если изменения часто в коде бывают.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы