Рабочий процесс Tdd при обнаружении нарушения принципа единой ответственности

Я пытаюсь следовать TDD. Итак, вот моя проблема

У меня есть интерфейс Risk с методом

boolean check(...)

Risk1 и Risk2 - это тестовые внедрения, разработанные в первую очередь, поэтому теперь они полностью покрыты. Я решил, что модуль, проверяющий все риски (CompositeRisk), также может реализовать Risk. CompositeRisk применяет операцию ИЛИ к каждому результату Risk1 и Risk2 (если один риск верен, то все это рискованно). Тем не менее, все тестируется в первую очередь.

Теперь я смотрю на один из рисков и думаю - у этого есть слово "И" и проверяет разные поля. Кажется, я могу разделить его на два объекта и создать еще один CompositeAndRisk, который будет применять И к обоим разделенным рискам. Таким образом, я мог построить DSL для дерева принятия решений по рискам (кажется хорошим, потому что правила рисков могут сильно измениться).

Итак, что мне делать с раздельными тестами риска? Должен ли я переименовать i в CompositeAndRiskTest? я должен удалить его?, я должен написать тест для splitClasses?


person timoras    schedule 06.08.2014    source источник


Ответы (2)


Прежде всего, я предлагаю вам превратить класс CompositeRisk в интерфейс и иметь от него два отдельных подкласса: CompositeOrRisk и CompositeAndRisk. Впрочем, это касается только дизайна.

Что касается вашего вопроса, я считаю, что нет единственно правильного ответа, поэтому позвольте мне поделиться своим видением этого.
Как вы знаете, в TDD есть конкретные шаги, которым вы следуете (которые составляют цикл TDD), и есть определенное состояние, в котором тесты должны быть в промежутке между каждым из них. Вот что я имею в виду:

[State = No tests]  
1. Write a test that fails  
[State = Test fails]
2. Write as little code as possible in order for the test to pass  
[State = Test passes]  
3. Refactor  
[State = Test still passes]

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

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

person ethanfar    schedule 07.08.2014
comment
Моя идея состояла в том, чтобы переименовать CompositeRisk в CompositeOrRisk. Создайте CompositeAndRisk. Оба реализуют риск (тот же интерфейс, что и компонент). Вероятно, я мог бы переименовать класс, который я хочу разделить, на CompositeAndRisk и извлечь функциональность в новые классы. Но, похоже, мой тест сейчас проверит ненужные детали. Ваше предложение разделить тесты кажется оптимальным - person timoras; 07.08.2014
comment
Я примерно об этом и говорю. Единственное, что я хотел бы рассмотреть помимо этого, это иметь общий интерфейс CompositeRisk для CompositeOrRisk и CompositeAndRisk, так как вы, возможно, захотите добавить еще несколько композитов позже и, возможно, добавить к нему функциональность (сделать его расширяющим Iterable<Risk> или что-то в этом роде). ). - person ethanfar; 07.08.2014

Подход, который я бы выбрал в этом случае, заключается в следующем: "притвориться невиновным". первый.

Случай «И» здесь — явно новый функционал. В этот момент не нужно изменять содержимое существующего теста, просто создайте еще один тест с именем, которое отражает новое требование, например CompositeAndRiskTest, и создайте соответствующую реализацию.

Затем, на этапе рефакторинга, «осознайте», что два предыдущих объекта — это две стороны одной медали, и соответствующим образом отрефакторите их. Это может означать просто переименование CompositeRisk в CompositeOrRisk или более сложные вещи.

После того, как 2 вида рисков определены, протестированы и реализованы, вы можете продолжить и создать новые тесты для их комбинаций.

person guillaume31    schedule 07.08.2014