LINUX.ORG.RU

Когда писать модульные тесты (unit tests)?


0

1

Когда в жизни проекта наступает момент, в который необходимо заняться созданием юнит-тестов? Когда проект вырос в полноценную софтину/либу, выложен в сеть и далее планируется совершенствование? Или когда API проекта перестаёт меняться по 10 раз на дню? А может быть, когда проект переваливает за 9000 строк чистого кода? Какого критерия придерживаетесь вы?

В моём сейчас 10000 строк, но он пока не завершён. Необходимость юнит-тестов ещё не чувствуется, но скорей потому, что я повсеместно повтыкал ассерты.

★★★★★

Последнее исправление: Obey-Kun (всего исправлений: 1)

Ответ на: комментарий от baverman

Дык ведь на начальных этапах формирования проекта API меняется постоянно. А так бы пришлось ещё и тесты поддерживать.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Каким образом?

зафиксировал интерфейсы - тут же зафиксировал инварианты на них; затем можешь сколько угодно писать реализацию. при TDD-подходе порядок обратный: зафиксировал инварианты - определил интерфейсы

jtootf ★★★★★
()
Ответ на: комментарий от Obey-Kun

на начальных этапах формирования проекта API меняется постоянно

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

jtootf ★★★★★
()
Ответ на: комментарий от Obey-Kun

инварианты?

то, что ты собрался проверять юнит-тестами. свойства, которые должны оставаться неизменными для данного интерфейса

jtootf ★★★★★
()

>Или когда API проекта перестаёт меняться по 10 раз на дню?

Это уже проблемы в голове либо того кто разрабатывал API, либо того, кто его реализует.

А может быть, когда проект переваливает за 9000 строк чистого кода? Какого критерия придерживаетесь вы?


В идеале весь нетривиальный код следует покрывать тестами. На практике это, конечно, сложно достижимо, но каждый метод API я проверяю и некоторые несколькими тестами.

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


Ассерты и тесты - совершенно разные вещи. Тесты как раз и нужны, чтобы быстро проверить какие-то изменения в коде, скажем перед коммитом, а не прогонять их вручную. Ассерты же - вспомогательное средство отладки обнаруженных в тестах (или ручном прогоне) проблем.

anonymous
()
Ответ на: комментарий от jtootf

Если честно, не верится, что написание тестов GUI возможно на настолько ранних этапах. Или возможна? Или речь не о GUI?

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Или речь не о GUI?

речь не о GUI. хотя тестирование GUI-кода ничем существенным от тестирования любого другого кода не отличается (разве что FSM'ами в случае асинхронных событий)

jtootf ★★★★★
()
Ответ на: комментарий от anonymous

> Какие у GUI могут быть API? GUI - это то, что ложится на API.

Ну ведь для тестирования гуя тоже ведь нужно иметь, собсно, гуй, а там есть не то чтобы API, но некоторая структура, которую с некоторой натяжкой можно так назвать. И она при разработке активно меняется. Или же тестирования гуя это вообще отдельный разговор?

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от anonymous

> Ассерты и тесты - совершенно разные вещи. Тесты как раз и нужны, чтобы быстро проверить какие-то изменения в коде, скажем перед коммитом, а не прогонять их вручную. Ассерты же - вспомогательное средство отладки обнаруженных в тестах (или ручном прогоне) проблем.

Понятно. Ну это и так ясно, что тесты комплексные, в отличие от ассертов. Просто в моём проекте (cad-подобная софтина на Qt) сложные места появились где-то после 8000 строк, спустя год от его начала (с учётом того, что из этого года я разрабатывал проект 4 месяца в некоторую часть свободного времени, а C/C++ до начала проекта не знал), вещи там были простые и ручное тестирование не отнимало много времени, так что ассертов для выявления проблем при ручных тестах хватало.

Сейчас появляется работа с полигонами, булёвые операции с ними (которые осложнены спецификой проекты) и т.п., так что только сейчас почувствовал нужность тестов.

Obey-Kun ★★★★★
() автор топика

В общем, всем спасибо за ответы.

1) В ближайшее время напишу тесты для не-гуёвых частей проекта. А их всего 2: рассчётная часть мат. модели (ядро) и булевы операции с полигонами. Там тесты должны были быть с самого начала, как я понял.

2) Когда проект приблизится к завершению, напишу тесты для GUI.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Ну ведь для тестирования гуя тоже ведь нужно иметь, собсно, гуй

Функциональные тесты тоже имеют место быть. Но если гуй у тебя жестко связан с моделью и модель нельзя отдельно протестировать, то ССЗБ.

baverman ★★★
()
Ответ на: комментарий от baverman

> Но если гуй у тебя жестко связан с моделью и модель нельзя отдельно протестировать, то ССЗБ.

Очень слабо завязан. Вообще, если честно, слабо представляю вообще, какие тесты можно писать для GUI. По крайней мере, в моём случае. Если, еснно, Undo-Redo не относить GUI (так ведь и не надо относить).

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от baverman

Ну в моём-то случае это Qt Test, выбирать больше не из чего :). Да и незачем. За полезный сайт спасибо.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

В общем, всем спасибо за ответы.

1) В ближайшее время напишу тесты для не-гуёвых частей проекта. А их всего 2: рассчётная часть мат. модели (ядро) и булевы операции с полигонами. Там тесты должны были быть с самого начала, как я понял.

2) Когда проект приблизится к завершению, напишу тесты для GUI.

увы, но Вы ничего не поняли из того что Вам сказали, тесты надо писать до написания кода, погуглите «насичот» red-green-refactor

shty ★★★★★
()
Ответ на: комментарий от shty

>писать надо с самого начала, до начала написания кода

Это лишь один из подходов к разработки ПО. Не нужно выставлять его как единственный верный.

anonymous
()
Ответ на: комментарий от Obey-Kun

Ну в моём-то случае это Qt Test, выбирать больше не из чего

опять неправда Ваша, Вам ещё понадобится QSignalSpy

и да, я бы в общем случае ещё добавил в рассмотрение какой-нибудь mocking framework, ala Google Mock - полезная штука, чтобы зависимости разруливать (главное не злоупотреблять)

shty ★★★★★
()
Ответ на: комментарий от anonymous

>писать надо с самого начала, до начала написания кода

Это лишь один из подходов к разработки ПО.

1. где я утверждал обратное?

Не нужно выставлять его как единственный верный.

2. приведите альтернативный, с учётом того что предполагается написание модульных тестов

shty ★★★★★
()

Хм, вообще я особо последнее время ловлю у себя тенденцию очень редко запускать программу. Создаю Maven проект, приложение склеиваю Spring, потом просто пишу интеграционный тест, который содержит практически код функции main, только с небольшими изменениями и другим spring контекстом. Если надо, то засуну парочку mock-классов. Придумываю use-case, дергаю API, которое заменяет пользователя, и так с самого начала. Хочу проверить другую функциональность, просто пишу другой тест, а старый не удаляю. Такой себе regression testing. Не знаю насколько подобное выполнимо не на Java, но вообще принцип очень удобный. Сейчас вот нужно соорудить такой тест для связи десятков P2P клиентов. Запросто, програмы ручками запускать не нужно, просто запущу такой контекст Spring. Главное блин один уродливый синглетон выпилить по всему коду, руки себе бы поодшибал за него. Ведь тогда в одной JVM не прокатит.

И все, практически запуск программы происходит редко в чистом виде, советую все через тесты и как можно раньше. Лучше сначала соорудить нужную инфраструктуру в проекте, пока еще строчки ни одной не написано

vertexua ★★★★★
()

Я обычно пишу тесты для каждой более-менне завершенной части проекта. Чаще всего это 3-7 классов. Сначала тестируются служебные классы, потом внешние классы. После этого, при внесении изменений - прогоняю тесты, чтоб проверится на регрессии. Также для нового функционала - необходимо добавлят тесты.
Как-то так.

trex6 ★★★★★
()

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

dizza ★★★★★
()
Ответ на: комментарий от shty

А можно я? Написание тестов «по горячим следам». Усредненная ситуация выглядит так: набросал api маленького модуля, написал реализацию, отрефакторил api до более адекватного состояния, написал на api тесты. Все в рамках одного работчего дня.

dizza ★★★★★
()
Ответ на: комментарий от dizza

Хм, что за подходы такие? Я что-то проспал? Список в студию!

модный термин, описывающий их собирательно, называется low coupling; мне больше по душе отсутствие утечки абстракций. абстракция (данных и процедур), инкапсуляция, позднее связывание, анализ общности и изменчивости - всё это так или иначе работает ради одной и той же цели

jtootf ★★★★★
()
Ответ на: комментарий от jtootf

Ну что-то похоже на правду да. Добавил бы, что еще сильно влияет баланс плановости-гибкости. Это как бы данность, определяемая обстоятельствами.

dizza ★★★★★
()
Ответ на: комментарий от dizza

Написание тестов «по горячим следам». Усредненная ситуация выглядит так: набросал api маленького модуля, написал реализацию, отрефакторил api до более адекватного состояния, написал на api тесты. Все в рамках одного работчего дня.

это называется подогнать решение под ответ - путь к появлению внезапных и неожиданных ошибок во вроде бы уже протестированном коде, проверено практиками

shty ★★★★★
()
Ответ на: комментарий от tailgunner

> Тесты определяют api.

Ахренеть. То есть API не проектируется, а определяется тестами? %)

конечно нет, просто тесты позволяют оценить создаваемое API с точки зрения user-side

//моск не заменить тестами

shty ★★★★★
()
Ответ на: комментарий от tailgunner

Ну если ты следуешь TDD, то фактически да. Ты проектируешь код тестами. Его API - как бы побочный продукт, его можно сгенерить по юнит-тестам (что я по сути и делаю). Фактически происходит написание спецификаций во время написании тестов.

dizza ★★★★★
()
Ответ на: комментарий от shty

Мозг включать нужно всегда. Нельзя спроектировать тест при использовании TDD и не спроектировать одновременно API - я это имел ввиду.

dizza ★★★★★
()
Ответ на: комментарий от dizza

Нельзя спроектировать тест при использовании TDD и не спроектировать одновременно API - я это имел ввиду.

а, ну тогда согласен :)

shty ★★★★★
()
Ответ на: комментарий от dizza

набросал api маленького модуля, написал реализацию, отрефакторил api до более адекватного состояния

Эк, какой быстрый у вас релиз-цикл! Что, неужели утром релиз, в полдень «отрефакторил», вечером новый релиз?

Рефакторинг — это изменение тела кода с целью сохранения _контроля_над_существующей_функциональностью БЕЗ изменения публичного интерфейса (API) к нему.

iZEN ★★★★★
()
Ответ на: комментарий от iZEN

Эк, какой быстрый у вас релиз-цикл! Что, неужели утром релиз, в полдень «отрефакторил», вечером новый релиз?

среднее время между рефакторингами 5-10 минут

shty ★★★★★
()
Ответ на: комментарий от shty

тесты позволяют оценить создаваемое API с точки зрения user-side

С точки зрения вариантов использования (use case).

iZEN ★★★★★
()
Ответ на: комментарий от tailgunner

То есть API не проектируется, а определяется тестами? %)

Да. Это называется когда-то модным буквосочетанием «Test-Driven Development». Ж)

iZEN ★★★★★
()
Ответ на: комментарий от iZEN

>> То есть API не проектируется, а определяется тестами? %)

Да. Это называется когда-то модным буквосочетанием «Test-Driven Development». Ж)

И похоже, люди на это ведутся.

tailgunner ★★★★★
()
Ответ на: комментарий от dizza

Тесты это инвестиции. Никто не говорит, что оно прямо сразу даст тебе результат и будут еще и за даром.

Модульные тесты защищают мозг разработчика от лишней информации: ему (и другим) не приходится хранить в голове всё то, как работает данный кусок кода, ведь его проверяет тест!

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

iZEN ★★★★★
()
Ответ на: комментарий от iZEN

Эк, какой быстрый у вас релиз-цикл! Что, неужели утром релиз, в полдень «отрефакторил», вечером новый релиз?

Смотря в каком проекте. Есть один в котором таки да, некие демки выпускаются раз в день-два.

Рефакторинг — это изменение тела кода с целью сохранения _контроля_над_существующей_функциональностью БЕЗ изменения публичного интерфейса (API) к нему.

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

Добавлю к твоему определению, что рефакторинг без юнит-тестов по суди дела тупое переписывание кода. А слово красивое, что бы начальству объяснить что делал. Не скажешь же «гавнокод переписывал», рефакторингом занимался, блин :)

dizza ★★★★★
()

>Когда в жизни проекта наступает момент, в который необходимо заняться созданием юнит-тестов?

Когда ты вносишь изменение в ядре системы и понимаешь, что уже не в состоянии вручную протестировать поведение даже базового набора приложений :)

Когда проект вырос в полноценную софтину/либу, выложен в сеть и далее планируется совершенствование?


Тут ещё не обязательно.

Или когда API проекта перестаёт меняться по 10 раз на дню?


Пока API меняется 10 раз на дню, то даже о проекте говорить ещё рано, не то что о его тестировании :D А то ещё и юниттесты придётся переписывать по 20 раз на дню :)

но скорей потому, что я повсеместно повтыкал ассерты.


Одно другому не замена.

KRoN73 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.