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

13

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

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

Должен ли я выполнить рефакторинг своего тестового кода после того, как я закончу? IE: создать ExtractedClassTest и перенести в него все соответствующие тесты из OriginalClassTest? Кажется, что это может быть немного рискованно: я могу потерять некоторую информацию в процессе, это может быть не так просто, как перенести тест, и я бы в конечном итоге переписал какой-то тестовый код, который, как я знаю, работал, но может больше не работать, и т.п.

С другой стороны, если я оставлю OriginalClassTest как есть, я вижу, что это проблема с тестовым обслуживанием. Будет немного странно найти тесты ExtractedClass. Ваше первое впечатление будет, что он не существует. Со временем при большом количестве рефакторингов производственного кода это может стать серьезной проблемой.

Я новичок в TDD, поэтому я хотел бы получить совет эксперта. Благодарность!

Даниэль Каплан
источник

Ответы:

7

После просмотра этого удивительного выступления «Ян Купер: TDD, где все пошло не так», я не согласен с @pdr. Я думаю, что вы должны оставить только оригинальные тесты. Ваша способность реорганизовывать тестируемую систему без поломок, написания или изменения каких-либо тестов - вот основная цель написания тестов.

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

Даниэль Каплан
источник
6

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

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

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

Потому что вы правы, вы не хотите уходить с обслуживающим кошмаром. Но вы не хотите меньше пути, чем раньше.

прецизионный самописец
источник
1
Я только что сделал это, и я должен сказать, что это довольно демотивирует. Несмотря на то, что мои изменения были простыми, потребовалось около 2 часов, чтобы убедиться, что я правильно реорганизовал свои тесты, и у меня все тот же охват. Стало очевидно, что я должен добавить несколько дополнительных тестов к новому тесту, просто чтобы убедиться, что я проверяю вещи. Я чувствую, что было бы более эффективно извлечь класс и оставить две системы под контролем. Этот объем работы говорит о том, что я плохо написал тесты?
Даниэль Каплан
1
@tieTYT: Трудно ответить, не сидя там и наблюдая за тобой. Иногда TDD кажется больше работы, чем стоит. В других случаях вам напоминают, почему вы беспокоились. А в другой раз, это ты усложняешь. Научиться понимать разницу - большая часть успеха в TDD.
фунтовые
Как вы думаете, возможно ли, что в этом случае я не должен был рефакторинг своих тестов, или вы думаете, что это маловероятно?
Даниэль Каплан
1
@tieTYT: вряд ли да. Невозможно, нет
фунтовые