Насколько я понимаю, большинство людей, похоже, согласны с тем, что частные методы следует тестировать не напрямую, а с помощью любых открытых методов, которые их вызывают. Я вижу их точку зрения, но у меня возникают некоторые проблемы с этим, когда я пытаюсь следовать «трем законам TDD» и использовать цикл «красный - зеленый - рефакторинг». Я думаю, что это лучше всего объяснить на примере:
Сейчас мне нужна программа, которая может прочитать файл (содержащий данные, разделенные табуляцией) и отфильтровать все столбцы, которые содержат нечисловые данные. Я думаю, что, вероятно, уже есть несколько простых инструментов для этого, но я решил реализовать их с нуля, в основном потому, что решил, что это может быть хорошим и чистым проектом для меня, чтобы немного попрактиковаться в TDD.
Итак, во-первых, я «надеваю красную шляпу», то есть мне нужен тест, который не проходит. Я подумал, мне понадобится метод, который находит все нечисловые поля в строке. Поэтому я пишу простой тест, конечно, он не может быть скомпилирован немедленно, поэтому я начинаю писать саму функцию, и после пары циклов назад и вперед (красный / зеленый) у меня есть рабочая функция и полный тест.
Далее, я продолжаю с функцией «collectNonNumericColumns», которая читает файл, по одной строке за раз, и вызывает мою функцию «findNonNumericFields» в каждой строке, чтобы собрать все столбцы, которые в конечном итоге должны быть удалены. Пару красно-зеленых циклов, и я закончил, снова имея рабочую функцию и полный тест.
Теперь я решил, что мне следует провести рефакторинг. Так как мой метод "findNonNumericFields" был разработан только потому, что я решил, что он понадобится при реализации "collectNonNumericColumns", мне кажется, что было бы разумно, чтобы "findNonNumericFields" стал закрытым. Однако это сломало бы мои первые тесты, поскольку у них больше не было бы доступа к методу, который они тестировали.
Итак, я получаю приватные методы и набор тестов, которые его проверяют. Так как многие люди советуют не проверять частные методы, я чувствую, что я загнал себя в угол. Но где именно я потерпел неудачу?
Я полагаю, что я мог бы начать с более высокого уровня, написав тест, который проверяет то, что в конечном итоге станет моим публичным методом (то есть findAndFilterOutAllNonNumericColumns), но это несколько противоречит цели TDD (по крайней мере, согласно дяде Бобу) : Вы должны постоянно переключаться между написанием тестов и рабочим кодом, и что в любой момент времени все ваши тесты работали в последнюю минуту или около того. Потому что, если я начну с написания теста для общедоступного метода, у меня будет несколько минут (или часов, или даже дней в очень сложных случаях), прежде чем я получу все детали в частных методах для работы, чтобы тестирование общедоступного метода метод проходит.
Так что делать? Является ли TDD (с быстрым циклом красный-зеленый-рефактор) просто несовместимым с частными методами? Или есть ошибка в моем дизайне?
private
будто это имеет смысл сделать так.