TDD: методы только для тестирования

Ищите какие-то практические советы здесь и любой опыт, который люди имели в подобной ситуации.

Мы используем методологию sytle для BDD/TDD для создания нашего программного обеспечения (довольно большое/сложное приложение). Конечным результатом является.. поведенческие спецификации (заданный/когда/тогда стиль), основанный на бизнес-требованиях, модульные тесты, которые отражают эти и код, который отражает требования тестов.

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

Проблема заключается в том, что некоторые из репозиториев Entity не имеют методов удаления, поскольку пока еще не было требований для бизнеса. Многие из них имеют архив /Reinstate/backup и т.д. (И могут иметь отложенные запросы на отставание).

Итак, теперь у нас есть тестовый отдел. требование для удаления (но которое конфликтует с историями бизнес-пользователей)

Итак... Мой вопрос: если я должен добавить методы специально для тестового отдела... что это лучший способ справиться с этим. Я понимаю, что это обычно считается плохой практикой в ​​ "TDD Utopia", но реалистично, как вы справлялись с таким конфликтом?

Первые мысли, которые у меня были, - это использование именования...

void TestOnly_Delete(Guid id){} 

... атрибуты...

[TestOnly]
void Delete(Guid id){}

... или директивы компилятора...

#if TESTBUILD
void Delete(Guid id){}
#endif

Итак, как минимум, разработчики могут знать, что не следует вызывать методы TestOnly и максимум, методы тестирования не развертываются в производственных сборках.

... или просто обмануть и добавить историю пользователей, чтобы управлять им таким образом; -)

Любой опыт или совет с благодарностью оценили?

Спасибо заранее.

Ответы

Ответ 1

Ваша первая проблема должна заключаться в том, что добавление этой функциональности увеличивает или ухудшает текущий API? Типичный сценарий в TDD состоит в том, что член класса (изначально) требуется только для проверки, но он соответствует всем нормативным нормам проектирования API, поэтому он не наносит вреда (и часто впоследствии оказывается ценным дополнением к производственному коду как а).

Если это правда, тогда обязательно добавьте его, если вы можете сделать это легко.

Иногда, однако, дело обстоит наоборот. В этом случае вы должны противостоять желанию добавить участника. Однако часто вы можете следовать Open/Closed Principle и открывать свой API, чтобы другие могли добавлять желаемые функции. Testability - это просто другое слово для принципа Open/Closed.

В вашем случае простейшим решением может быть просто убедиться, что классы, о которых идет речь, не распечатаны, а затем попросите Test Department получить эти классы и реализовать сами функции. Если у них нет этой возможности, вы можете сделать это для них, сохраняя при этом только подклассы.

Ответ 2

В моем коде я создаю подкласс: например, если у меня есть класс DataLayer, который имеет все общедоступные методы для доступа к слою данных, тогда я могу подклассифицировать его подклассом Test_DataLayer, который наследует методы от DataLayer и, кроме того, реализует любые дополнительные методы, которые вам могут понадобиться как Delete, и реализация которых может обращаться к внутренним или защищенным методам базового класса.

Ответ 3

Я обычно заканчиваю проект/библиотеку только для тестирования, поддерживая все классы макета/помощника, которые мне нужны для моих тестов. Добавление необходимых классов/методов в эту макетную библиотеку, которая не входит в производственный код, кажется естественным подходом для этого требования. Если у вас еще нет такой библиотеки и вы не хотите ее создавать, я бы помечал - если возможно - методы внутренние и только подвергал их тестированию. Вы не указываете платформу, но я знаю, что это возможно с помощью С#/. NET, и я часто использую эту способность, чтобы дать моим тестам доступ к методам, которые в противном случае были бы недоступны вне библиотеки.

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

Ответ 4

Это интересный вопрос. Я подумал, но не уверен, будет ли это ответ на вашу проблему.

Я лично создам экслизированный набор интерфейсов, наследующий от того, что у вас уже есть для объекта, такого как IIntTest_Customer: ICustomer, и определите метод удаления там. Если возможно, попробуйте поместить весь этот интерфейс в отдельный проект, чтобы разработчик даже не ссылался на него из обычного проекта и избегал случайного их использования. Затем испытательный отдел будет использовать эти специальные интерфейсы для тестирования для целей тестирования.

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

Ответ 5

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

Существует так много альтернатив: от интеллектуального управления транзакциями до автоматического восстановления баз данных.