Comments 17
Я когда-то тоже думал на эту тему. Если кратко, то чем больше в коде решений, чем больше в команде разработчиков, чем более стабильна предметная область - тем осмысленнее применение юнит-тестов. Нет смысла писать юнит-тесты, если проект ведётся в "одну голову" или пишется "одноразовый" код. Но смысл появляется, если предполагается, что проект будет эволюционировать или количество разрабов станет больше одного. Хотите набраться реального опыта в юнит-тестировании - возьмите "силиконового" напарника ;)
Ну собственно эта мысль и прослеживается в топике :) В условиях изначально продуманной структуры они действительно полезны.
Но дело в том, что я практически не работаю в таких условиях, а вот на собеседованиях периодически об этом спрашивают. И вопрос в том, нужно ли стремиться ли в компании с культурой тестирования, или можно просто забить?
Вчера я бы ответил, что можно забить. Сегодня - что в парном кодировании с ИИ-агентом без юнит-тестов не обойтись.
Завтра вы не сможете себя продать, если не будете способны генерировать код в паре с ИИ. "Силиконовые" производят стандартный код с очень впечатляющей скоростью. Это как копать ямы лопатой и экскаватором. А раз уж "экскаватором", то какая разница, что "копать" - код или тесты для него?
Тесты помогают:
Исключить ошибки невнимательности
Понимать, что при изменении кодовой базы функционал работает корректно
Планировать и структурировать код
Убедиться в работоспособности перед выпуском на стенд
Если у вас появляются новые кейсы (все предусмотреть действительно невозможно) - просто добавляйте еще один тест и все)
А необходимость всего этого каждый решает для себя сам. Ну, либо это регламентируется правилами на проекте
Статью не читал, но с посылом согласен. Пирамида тестирования известна давно: юнит тесты в основании пирамиды тестирования, их много, но вклад в покрытие функционала мизерный. Их девы пишут для себя, чтобы просто прошёл мёрж реквест. Никакой дополнительной пользы они не несут.
А то что юнит-тесты позволяют очень точно протестировать бизнес-логику и покрыть граничные случаи, которые или очень тяжело или вообще невозможно покрыть огромными интеграционными тестами - это конечно же БЕСПОЛЕЗНО :)
Бизнес логику покрывают фукнциональные и приёмочные тесты. Граничные условия покрывают тоже функциональные тесты. Итеграционные тесты проверяют протокол взаимодействия компонент по API. И да, юнит тестам тут места нет.
Приёмочные и функциональные тесты проверяют сквозные пользовательские сценарии (happy path + несколько граничных) и требуют обычно полного запуска системы с базой, брокером и т.п.
Если вместо использования юнит-тестов, вы будете пытаться тестировать все инварианты через перебор комбинаций входов в функциональных тестах, вам нужен будет по меньшей мере квантовый CI-сервер, потому что это будет очень-очень долго и тяжеловесно.
В нормальной разработке вместо этого юнит-тесты обычно используются чтобы быстро прогнать много граничных комбинаций за секунды и показать точный метод, где упал инвариант. Поэтому, говорить что юнит-тесты не нужны значит недооценивать само их предназначение.
Перебор вариантов будет в любов случае. И это корневая задача тестирования объять необъятное: ограниченным числом тестов покрыть огромный функционал. И отчасти эту проблему решает white box когда сокращается количество изначально неработающих вариантов путём изучения кода и бизнес кейсов заказчика. Именно эти тесты будут гонятся постоянно в регрессии и будет гарантом функционала, который ещё не сломали. Большая часть юнит тестов вообще не попадёт в CI в виду flakebility (ломкости).
Юнит-тесты это чаще всего и есть самый точный и дешевый способ сделать то, что делается при white-box тестировании.
Если юнит-тест то проходит, то нет, это вопрос к тем кто его писал, а не к самой концепции. Даже более того, за счет того что в юнит-тестах нет сети, БД и тому подобного, шанс flakebility при правильном написании даже ниже, чем у функциональных/приемочных тестов.
Ну, и гораздо полезнее, когда CI загорается красным сразу после некорректного коммита, а не спустя полдня, когда упал регресс-ран из e2e-сценариев.
Если вы отключаете хрупкие юнит-тесты в CI, а не чините их, то это опять вопрос к тем, кто работает над проектом, а не к самой концепции.
Красные тесты на каждый коммит это не есть хорошо и не лучшая практика отладки кода. Отлаживаться на юнит тестах надо не в CI, а где то там локально, на кошках. В CI должен попадать хоть как то отлаженный код (а не как это принято сейчас пушить что попало без тестирования) для чего и служат юнит тесты. При этом самим юнит тестам быть в CI вовсе не обязательно.
Речь не про отладку, а про единую точку правды и скорость обнаружения ошибок. Ведь человеческий фактор никто не отменял. Но да ладно.
Что могу сказать, могу пожелать только удачи с подходами "отключать тесты в CI" и надеяться, что разработчики будут все тесты запускать локально.
Как пошутили где-то в комментариях, с такими подходами можно просто в прод всё катить, и пусть пользователи тестируют :)
А что вы считаете очевидным? Да, в
assert 0.1 + 0.2 == 0.3
смысла нет, но вassert some_your_sum(0.1, 0.2) == 0,3
он уже появляется. Тестируются не встроенные операторы, а то, что мы сами пишем, ну или то внешнее, чему доверяем, но всё-таки проверяем.
Кажется дзен TDD так и не понят, что тесты пишутся до кода и как это будет проверяться проектируется одновременно с системой.
Вот честно, проще тесту скормить кусок непонятных данных отброшенных в лог, чем страдать ловя их в потоке.
И это хорошо когда данные просто поменялись, а когда начинается подмес чего-то нового? А потом ещё и ещё? Вам же нужно стабильно обрабатывать и первое и второе и третье. Без тестов тут такой замес можно устроить...
И ещё раз - пишите тесты до кода и на все уровни сразу. Хотя-бы их канву...
Уже как-то формулировал свой взгляд...
Совет из TDD: Начинайте писать тест ДО того как создали метод, убеждаемся что тест не проходит и только потом создаём метод который проходит тест, рефакторим, убеждаемся что проходит, думаем а какой функционал ещё нужен? добавляем новый тест, убеждаемся что он не проходит, меняем или добавляем новый метод, чтобы он его проходил, рефакторим и смотрим чтобы уже два теста проходили, и так накручиваем
Такой способ даёт 100% покрытие и 100% предсказуемость, а так же крепкий сон, исключает драмы в стиле почему когда я парсил json у меня дропнулась таблица в бд
если ты не знаешь чего тестировать - скорее всего либо тебе не ясна задача, либо тебе дали задание в стиле "сделай как нибудь" , значит и делай как нибудь, но я так не делаю, потому что потом всё будешь переписывать, руководствуюсь другим принципом - стараюсь делать хорошо, хренова всегда получится, когда ты пишешь тест ты четко понимаешь что ты хочешь на выходе при таком входе, а значит и проще объяснить железяке, поэтому относиться ко времени на тесты нужно как на проектирование, а не само программирование
Но упарываться в юнит-тесты тоже не нужно, если как минимум три исключения:
1) не нужно тестировать приватные методы, не нужно ничего открывать во вне, только интерфейс, который задуман, покрытие обеспечивается косвенными методами
2) не нужно пихать в тесты бизнес логику, её нужно тестировать, а не сувать в тест, иначе тест станет хрупким и бесполезным
3) не нужно загрязнять тестами release код, продукт ничего не должен знать о тестах, иметь какие-то скрытые параметры и методы только для прохождения теста
Простые вещи, которых я не знаю: юнит-тесты