Модульное тестирование и инкапсуляция - PullRequest
2 голосов
/ 08 января 2010

Я пытаюсь пройти модульное тестирование, но меня беспокоит одна вещь.

У меня есть класс php, который я хочу протестировать. Он принимает некоторые параметры, а затем выплевывает HTML. Проблема в том, что основной функциональностью является вычисление некоторых значений и условий, которые я хочу проверить. Но я поместил это в приватный метод, потому что обычно никто не должен знать об этом методе. Но таким образом я не могу провести модульное тестирование класса, потому что у меня нет средств для проверки результата метода.

Я нашел эту статью на эту тему. В заключении статьи используется рефлексия для проверки приватных методов.

Как вы против этого предмета?

Ответы [ 6 ]

11 голосов
/ 08 января 2010

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

Как правило:

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

Если вы можете удалить приватные методы, не нарушая общедоступные методы, вам не нужны приватные методы, и вы можете удалить их.

Если вы не можете удалить приватные методы, не нарушив общедоступные методы, тогда приватные методы тестируются.

Если вы следуете практике TDD, вам будет трудно попасть в эту ситуацию, потому что каждая строка кода написана для прохождения модульных тестов. В вашем классе не должно быть «случайного» кода.

2 голосов
/ 08 января 2010

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

(Использование рефлексии для тестирования частных методов звучит для меня очень плохой идеей.)

1 голос
/ 08 января 2010

Модульное тестирование - это повышение вероятности правильности исполнения.

Инкапсуляция - это минимизация числа потенциальных зависимостей с наибольшей вероятностью распространения изменений.

Модульное тестирование касается времени выполнения; инкапсуляция о исходном коде.

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

Скопируйте весь исходный код в тестовый каталог, а затем удалите все экземпляры модификатора "private". Затем напишите свои тесты в эту, деприватизированную директорию. Это отделяет модульное тестирование от проблем инкапсуляции.

Автоматизируйте это копирование, деприватизацию и модульное тестирование, используя скрипт, подобный приведенному ниже.

С уважением,

Ed.

! / Bin / Баш

rm -rf code-copy

эхо Создание кода-копии ...

MKDIR код-копия

cp -r ../www code-copy /

для меня в find code-copy -name "*php" -follow; делать

sed -i 's/private/public/g' $i

сделано

php run_tests.php

0 голосов
/ 19 января 2010

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

0 голосов
/ 08 января 2010

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

То, что вы также можете сделать, - это сделать метод общедоступным, но ретранслировать какое-то соглашение об именах для обозначения его конфиденциальности: например, privateGetNumberOfPages() или _getNumberOfPages(). Это будет моральная инкапсуляция : это не помешает кому-либо ссылаться на метод, но никто не может сказать, что он не знал, что он был закрытым.

Таким образом, вы можете вызвать метод в своем модульном тесте, но документально (не принудительно) это частный метод. Это хорошо работает в некоторых командах, но не во всех.

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

0 голосов
/ 08 января 2010

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

Если вы хотите проверить рендеринг (и вам следует), сделайте это отдельно.

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

При такой настройке не будет закрытых методов для тестирования.

...