Сколько тестов на метод?
Ну, теоретический и крайне непрактичный максимум - сложность N-Path (предположим, что все тесты охватывают код различными способами;)). Минимум ОДИН !. Для открытого метода, то есть он не тестирует детали реализации, только внешние поведения класса (возвращают значения и вызывают другие объекты).
Вы цитируете:
* И мысль о тестировании каждого из ваших методов с помощью собственного метода тестирования (в соотношении 1: 1) будет смешной. *
а затем спросите:
Итак, если создание теста для каждого метода «смешно», как и когда вы выбрали то, для чего пишете тесты?
Но я думаю, что вы неправильно поняли автора здесь:
Идея « one test method
пер» one method in the class to test
- это то, что автор называет «смехотворным».
(По крайней мере, для меня) Это не о «меньше», а о «больше»
Итак, позвольте мне перефразировать, как я понял его:
И мысль о тестировании каждого из ваших методов ТОЛЬКО ОДНЫМ МЕТОДОМ (его собственный метод тестирования в соотношении 1: 1) будет смешной.
Чтобы процитировать вашу цитату снова:
Когда вы понимаете, что все дело в определении поведения, а не в написании тестов, ваша точка зрения меняется.
Когда вы практикуете TDD, вы не думаете :
У меня есть метод, calculateX($a, $b);
и ему нужен тест, testCalculcateX
который проверяет ВСЕ о методе.
TDD говорит вам о том, что ваш код ДОЛЖЕН ДЕЛАТЬ :
Мне нужно вычислить большее из двух значений ( первый тестовый случай! ), Но если $ a меньше нуля, то это должно привести к ошибке ( второй тестовый случай! ), А если $ b меньше нуля, это должно произойти .... ( третий тестовый кейс! ) и тд.
Вы хотите проверить поведение, а не только отдельные методы без контекста.
Таким образом, вы получаете набор тестов, который является документацией для вашего кода и ДЕЙСТВИТЕЛЬНО объясняет, что он должен делать, возможно, даже почему :)
Как вы решаете, для какой части вашего кода вы создаете модульные тесты?
Что ж, все, что попадает в хранилище или где-то рядом с производством, нуждается в проверке. Я не думаю, что автор ваших цитат не согласился бы с этим, как я пытался заявить в вышесказанном.
Если у вас нет теста для него, становится намного сложнее (дороже) изменить код, особенно если это не вы вносите изменения.
TDD - это способ гарантировать, что у вас есть тесты на ВСЕ, но пока вы ПИШИТЕ тесты, все в порядке. Обычно написание их в один и тот же день помогает, потому что вы не собираетесь делать это позже, не так ли? :)
Ответ на комментарии:
приличное количество методов не может быть протестировано в определенном контексте, потому что они либо зависят, либо зависят от других методов
Есть три вещи, которые эти методы могут вызывать:
Публичные методы других классов
Мы можем смоделировать другие классы, чтобы мы определили состояние там. Мы контролируем контекст, так что это не проблема.
* Защищенные или частные методы на том же *
Все, что не является частью общедоступного API класса, обычно не тестируется напрямую.
Вы хотите проверить поведение, а не реализацию, и если класс выполняет все, он работает в одном большом публичном методе или во многих меньших защищенных методах, которые вызываются, является реализацией . Вы хотите иметь возможность ИЗМЕНИТЬ эти защищенные методы БЕЗ касания ваших тестов. Потому что ваши тесты сломаются, если ваш код изменит поведение! Вот для чего нужны ваши тесты, чтобы сказать вам, когда вы что-то сломаете :)
Открытые методы в одном классе
Это случается не очень часто, не так ли? И если это так, как в следующем примере, есть несколько способов справиться с этим:
$stuff = new Stuff();
$stuff->setBla(12);
$stuff->setFoo(14);
$stuff->execute();
То, что сеттеры существуют и не являются частью сигнатуры метода execute, является другой темой;)
Что мы можем проверить здесь, так это то, что, если execute устанавливает значение, когда мы устанавливаем неправильные значения Это setBla
выдает исключение, когда вы передаете строку, может быть протестировано отдельно, но если мы хотим проверить, что эти два допустимых значения (12 и 14) не работают ВМЕСТЕ (по какой-либо причине), чем это один тестовый пример.
Если вам нужен «хороший» набор тестов, вы можете, в php, возможно (!) Добавить @covers Stuff::execute
аннотацию, чтобы убедиться, что вы генерируете только покрытие кода для этого метода, а другие просто настраиваемые вещи нужно тестировать отдельно (опять же, если ты хочешь это).
Итак, суть в том, что сначала вам нужно создать какой-то окружающий мир, но вы должны быть в состоянии написать значимые тестовые примеры, которые обычно охватывают только одну или, возможно, две реальные функции (сеттеры здесь не учитываются). Остальные могут быть издевались над эфиром или сначала проверяться, а затем полагаться (см. @depends
)
* Примечание: вопрос был перенесен из SO и изначально касался PHP / PHPUnit, поэтому пример кода и ссылки взяты из мира php, я думаю, что это также применимо к другим языкам, так как phpunit не так сильно отличается от других xUnit рамки тестирования.