Поиск некоторого практического совета здесь и любых людей событий имел в аналогичной ситуации.
Мы используем BDD/TDD sytle методология для создания нашего программного обеспечения (вполне большое / сложное приложение), конечный результат.. поведенческие спецификации (Стиль Given/When/Then) полученный из бизнес-требований, модульные тесты, которые отражают их и код, который отражает требования тестов.
Однако недавно наш испытательный цех начал выполнять интеграционные тесты, и понятно они хотят использовать наш (уже передающий) код бизнес-логики, чтобы настроить и разъединить тестовое состояние (вместо того, чтобы иметь необходимость иметь дело непосредственно с базой данных), как они главным образом обеспокоены тестированием через UI приложения и не хотят тратить весь день базы данных пререкания.
Проблема, некоторые Репозитории Объекта не имеют, удаляют методы, поскольку еще не было никакого бизнес-требования, выраженного для них. Многие имеют, Архивируют/Восстанавливают/копируют и т.д. (и может иметь, удаляют ожидание на отставании).
Таким образом, теперь у нас есть тестовое требование отдела для удаления (но тот, который конфликтует с историями бизнес-пользователя),
Так.... Мой вопрос состоит... в том, если я должен был добавить методы специально для испытательного цеха... what't лучший способ обработать их. Я понимаю, что это обычно считают плохой практикой в "Утопии TDD", но реалистично, как Вы имели дело с этим видом конфликта?
Первые мысли, которые я имел, являются любой именованием использования...
void TestOnly_Delete(Guid id){}
... атрибуты...
[TestOnly]
void Delete(Guid id){}
... или директивы компилятора...
#if TESTBUILD
void Delete(Guid id){}
#endif
Так как минимум разработчики могут знать для не вызова методов TestOnly и в максимуме, методы тестирования не развертываются в производственных сборках.
... или просто обманите и добавьте пользовательскую историю для управления им тот путь;-)
Опыт или совет с благодарностью ценятся?
Заранее спасибо.
Ваша первая проблема должна быть : добавление этой функции улучшает или ухудшает текущий API? Типичный сценарий в TDD - это член класса (изначально) требуется только по причине тестируемости, но он соответствует всем нормальным рекомендациям по проектированию API, поэтому не причиняет вреда (и часто впоследствии оказывается ценным дополнением в производственном коде).
Если это правда, то непременно просто добавьте , если вы можете сделать это легко .
Однако иногда бывает и обратное. В этом случае вы должны сопротивляться желанию добавить участника. Однако часто вы можете следовать Принципу открытости / закрытости и открыть свой API, чтобы другие могли добавить желаемую функциональность. Тестируемость - это просто другое слово для принципа открытости / закрытости .
В вашем случае самое простое решение может заключаться в том, чтобы просто убедиться, что рассматриваемые классы распечатаны, а затем попросить отдел тестирования наследовать от этих классов и реализовать функциональность самостоятельно. Если у них нет такой возможности, вы можете сделать это за них, оставив подклассы только для тестирования.
В своем коде я создаю подкласс: например, если у меня есть класс DataLayer
, который имеет все публичные методы для доступа к слою данных, то я могу подклассифицировать его подклассом Test_DataLayer
, который наследует методы от DataLayer
и который, кроме того, реализует любые дополнительные методы, которые вы можете захотеть, например Delete
, и реализация которого может получить доступ к внутренним или защищенным методам базового класса.
Обычно я получаю проект / библиотеку «только для тестирования», в которых хранятся все макеты / вспомогательные классы, которые мне нужны для моих тестов. Добавление необходимых классов / методов в эту фиктивную библиотеку, которая не включена в производственный код, кажется естественным соответствием этому требованию. Если у вас еще нет такой библиотеки и вы не хотите ее создавать, я бы отметил - если возможно - внутренние методы и предоставил бы их только среде тестирования. Вы не указываете платформу, но я знаю, что это возможно с C # /. NET, и я часто использую эту возможность, чтобы предоставить своим тестам доступ к методам, которые в противном случае были бы недоступны за пределами библиотеки.
С другой стороны, я бы сказал, что тестировщики являются такой же частью вашего анализа требований, как и фактические клиенты. Точно так же, как у нас есть некоторые требования, которые предназначены исключительно для наших нужд разработки, у нас также есть некоторые требования для тестирования. Уловка, как вы обнаружите, состоит в том, чтобы разработать код таким образом, чтобы все потребности заинтересованных сторон были удовлетворены в максимально возможной степени. Когда потребности конфликтуют, мы стараемся найти наилучший возможный компромисс. ИМО, возможность удаления из библиотек, предназначенных только для тестирования, является разумным компромиссом с потребностью клиента в безопасности данных (без удаления).
Я никогда не буду добавлять в свой код методы удаления или другие методы очистки только для поддержки автоматического тестирования.
Существует так много альтернатив, от интеллектуального управления транзакциями до автоматического восстановления баз данных.
Это интересный вопрос. У меня есть некоторые мысли, но я не уверен, что это станет ответом на вашу проблему.
Я лично создам явный набор интерфейсов, унаследованных от того, что у вас уже есть для объекта, такого как IIntTest_Customer: ICustomer, и определю там метод удаления. Если возможно, попытайтесь поместить все эти интерфейсы в отдельный проект, чтобы разработчик даже не имел ссылки на него из обычного проекта и избегал их случайного использования. Затем отдел тестирования будет использовать этот конкретный внутренний тестовый интерфейс для своих целей тестирования.
Для этого вам, возможно, придется реорганизовать текущий код и изменить сущность, чтобы вместо этого реализовать эти внутренние тестовые интерфейсы, а с иерархией наследования весь ваш существующий код, который ссылается на базовый интерфейс, должен по-прежнему работать.