Я пытаюсь отстаивать модульное тестирование в моей рабочей группе, но я часто получаю возражение, что его следует использовать только для экспортируемого извне API (который является только минимальной и некритической частью нашей системы), а не для внутреннего и частного код (который теперь имеет только функциональное тестирование).
Хотя я думаю, что юнит-тест можно и нужно применять ко всему коду, как я могу убедить своих коллег?
unit-testing
Wizard79
источник
источник
Ответы:
Ваши коллеги могут путать настоящие модульные тесты с интеграционными тестами. Если ваш продукт является (или имеет) API, интеграционные тесты могут быть запрограммированы как тестовые случаи NUnit. Некоторые люди ошибочно полагают, что это модульные тесты.
Вы можете попытаться убедить своих коллег в следующем (я уверен, что вы уже знаете это, все, что я говорю, это то, что указание на это вашим коллегам может помочь):
источник
Причины использования модульных тестов для внутреннего / частного кода точно такие же, как для внешне поддерживаемых API:
источник
Если вы имеете в виду частное, как я думаю, вы это имеете в виду, то нет - вам не следует это тестировать. Вы должны только проводить модульное тестирование наблюдаемого поведения / состояния. Возможно, вы упускаете точку за циклом «красный-зеленый-рефактор» TDD (и если вы сначала не проводите тестирование, то применяется тот же принцип). После того, как тесты написаны и пройдены, вы не хотите, чтобы они менялись при выполнении рефакторинга. Если вы вынуждены проводить модульное тестирование приватной функциональности, то это, вероятно, означает, что модульные тесты вокруг публичной функциональности имеют недостатки. Если сложно и сложно писать тесты для открытого кода, то, возможно, ваш класс делает слишком много или ваша проблема четко не определена.
Хуже того, со временем ваши юнит-тесты станут шариком и цепью, замедляя вас, не добавляя никакой ценности (изменение реализации, например, оптимизация или удаление дублирования, не должно влиять на юнит-тесты). Внутренний код должен, однако, быть проверен модулем, так как поведение / состояние можно наблюдать (только ограниченным образом).
Когда я впервые проводил модульное тестирование, я применял всевозможные трюки к частным тестам, но теперь, когда у меня за плечами несколько лет, я вижу это хуже, чем трата времени.
Вот немного глупый пример, конечно, в реальной жизни у вас будет больше тестов, чем они:
Допустим, у вас есть класс, который возвращает отсортированный список строк - вы должны проверить, отсортирован ли результат, а не то, как он на самом деле сортирует этот список. Вы можете начать реализацию с одного алгоритма, который просто сортирует список. Как только это будет сделано, ваш тест не нужно менять, если вы измените алгоритм сортировки. На данный момент у вас есть один тест (при условии, что сортировка встроена в ваш класс):
Теперь предположим, что вам нужно два алгоритма (возможно, один более эффективен в некоторых обстоятельствах, но не в других), тогда каждый алгоритм может (и, как правило, должен) предоставляться другим классом, и ваш класс выбирает их - вы можете проверить, происходит ли это для в выбранных вами сценариях используются макеты, но ваш первоначальный тест все еще действителен, и, поскольку мы только проверяем наблюдаемое поведение / состояние, его не нужно изменять. В итоге вы пройдете 3 теста:
В качестве альтернативы можно было бы начать тестирование частного кода внутри вашего класса - вы ничего от этого не получите - вышеприведенные тесты рассказывают мне все, что мне нужно знать, что касается модульного тестирования. Добавляя частные тесты, вы создаете себе прямую оболочку, сколько еще работы будет, если вы не только проверите, что результат был отсортирован, но и как он сортируется?
Тесты (такого типа) должны изменяться только при изменении поведения, начинать писать тесты для частного кода, и это выходит за рамки.
источник
Вот еще одна причина: в гипотетическом случае мне пришлось бы выбирать между модульным тестированием внешнего API и закрытыми частями, я бы выбирал частные части.
Если каждая закрытая часть покрыта тестом, API, состоящий из этих закрытых частей, должен быть покрыт почти на 100%, за исключением только верхнего уровня. Но это может быть тонкий слой.
С другой стороны, при тестировании только API может быть очень сложно полностью охватить все возможные пути кода.
источник
Трудно заставить людей принять модульное тестирование, потому что это кажется пустой тратой времени («мы могли бы кодировать другой проект, приносящий доход!») Или рекурсивным («И тогда мы должны написать тестовые случаи для тестовых случаев!») Я виновен в том, что сказал оба.
В первый раз, когда вы обнаружите ошибку, вы должны признать правду, что вы не совершенны (как быстро мы программисты забываем!), И вы говорите: «Хм».
Другим аспектом модульного тестирования является то, что код должен быть написан для тестирования. Понимание того, что Some Code легко тестируется, а Some Code не делает хорошего программиста «Хммм».
Вы спрашивали своего коллегу, почему модульное тестирование было полезно только для внешних API?
Один из способов показать ценность модульного тестирования - дождаться появления неприятной ошибки и затем показать, как модульное тестирование могло бы ее предотвратить. Это не втирает в их лица, а в их умах переносит юнит-тестирование из Теоретической Башни Слоновой Кости в реальность в окопах.
Другой способ - подождать, пока одна и та же ошибка не произойдет дважды . «Ухх, хорошо, Босс, мы добавили код для проверки на ноль после проблемы на прошлой неделе, но на этот раз пользователь ввел пустую вещь!»
Подавать пример. Напишите модульные тесты для ВАШЕГО кода, а затем покажите своему боссу значение. Затем посмотрите, не позвонит ли босс в пиццу на обед и не сделает презентацию.
Наконец, я не могу сказать вам облегчение, которое я испытываю, когда мы собираемся подтолкнуть к продукту, и я получаю зеленую полосу от юнит-тестов.
источник
Существует два вида закрытого кода: закрытый код, который вызывается открытым кодом (или закрытый код, вызываемый закрытым кодом, который вызывается открытым кодом (или ...)) и закрытый код, который в конечном итоге не вызывается открытым код.
Первый уже проверен с помощью тестов для открытого кода. Последнее не может называться вообще и , следовательно , должны быть удалены, не тестируются.
Обратите внимание, что при выполнении TDD для непроверенного частного кода невозможно существование.
источник
Модульное тестирование - это все о тестировании модулей вашего кода. Вам решать, что такое юнит. Ваши коллеги определяют единицы как элементы API.
В любом случае, тестирование API также должно привести к использованию частного кода. Если вы определите покрытие кода как индикатор прогресса модульного тестирования, вы в конечном итоге протестируете весь свой код. Если какая-то часть кода не была достигнута, предоставьте коллегам три варианта:
источник