Стратегия рефакторинга для класса, который генерирует определенный текстовый файл - PullRequest
1 голос
/ 05 мая 2009

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

Как должны выглядеть эти тесты? Собственно основная цель - не нарушать структуру файла. Но это не значит, что я должен сравнивать содержимое файла до и после?

Ответы [ 4 ]

1 голос
/ 05 мая 2009

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

Теперь приступим к рефакторингу. Извлеките метод - или, лучше, напишите тест для метода, который вы можете себе представить, настоящий модульный тест - извлеките метод и убедитесь, что все тесты, для нового маленького метода и для более крупной системы, все еще проходят. Вспенить, промыть, повторить. Системные тесты дают вам сеть безопасности, которая позволяет вам уверенно продвигаться в рефакторинге; модульные тесты определяют дизайн нового кода.

Существуют библиотеки, облегчающие такое тестирование (хотя это довольно легко даже без них). Смотри http://approvaltests.sourceforge.net/.

1 голос
/ 05 мая 2009

На самом деле, это довольно хорошее место для начала (сравнение хорошо известного вывода с тем, что генерируется текущим классом). Если класс одного генератора может давать разные результаты, то создайте его для каждого случая. Это гарантирует, что вы не нарушаете свой текущий класс генератора.

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

1 голос
/ 05 мая 2009

Если вы еще этого не сделали, возьмите книгу Майкла Фезерса " Эффективная работа с устаревшим кодом ". Это все о том, как добавить тесты в существующий код, а это именно то, что вы ищете.

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

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

По пути вы можете найти объекты, которые хотят выбраться. Например, вы можете обнаружить, что код (или тесты!) Был бы проще, если бы существовал отдельный класс, который генерирует одну строку вывода. Смирись с этим. У вас есть регрессионный тест, чтобы поймать вас, если вы что-то напортачили.

Неуклонно работайте над удалением зависимостей (но убедитесь, что у вас есть высокоуровневый тест, такой как регрессионный тест, чтобы ловить вас, если вы делаете ошибки). Если ваш класс создает свой собственный FileStream и выполняет запись в файловую систему, измените его на взятие TextWriter в своем конструкторе, чтобы вы могли писать тесты, которые передают StringWriter и никогда не касаются файловой системы. Как только это будет сделано, вы можете избавиться от старого теста, который записывает файл на диск (но только если вы не сломали его при попытке записать новый тест!) Если вашему классу требуется соединение с базой данных, проводите рефакторинг, пока не сможете написать тест, который проходит в поддельные данные. И т.д.

1 голос
/ 05 мая 2009

В таком случае я использую следующую стратегию:

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

  • Запустите инструмент покрытия кода и найдите блоки, не охваченные тестами. Написать тесты, охватывающие эти блоки.

  • Делайте это, пока не получите покрытие кода более 80%

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

  • Используйте Test Driven Development для написания новых классов.

...