Как стать автором
Обновить

Комментарии 45

Польза тестов понятна, но кто даст на это время/деньги?

в смысле? а кто дает время на хороших код? написание юнит тестов для кода это огромный фильтр для качества кода. Гавнокод нельзя покрыть юнит тестами только интеграциоными или вообще эндтуэнд. От сюда на выходе имеем код который будет читаемым чистым поддерживаемый . Мы в своей массе новый код пишем очень мало даже в бурно развивающемся проекте. В основном юзаем и преюзываем код который уже написан. А если он будет по феншую то это же хорошо и ускорит в разы разработку даже нового функционала

Есть множество компаний, где нет ни хорошего кода, ни юнит-тестов. И они как-то живут.

ты хочешь в таком коде ковырятся ? или все же Предпочитаешь работать в хороших условиях?

Я люблю в таком коде ковыряться. После 30 с небольшим лет в отрасли я уже уверен что "работать в хороших условиях" не более чем миф. Розовый единорог - в природе не встречается.

Отвечено "зачем" но этот вопрос не задавали.

Вопрос звучал "кто выделить время/деньги на написание тестов?"

Если сами себе пишите программу и никто не подгоняет - есть возможность.

Если "начальник" прибегает и говорит сто надо сделать проект за такой-то срок, чтобы получить деньги, чтобы вам заплатить зп... Ну как бы другие условия.

Нико не спорит, что тесты всякие хороши.

Что переходить на красный плохо - все знают. Всегда ли соблюдается это правило?

Зы: на вентилятор накину. Как internal методы тестировать? Ну к высказыванию "говнокод покрыть нельзя".... Приватные/внутренние методы - говнокод?

Только не надо "они должны тестироваться путём тестов публичных, которые их используют".. Нет публичных )) Есть большой черный ящик с двумя методами публичными, а под капотом магия.. ))

Зависит от горизонта планирования

Почти всегда это только год (

Для такого юнит тесты не нужны, конечно

Вы по сдельной схеме работаете? Вам отдельно платят за строчки кода, за багфиксы, за тесты, за сообщения в коммитах, за документацию в базе знаний, за консультации QAшникам и саппорту?

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

Я к тому, что писать/не писать тесты это часто не решение самого разработчика.

Утверждения годные, но без конкретных примеров спорить почти не о чем

  • Что происходит с юнит-тестами при рефакторинге?

  • Зачем нужен тест, которому я заранее говорю, что будет на выходе, а потом проверяю, что на выходе именно это?

  • Большая часть юнит-тестов проверяет только количество вызовов при разных вызовов, а не данные.

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

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

Что происходит с юнит-тестами при рефакторинге?

Они также меняются, как того требует структура проекта.
Если у вас только что созданный проект, то да, написание юнит-тестов нужно отложить до момента, когда проект более менее устаканится. В ином случае вы будете тратить тонну времени на изменение тестов не по причине добавления/изменения функциональности, а из-за рефакторинга.
А в устоявшемся проекте изменение тестов происходит в рамках выполнения задачи за вменяемое время.

Зачем нужен тест, которому я заранее говорю, что будет на выходе, а потом проверяю, что на выходе именно это?

Вы не говорите в тестах проверяемому методу, что надо вернуть.
Вы говорите классам/объектам, которые вызываются в тестах, что надо вернуть. Тем самым вы проверяете только работу проверяемого метода.
А результат работы метода, если он есть, сравнивается с ожидаемым значением.

Большая часть юнит-тестов проверяет только количество вызовов при разных вызовов, а не данные.

Это возможно, если у вас большая часть void методов. На практике это не частое явление.
А так для проверки, на вскидку, есть:

  1. Возвращаемое значение

  2. Выбрасываемые ошибки

  3. Кол-во вызовов методов

  4. Проверка того, что какой-то метод не вызывался

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

Зависит от того, кто и для каких целей пишет.
Основной инструмент тестирования разработчика ⟶ юнит-тесты. Мы проверяем только свой код, мокая всё остальное. Запускаются и проходят эти тесты также сильнее быстрее (не забываем, что для интеграционных нужно поднимать всю инфру)
А вот тестировщика основным инструментом являются интеграционные тесты, так как задача у тестировщика другая.

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

Если юнит-тесты проходят дольше интеграционных (это надо сильно сильно постараться), то такие тесты написаны неправильно.
С другой стороны, куда-то торопитесь? 5 минут времени критично?

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

Пожалейте сову и глобус. Импакт от юнитов заметен, если у вас хост для CI крутится на Pentium 3. Или если у вас этих тестов под миллион штук. Любой sleep(100) в интеграционных тестах, завязанных на эвенты, или подготовка данных для БД имеют на пару порядков больше импакт.

Хорошо лить эту воду, когда ты сам тесты писать не будешь. Сам по себе юнит-тест тестирует один метод вне какого-либо контекста. Проверяет, что метод getArray(...) отдает массив. Но какая разница, что отдает этот метод, если он давно в проекте не используется? Согласен, что e2e и интеграционные тесты гораздо более полезны, чем юнит. Юнит - это скорее для дебага при разработке.

проверяет что getArray отдает массив, кхм, компилятор. Юнит-тест проверяет что если мы создали объект, добавили туда "А" и "В", то getArray вернет ["A", "B"].

Ну а если язык интерпретируемый...

Вы меньше боитесь рефакторинга. Тесты сразу покажут, если что-то пошло не так — не нужно бояться “сломать прод”.

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

Поэтому зачастую приходится ограничиваться интеграционными.

Да нет, все правильно там написано. Я вообще не понимаю, как заниматься какими-либо изменениями в коде, если нет unit-тестов, это ж чистые слабоумие и отвага. Ну, если только звонки в 5 утра с криками, что прод упал, доставляют удовольствие и добавляют радости в жизни...

Привет, HabrGPT, перепиши статью, учтя следующие замечания:

Вы мгновенно видите ошибки. Никаких “а вдруг я забыл какой-то кейс” — всё проверяется автоматически.

Проверяются только те кейсы, на которые вы не забыли написать тест.

Вы ловите баги ДО того, как они попадут на прод или, хуже, к клиенту.

Именно юнит-тесты в этом слабо помогают. Поэтому им и нужны подпорки в виде других типов тестов.

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

Написание моков на каждый тест всё же гораздо сложнее накликивания в браузере. А когда эти моки нужно ещё и без конца переписывать - это совсем утомительно.

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

Я практически не пишу типы руками, но при этом мой код строго типизирован. Наверно я что-то делаю не так.

С юнит-тестами та же история. Это не затраты, а инвестиция.

Аналогия не является аргументом. Один инструмент даёт больше, чем берёт, другой - наоборот.

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

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

Кроме того, тест, который «сломался» — это не проблема. Это сигнал: "что-то поменялось, проверь, не сломал ли ты логику." Это как лампочка на приборной панели — предупреждение, а не баг.

Чем чаще эта лампочка кричит "волки", тем реже на неё вообще обращают внимание.

Интеграционные и e2e тесты важны, но: Они медленные.

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

Они сложнее в поддержке.

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

Они не всегда точно указывают, где ошибка.

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

Юнит-тест — это быстрый, детальный и локализованный способ убедиться, что маленький кусочек логики работает как надо. Они не заменяют интеграционные тесты, но великолепно дополняют их.

Никакой дополнительной пользы к компонентным тестам модульные не приносят.

юнит-тесты ускоряют разработку даже простого кода, потому что

Тут стоит перечислить отличительные свойства именно юни-тестов, а не любых тестов.

Рефакторинг без страха. Не нужно вручную кликать по UI, чтобы проверить всё.

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

Экономия времени. Проверить 10 сценариев тестами — дело секунд, а не получаса ручного «протыкивания» в браузере.

Это дело миллисекунд.

Живая документация. Тесты часто лучше объясняют поведение функций, чем комментарии.

Код модульного теста изобилует моками, которые не используются в реальном коде. По этому коду не очень понятно, как канонично пользоваться модулем.

Командная работа. Вы доверяете чужому коду, потому что знаете — если тесты зелёные, значит всё ок.

Либо на чужой код написаны далеко не все тесты.

Если вы верите в пользу статической типизации, поверьте и в пользу автоматической проверки логики. Юнит-тесты дают тот же контроль — только над логикой.

Это называется "формальная верификация". Тесты тут вообще ни при чём.

PS. Cтарался писать поменьше букв, но просто накипело.

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

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

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

Скорее не ломание под тесты, а осознание, что где-то переусложнил класс. Просто иногда это ко мне приходило именно на этапе написания юнит тестов. Но, конечно, каждый случай индивидуален.

Если любое изменение приводит к падению тестов, то это плохие тесты. Не концепт плохой, а конкретная реализация. На хороший код тесты пишутся легко и приятно

Так покажите нам свой хороший код с юнит-тестами, не стесняйтесь

Так а что мне показать? Как паттерном "стратегия" пользоваться вместо кучи приватных методов? Как избегать классов с 20ю внутренними филдами? Что методы с 10 возможными результатами - это плохо? Это всё идеи, которые лежат на поверхности, но на которые очень легко забить в процессе работы. Написание теста же сразу подсвечивает такие места. Да фиг с ним с тестом, его можно и не писать по итогу, но если ты в процессе работы думаешь над тем, что код должен быть тестируемым, то ты сразу думаешь над тем, как сделать нормально, а не тяп-ляп и в прод

Я вот абсолютно искренне не понимаю людей, которые не пишут тестов. Есть возможность делать хорошо, но они осознанно выбирают делать плохо. Зачем? Нафига? Очень много вопросов и так мало ответов

Вы действттельно не видите разницы между тестами и юнит-тестами или просто публично демагогизируете?

ты действительно решил не ответить по существу, а докопаться до отсутствия слова "unit"?

Ответ на ваши глупости, молодой человек, есть по ссылке выше.

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

Проверяются только те кейсы, на которые вы не забыли написать тест.

Чтобы что-то делалось, нужно это сначала сделать, это довольно очевидно. А минусы где?

Именно юнит-тесты в этом слабо помогают. Поэтому им и нужны подпорки в виде других типов тестов.

unit-тесты - не панацея, и автор ни разу не сказал, что надо писать только их

Написание моков на каждый тест всё же гораздо сложнее накликивания в браузере.

Один раз накликать в браузере, может быть, и проще. Кликать весь функционал со всеми его инвариантами каждый раз после добавления/изменения куска кода - и близко не проще и не быстрее

А когда эти моки нужно ещё и без конца переписывать - это совсем утомительно.

Если код нормальный, и тест нормальный, то не придется ничего переписывать. Если на каждый чих надо переписывать, то это сигнал, то код - говно

Хороший рефакторинг меняет в том числе и контракты

Голословно

Чем чаще эта лампочка кричит "волки", тем реже на неё вообще обращают внимание.

Рекомендую почитать, что такое "хрупкие тесты", и почему это плохо, и почему надо писать нормальные тесты

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

Повторюсь, если тесты ломаются от каждого чиха, то это плохие тесты

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

Зависеть от порядка выполнения тестов - это, я даже не знаю, довольно занятное извращение, но так себе практика для проекта

Никакой дополнительной пользы к компонентным тестам модульные не приносят.

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

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

То, запускается ли программа, проверяется ее запуском. Не стоит ставить инструменту в вину попытки неправильного его использования

Код модульного теста изобилует моками, которые не используются в реальном коде. По этому коду не очень понятно, как канонично пользоваться модулем.

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

Вы тоже не стесняйтесь показать свои "хорошие юнит тесты для хорошего кода". Языком болтать-то все горазды.

Ну так ты тоже не стесняйся показать пример твоим аргументам, иначе это тоже просто "болтание языком"

Так я и не стесняюсь - по ссылке выше всё есть. Или не царское это дело по ссылкам ходить?

"Юнит-тесты" никакая конечно же не суперсила. Просто один из инструментов разработчика.

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

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

вот да. Юнит тесты не спасут от всего. Даже может и наоборот. Юнит тесты надо уметь писать, и надо уметь писать код хороший. который как раз и хорошо покрывается хорошими юнит тестами.

А вот ФСТЭК уже требует покрытие юнит-тестами и отчёты по тестированию при сертификации ПО, правда пока это не проверяет

Именно юнит-тестами, а не тестами вообще? Можно ссылку, где он это требует?

Не только юнит-тестами: SAST, DAST, SCA, Fuzzing, Unit.

Ссылку на документ дать не могу, т.к. он ДСП и в открытом доступе я его в Интеренет не нашел: "“Методический документ. Методика выявления уязвимостей и недекларированных возможностей в программном обеспечении (издание второе, доработанное)”

Документ продает ГНИИИ ПТЗИ ФСТЭК России, но только лицензированным ФСТЭК испытательным лабораториям (поэтому испытательные лаборатории и интеграторы по ИБ берут дорого за оформление бумажек на сертификацию). Как вариант, если интересует сертификация во ФСТЭК, взять в штат специалиста, который уже это делал.

Выдержку из этой тайной книги вы, конечно же, не приведёте?

Должно быть обеспечено покрытие SAST, DAST, SCA, Fuzzing, Unit тестами: статический анализ (исходный код размечен), динамический анализ, отсутствие криптических и высоких общеизвестных уязвимостей в транзитивных зависимостях, фаззинг-тестирование, покрытие unit-тестами. Далее подробности на >100 страниц по офррмлению результатов и т.д.

Если используются opensource зависимости в продукте, то нужно также предоставить информацию по их тестированию.

То есть интеграционные тесты не нужны? Очень интересно.

Если верхне-уровнево, то ФСТЭК интересует только безопасность кода, сторонних зависимостей, а также работоспособность заявленных функций безопасности.

Пришел к такому выводу относительно написания юнит тестов - CPU-bound методы обычно идеально подходят под юнит тесты. Пример: хмл парсер с кучей corner-cases внутри. Генерим разные xml на входе, проверяем правильность объектов на выходе. Любые функции, которые хитро что-то высчитывают, регулярки там всякие. Такого кода обычно очень мало в большом проекте. Писать такие тесты даже где-то приятно.
IO-bound ETL функции - аля "прочитай из базы - передай дальше в другой микросервис" (99% функционала в больших e-com компаниях) превращаются в бесполезные "the code I wrote is the code I wrote" проверки, которые просто дублируют всю логику. Такие тесты изматывают и угнетают, я их пишу исключительно для прохождения барьера по покрытию (в больших компаниях иначе не задеплоить свой код).
Кстати, с появлением AI помощников появилась надежда, что наконец-то написание этих ваших тестов для IO ETL методов можно спихнуть на AI бота. Но пока чето не очень, именно такие тривиальные, казалось бы, методы chatgpt почему-то очень плохо пока умеет и получается корявенько.

Юнит тесты это хорошо, но не надо забывать, что они находятся в самом основании пирамиды тестирования. Их много, но их вклад в тестовое покрытие минимален. Соответственно, нужны они исключительно как поддержка в разработке самому разработчику. На поздних этапах разработки они будут заменены следующим слоем тестов в пирамиде, функциональными тестами. О юнит никто уже не вспомнит. Даже сами разработчики. Ибо будут заняты починкой багов, которые уже нашли QA своими тестами, проверяющими не какие то модульные никому не видные вещи, а сценарии используемые заказчиком в коммерческом продукте. С другой стороны, разраб , который не пишет юнит и интеграционные тесты стреляет себе в ногу на поздних этапах, когда исправление ошибки может вылиться в не подъемный рефакторинг или пересмотр архитектуры. Либо постоянное, но бессмысленное латание дыр валящихся из пайплайнов каждый день.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации