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

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

Хоть кто-то на Хабре пишет разумные статьи! Всё борюсь с коллегами, ежедневно доказывая, что "х-к, х-к и в продакшн" — самая продвинутая и современная методология разработки! Побольше бы таких единомышленников, как автор!

Настоящие программисты правят код прямо на проде!

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

ага, было такое дело в моей практике.

делали устройство, загрузчик самописный был с обновлением через WIFI. Заложился на фиксированный размер образа, 90кБ. Как раз оставшееся свободное место в ОЗУ stm32 ушло на этот демпфер. Рабочая микропрограмма получалась порядка 70 кБ, так что выделил как казалось с запасом…
а потом, добавить ещё пару плюшек и… образ внезапно получился 92 кБ с учетом оптимизации. Как итог, писался апгрейд загрузчика, который грузился вместо основной прошивки и переписывал бут. Далее уже новый бут принимал новую прошивку.

«Если вы никогда не ALTER'или на продакшне по неопытности таблицу БД размером 10GB, локнув ее на полдня — вы вообще разработчик?»

Никто не сравнится с программистом, угрожающим проверять свои коммиты, перед тем как делать PR!

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

Спорно это всё. Я у себя в проектах практикую написание тестов разработчиками.
При этом слежу чтобы разработчик не писал тестов на свой код, а обязательно на соседний.
Часто тесты пишутся до самого функционала.
И всё хорошо. И все счастливы.
Разработчики лучше понимают общий код разрабатываемой системы. Всегда могут подменить неожиданно выпавшего из процесса бойца. Качество релизов стабильно высокое. Скорость разработки высока.
Другие департаменты приходят чтобы перенять опыт.


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

Вы слишком толерантны. Подход, описанный в статье, не подойдет никому. Разумеется, если целью стоит грамотное развитие проекта.
Думаю, после прочтения заключения (под спойлером) вы лучше поймете цель этого поста, и все сразу встанет на свои места :)
Сори))) Спойлер не заметил :facepalm: от отсутствия тестов у меня подгорело)))

Часто целью стоит успешное развитие проекта…

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

Get Shit Done — вот правильная методология. Нахрен все эти property-testы и given-when-then-ыс их cucumber-ами и jbehav-ами! И Intellij-и с их долбаными статическими анализаторами, у пацанов код как новогодняя елка выглядит из-за них.

tmn4jq респект, за скрытие рекламы под спойлер. Все б так делали.

Тесты придумали трусливые разработчики, которые боятся х-ть в прод почаще, побольше и побыстрее. Им никогда не достигнуть высот в программировании, и "Citius, Altius, Fortius!" — для них просто пустой звук. В них пропал дух авантюризиа. Они перестали не только лазить в окна к любимым женщинам, но и дропать таблицы в боевых БД...

Тесты придумали ленивые разработчики, которые не хотят потратить несколько лет на изучение техник верифицированного программирования. Им никогда не достигнуть высот в теории типов, и «W-types» — для них просто пустой звук. В них пропал дух исследований. Они перестали не только лазить в окна к любимым женщинам, но и доказывать, что n + 0 = n…

Херак, Херак и в продакшен!

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

Минимальные тесты которые проверяют happy path обязательно должны быть написаны разработчиками до передачи в тестирования, иначе это сводится к тому, что чукча писатель, а не читатель. В результате повторые итерации начинают зашкаливать.
Чукча не читатель – это точно, потому что кто-то не дочитал до заключения.
Но я вам больше скажу – happy path это чушь, вы должны ломать свой код в тестах. Меньше happy, больше хардкора.
заключения не заметил ((( подгорело однако. у меня бывало что хэппи пас на интеграции не проверили, а юнит тесты были норм, а до релиза 1 день, я негодовал…
Эдакая проверка на читаемость.)
Ви таки будете смеяться но есть вполне себе серьёзные и коммерчески успешные компании в которых код дикое спагетти, а баги именно что фиксят только после тикета в саппорт. Даже при наличии тестов.

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

Совет: Чтобы не срывать сроки и доставлять вовремя – лучше нанять разработчиков, а тестированием заниматься на продакшене. Даже если что-то пойдет не так, вы всегда можете возразить, что соблюли сроки, как и было обговорено. А о большем и не договаривались.


Вы серьезно? Да Вам в Microsoft надо идти работать — там именно так и делают. Или в Boeing — 737MAX примерно так и разрабатывался.

А теперь представьте, что Вы разрабатываете систему управления, скажем, энергоблоком АЭС. долго Вы проживете (в буквальном смысле слова) с таким подходом?

Не, я понимаю, что если клепать сайты для всяких там ООО «Сукин и Сын», то «и так сойдет» (с). Но очень много областей, где ошибка на проде стоит непомерно дорого.

В общем, бред какой-то…
Не, я понимаю, что если клепать сайты для всяких там ООО «Сукин и Сын», то «и так сойдет» (с)

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

а еще 2 предыдущие статьи автора из серии «вредные советы», думаю эта статья так же в этой тематике на самом деле
Я никогда не обманываю и сразу честно указываю теги!
извините, другие статьи то глянул, а заключение с тегами проигнорировал, в обмане я вас и не обвинял
Тэги не для всех работают. В десктопной версии они расположенны сразу после заключения.
Уважаемый, дочитайте до заключения (оно под спойлером в конце поста)
К сожалению не очевидно, что статья в стиле «вредные советы» (на теги под статьей вообще редко смотрю).
Я многократно слышал мнение, подобное изложенному, но высказанное вполне серьезно, в том числе от хороших разработчиков с 10-15 лет стажа — они просто не умели использовать тесты, и не хотели этому учиться.
А почему это должно быть очевидно? Если в заголовке будет стоять «эта статья — ирония/сарказм» ее будет банально неинтересно читать. Я вот тоже только на третьем абзаце допетрил что это все не всерьез. Нужно просто читать до конца (или хотя бы тэги), а не бежать сломя голову писать гневные комментарии, потому что в интернете опять кто-то неправ
Я прочитал первые абзацы, пробежал по остальным, внимательно начал читать комментарии, откуда и понял, что это «вредные советы». Я сделал это так, поскольку
Я многократно слышал мнение, подобное изложенному, но высказанное вполне серьезно

Не думаю, что мой комментарий можно расценивать как «гневный», и я не считаю, что автор не прав — я читаю, что возможны вариации в понимании идеи статьи.
На самом деле, я приветствую гневные комментарии к этому посту. При условии, что вы разобрались в вопросе и обоснованно доказываете мне обратное. Это значит, что вы понимаете важность тестирования, а пост, на самом деле, именно об этом. Да, это не хабр-формат, может, кто-то неправильно поймет. Однако, я нарочно сильно утрировал местами, чтобы лучше намекнуть на цель поста.
Согласен, это нечно необычное для хабра, и пишу я сюда редко. Я пишу такое у себя в блоге, и там я всегда делаю посты-разоблачения на свои вредные советы :)
Кто-то с первого же абзаца понял, что это это ирония. Другие даже к концу поста не понимают, и это нормально. Но все же, если вы ко всему этому относитесь так серьезно, то вам определенно стоит проще смотреть на мир.
Да вся статья это Юнит-Тест для проверки не сломался ли у человека блок юмора и не потерял ли он связь с реальностью. Если вы всерьез относитесь к тому что в ней написано, то либо вы переработали и вам пора отдыхать на «Новый Год», либо вы просто поверхностно, без критичного подхода, читаете то что пишут в интернете.

Интеграционный же! Юнит-тесты гораздо проще.

Забыли ещё пару пунктов:


У вас слишком специфический проект, чтобы писать в нем тесты.
Тесты пусть пишут веб-макаки и формошлепы-кодеры в своем кровавом энтерпрайзе, а вы же занимаетесь действительно серьезными вещами. Проект у вас по-настоящему сложный, в нем много завязанных друг на друга частей, тестировать такое можно только скопом, а число возможных комбинаций и сценариев такое, что жизни не хватит их все описать. "Чистая архитектура" и паттерны проектирования — тоже хипстерская хрень, да и на рефакторинг времени нет, вы же тут делом занимаетесь, а не фигнёй страдаете.


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

Спасибо за дополнение!
> «Чистая архитектура» и паттерны проектирования — тоже хипстерская хрень

Это придумали консультанты чтобы свои услуги продавать!
Жаль, что это вредные советы. Я уж было подумал что кто-то действительно понял, что тесты (в том виде, в каком они сейчас восхваляются сообществом) — зло. Ладно, подождем еще пяток лет.

Вы знаете меньшее зло по сравнению с тестами?

Почему зло? Есть другие способы повышения качества. В некотором смысле какие-то из них — лучше тестов.

Я могу поверить что часть юнит-тестов можно заменить хорошим языком программирования. Но я не понимаю чем можно заменить интеграционные тесты.


Вот у нас есть на coq доказанная программа, которая сохраняет инвариант и всегда правильно вычисляет команду назначения ip-адреса. Она учитывает всё, что может быть в ip (мультикасты и т.д.), но… Она вызывает /usr/bin/ip, а в системе это /bin/ip. И всё рушится. Ещё лучше, если даже /bin/ip нет, потому что кто-то его должен ставить.


Как это проверять?

> Я могу поверить что часть юнит-тестов можно заменить хорошим языком программирования. Но я не понимаю чем можно заменить интеграционные тесты.

А я не могу. Языкам программирования нет дела до бизнес-логики приложения, а тестируют именно ее, а не базовые конструкции языка.
Языкам программирования нет дела до бизнес-логики приложения, а тестируют именно ее, а не базовые конструкции языка.

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

Проверять инварианты — дело неплохое, но что делать если инвариантов-то и нет, а есть только алгоритм, который надо написать?

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

Как что? То, что на контрольных примерах этот алгоритм работает ожидаемым образом.


А вот что вы будете делать с типами?

А кроме контрольных примеров у этого алгоритма нет ничего-ничего? Ну, в этом случае типы сведутся к тестам, которые прогоняются тайпчекером. Какое-нибудь там


or : Bool -> Bool -> Bool
or = ...

orIsCorrect : (or True False = True,
               or True True = True,
               or False False = False,
               or False True = True)
boolOrIsCorrect = (refl, refl, refl, refl)

В этом случае всё скучно, да.

У меня на работе питон, а как хобби — Rust. Поверьте мне, это очень большая разница.


В питоне нужны тесты для проверки инвариантов (что все if/else сохраняют возвращаемый тип) — в Rust это автоматом. В питоне нужно проверять интеграцию функций друг с другом (что передают правильный тип), в Rust — нет, потому что сигнатуры уже всё решили.


В Питоне постоянно висит опасность TypeError: unsupported operand type(s) for +: 'NoneType' and 'str', в Rust такой нет.


Логику всё равно надо проверять (и Rust падает с куда большим усердием, чем питон, если что-то не так), но вот гоняться за нелепыми опечатками в exception'ах — уже не нужно.


Например, вот такой код:


try:
   foo=bar(baz["data"])
except ExceptionFoo as e:
   module.json_fail(f"Error processing baz data: {e}, data: {baz.data}")

Мало того, что обработка ошибок (которую трудно проверить), так оно ещё и сломает отладочный вывод, потому что надо было json_fail, а оно сделает грёбанный trace, который не прочитать потом. Да ещё и содержимое baz["data"] так и не увидишь.

Насчет «В Питоне постоянно висит опасность TypeError»:
Можно писать аккуратный код и использовать статическую типизацию.
Возможность динамической типизации не обязывает и не означает отсутствие статической.
Сам использую статическую, привычка с С/С#.

Для этого нужно, чтобы все используемые библиотеки имели аннотации типов.


Более того, статическая типизация в стиле mypy на самом деле очень слабовыразительная.

В питоне нет статической типизации. Есть type hinting, который помогает чуть более чем ничем. Его основная польза — документация к функциям.


А "писать аккуратный код" очень просто. Берёте и пишите код без багов. Получается очень аккуратно и типизация не нужна. Вообще никакая.

У меня на работе Питон и Джава.

> В питоне нужны тесты для проверки инвариантов (что все if/else сохраняют возвращаемый тип)

И в логике нужны тесты на проверку инвариантов. Если в типах проблемы, то тесты это тоже поймают.

> но вот гоняться за нелепыми опечатками в exception'ах — уже не нужно

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

> Мало того, что обработка ошибок (которую трудно проверить),

Связка pytest + monkeypatch + Mock + side_effect хорошо справляется. Код который кидает исключение нужно вынести в отдельную функцию и её замокать.

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


А вот избыток mock'ов в районе exception'ов чреват code liability. У вас была программа на 1000 строк. Вы к ней написали 20 тестов на 2000 строк (с кучей моков, так что "ехал мока через моку видит мока мок, сунул мока моку в моку, мока мока not equal mock"), и у вас теперь ещё 2000 строк трудного кода, с ядрёной инстроспекцией.


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

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


Как это проверять?

Можно проверять, что программа корректно обрабатывает отсутствие /usr/bin/ip.

Ну вот в коде написано: if !exists!('/usr/bin/ip'){panic!("Unable to find ip")}. Проверили? Проверили. Обработали? Обработали.


Но почему оно уехало в продакшен с миллионом копий в epprom без интеграционного теста на то, что оно таки эти роуты поднимает?

Ну тут два аспекта.


  1. Тесты тоже тут ничего не гарантируют — вы ж сами приводите рядом пример, когда код в проде отличался от кода в гите (и, подозреваю, от кода на тестовом сервере). Как ваши тесты гарантируют отсутствие аналогичных проблем в проде?


  2. Даже с такими проверками вы потом можете прогрепать ваш код на предмет таких обработок (или, более общо, найти все термы с типом, подразумевающим критическую ошибку отсутствия того или иного файла на диске), собрать их список и в автоматическом режиме проверить, что в образе они содержатся. И узнать, что у вас не только ip не хватает, но и других бинарей, которые используются, например, только при обработке ошибок (и отсутствие которых даёт дыру в безопасности, например).


Интеграционные тесты обычно очень много чего гарантируют, но что именно — это такая рандомная выборка. Задача интеграционных тестов — это проверка ожиданий двух систем друг от друга. В отрыве от друг от друга их проверить (на практике) нельзя.


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


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


… хорошая мысль.


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

Я с этим не спорю, но я говорю немного о другом. Точно так же, как формальные доказательства не дают гарантий, что в еепром в железке в проде запишется ip по нужному пути, интеграционные тесты тоже не дают таких гарантий. Вот и всё.

Интеграционные дают. К сожалению, список гарантий там очень узкий (только то, что проверили), но дают.

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

Я вообще не про интеграционные говорил, сорри если так выглядело. Это две разные вещи, на мой взгляд.

Да. А мы с вами достаточно часто общаемся, чтобы вы знали мой ответ.

Вводная про хипстеров, придумавших TDD, сразу спойлерит. Даже до тегов.
Но ответственность за эти ошибки плавно перекочевала с плеч разработчиков на плечи тестировщиков. Как-никак, это они назвали себя Quality Assurance – а раз проводишь проверку качества, делай это качественно

Вот это мне особенно понравилось! Реально ведь встречаются люди, которые так думают.

Да, в какой-то момент батхёртнуло, только теги спасли.


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


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


ЗЫ Ещё надо помнить, что code is liability, так что чем больше тесты похожи на код, тем больше они liability.

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

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


А между интеграционными тестами и юнит-тестами реально есть некоторое провисание

Это же прекрасно. Хуже когда ахитектура позволяет писать юниты только размером с интеграционные.

Про провисание вы, возможно, не поняли. Я говорю, что с одной стороны есть юнит-тесты, с другой стороны есть интеграционные тесты; обе области хорошо исследованы и там есть удобный инструментарий. Но чем дальше мы от юнит тестов и от интеграционных тестов (слишком толстый для юнит, слишком поверхностный для интеграционного), тем хуже с написанием тестов. Там слабина и неудобно. И инструментария приличного нет.

Есть юнит тесты. Есть тесты взаимодействие компонентов между собой (интеграционные, компонентные). Есть тесты на взаимодействие всех компонентов между собой (end to end).


Я под интеграционными именно эту середину и понимаю. Пока для себя еще не сложил в голове чёткого представления, как с ними работать.


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


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

Нормальный, уверенный в себе программист всегда правит код на продакшне. Зачем тратить время на все эти гиты, CI/CD и прочую хипстерскую чушь? Все знают, что лучший друг программиста это ssh под рутом и GNU Nano.

Лучше vim — ведь из него невозможно выйти, пока всё не исправишь.

эх, шутки шутками, а ситуация страшная. Я однажды так чинил на проде один внутренний сервис для 3,5 сотрудников, так там схема была совсем грустная (не спрашивайте почему, сам был не рад): подключаюсь по teamviewer'у к машине с доступом к внутренней инфраструктуре, оттуда по ssh стучусь на прод, и правлю баги vim'ом прямо там. Попоболь от такого расклада сложно передать словами

Хотите я вам подкину ужастика? После сохранения файла на продакшене, оказывается что:


  1. Код в гите не соответствует коду на продакшене и безнадёжно забагован.
  2. Код в файловой системе сервера не соответствует запущенному, но тоже безнадёжно забагован.
  3. Запущенный код работает в screen'е, и это единственный правильный код, но его исходник (на файловой системе) случайно перезатёрли из старого vim'а (получив п.2).
  4. Человек, который писал код в скрине из аэропорта (вызвонили) уже в какой-то африканской республике без интернетов и на связь не выходит.
  5. Этот код что-то поменял в схеме базы данных и никто не может понять что, потому что бэкап сделать нельзя, потому что где-то там открыта транзакция в которой поменянная схема, есть новые данные, и эта транзакция не завершена (см п.3).
  6. Этот код работает уже неделю и от него в БД данных уже больше, чем было до его "починки".
  7. Где-то там стоит хотспара с stonith на ноду с программой в скрине, готовая сделать failover по таймауту в 300мс.
  8. Хотспару убивать нельзя, потому что развалится кворум с п.3.
  9. Хотспара проверяет доступность stonith и выходит, если его нет.

Enjoy your weekend.

image

Я был в п.3 Остальное — это моя пятничная фантазия. Алсо, у товарища с детьми кворум, он победил.

про покрытие бранчей и прочее.

при написании реактивного кода можно напороться на это самое покрытие бранчей

resolveHttpHeader().
       .flatMap(h -> requestDataFromAnotherService())
       .switchIfempty(respondWithError()) 


обе бранчи можно покрыть одним тестом. В случае нереактивного кода этот кусок выглядел бы так

condition = await resolveHeader()
if (condition) {
res = await requestDataFromAnotherService()
} else {
res = respondWithError() // не выполнится в тесте а значит не войдет в покрытие
}


а дело в том что в таком билдер-стайле чейнинга вызовов switchIfempty выполняется всегда, и покрытие считается по вызванному байткоду. Выход есть, но он выглядит уже менее красиво и не интуитивно. Но я вполне представляю себе ситуацию когда команда считает что у покрытие бранчей 80%, хотя реально оно скажем 30%.

Был как-то один проект, мы там использовали и статический анализ, и тесты — всё как положено. Время на это уходило таки прилично. Потом проект разорился и компания закрылась. Я не знаю причин почему так вышло, но думаю что отчасти это и медленный прогресс к продакшну.

самоирония статьи понятна, но по-моему мы, программисты порой забываем, что бест практики нужны не сами по себе, а для достижения определенных целей, и если какие-то цели для проекта не приоритетные, то от некоторых бест-практик можно отказаться. Иначе это какой-то «бест-практицизм», так сказать бест практики ради бест практик, а если кто против — сожжем его на костре
Не, ну давайте будем честными! Сарказм автора понятен, аргументация тоже. Ну и текст такой получился, веселенький :)

Но:
В IT-сообществе прочно укоренилось мнение, что все эти тесты вам хоть как-то помогают


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

Как так? А вот очень просто — попробуйте спросить своего пользователя, что ему нужно? И вы, возможно будете удивлены тому, как часто он вам скажет: «Не, дружок, надежность и качество твоей программы меня устраивает, давай лучши фичи пилить». Ну то есть, может он так и не скажет, всякое бывает. Но мне говорили.

А даже если заказчик сказал, что качество его не устраивает — он никогда не скажет «пишите больше тестов». Ему пофиг. Тесты — это ваш инструмент достижения качества, причем далеко не единственный. Я бы сказал, что лучший способ повышения качества — это вообще повышение квалификации исполнителей. А чтобы исполнители стали умнее — тесты вовсе не нужны, нужно разработчиков просто учить.

То есть, и без написания тестов вообще, качество кода может быть достаточным (не высоким или низким, а именно достаточным для потребителя), в зависимости от разных параметров, конечно — а точнее от таких широко известных всем, как сроки, стоимость и качество, а точнее — от их соотношения. Если на вас не давят сроки, а стоимость продукта (в виде высоких зарплат разработчиков) позволяет держать качество достаточно высоким без написания тестов — то… Я при этом заранее согласен, что так бывает далеко не всегда. Возможно даже редко.
Вы описали идеальную картину мира, как по мне. Но на деле это, как и любые другие идеалы, недостижимо.

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

Разумеется, ни пользователь, ни заказчик не скажут вам про важность тестов. Это не их компетенция, им просто нужен работоспособный продукт. А его работоспособность обеспечивают не только хорошие специалисты, но и хорошее тестирование (как QA, так и модульное).
Забыл добавить – когда проект сложно поднимается локально, то юнит и интеграционные тесты помогают понять, написали ли вы что-то рабочее или же нет.
Не, ну я там в конце написал, что может так и эдак не сложиться. И что это зависит от многих факторов.

>может стоить еще дороже
А вы меряли? Вот я не видел ни одного человека, который мерял бы. Серьезно. Особенно — в сравнении с другими методами повышения качества. Ну т.е. я ни разу не видел, чтобы показатель «у нас покрытие тестами 45% и этого хватает» был бы хоть чем-то обоснован, кроме… экспертной оценки потребителя, который нам сказал, что качества достаточно.

Ну т.е. мне кажется, нет никакой проблемы в том, чтобы писать тесты. Проблема в том, и это уже выше отметили, когда начать и когда остановиться, писать ли тесты, или скажем выбрать язык с более строгой статической системой типов, который не даст написать некоторые вещи неправильно (это только немного условный пример того, что можно сделать вместо тестов).
> выбрать язык с более строгой статической системой типов, который не даст написать некоторые вещи неправильно

Поверьте, это не особо поможет) Статическая система типов не беспокоится о вашей бизнес-логике.

Насчет дороговизны отсутствия тестов – нет, не измерял, вот честно. Но мне лично это кажется очевидным.

Кейс:
1. Разработчик пишет код без тестов. Запускает локально проект, вроде норм. Отдает тестировщикам
2. Тестировщики находят баги, возвращают
3. Разработчик продолжает ковыряться и получать зарплату

Вместо этого можно написать тесты, и тогда тестировщики не вернут задачу на доработку.

Это все условно, конечно. Ситуации в вакууме. Я согласен, что есть грань, и нужно преследовать не какие-то конкретные цифры в покрытии, а просто делать хорошо.

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

Ну а тесты не беспокоятся о доказуемой завершимости и кванторе всеобщности.

Ваш никнейм очень хорошо сочетается с вещами, о которых вы говорите.

Ну не менять же мне никнейм с каждой сменой интересов!

>Поверьте, это не особо поможет)
Ну во-первых, я же и написал что статическая типизация — это пример. Просто надо помнить, что есть другие методы повышения качества. Э… ну ручное тестирование, например?

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

И потом, почему мне нужно вам верить, если мне помогает? Ну т.е. я пишу минимум тестов — и при этом потребителя в основном устраивает результат. А там где не устраивает — там причина большинства недостатков кода совсем не в том, что нет тестов. Там либо слишком велика внешняя неопределенность (а тесты ее не снижают, как вы догадываетесь), либо код слишком сложен, в том числе для того, чтобы покрыть его тестами.

А когда удается достичь просветления :), и код упростить, чтобы его понимание стало кристально ясным — зачастую и баги в этом участке кода магически пропадают сами по себе. Т.е., для меня достаточно типичным является случай — что-то вот тут код странно работает, давайте его покроем тестами, для чего отрефакторим вот так и вот так. Отрефакторили. Бац — а все уже совсем хорошо. Ну т.е. даже цель в общем-то была — написать тест, но его еще не написали даже — а код уже стал лучше. Потому что основной способ сделать код лучше — это подумать над ним еще раз, и еще, и еще. Вот что мне реально помогает :)

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

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

> Отрефакторили. Бац — а все уже совсем хорошо.

А бывает, что отрефакторили – и что-то не то. Тесты такое отловят :)

На самом деле, я думаю, что мы говорим об одном и том же, но с разных ракурсов.
>Вот это кстати очень хорошо объясняет мне вашу позицию.
Моя позиция состоит в том, чтобы адаптироваться к разным условиям проектов. Во!

>А бывает, что отрефакторили – и что-то не то
Бывает. Но я собственно говорил о том, что рефакторинг, как процесс в чем-то улучшения кода (иногда чтобы написать тест, иногда нет) просто и приводит сам по себе к улучшению. Собственно, ну вот вы поймали тестом баг (у меня это кстати бывает достаточно редко — т.е. эффективность тестов в этом смысле низкая). Все равно же, чтобы починить его хорошо, а не заткнуть дырку, нужно понять, почему, где, когда, при каких условиях. Т.е. улучшить свое понимание этого куска кода, и его взаимодействия с другими кусками. А чем я собственно и заниимаюсь в процессе рефакторинга, если не этим же?

>На самом деле, я думаю, что мы говорим об одном и том же, но с разных ракурсов.
Ну да. Так я и не спорю с общей постановкой вопросов в тексте. Я просто уточняю некоторые моменты, с другой точки зрения.
А бывает, что отрефакторили – и что-то не то. Тесты такое отловят :)

У меня есть пара проектов, где есть только интеграционные тесты, проверяющие, условно, что компилятор на такой-то входной программе генерирует такой-то код, который на таких входных данных даёт такой выход. Отдельных тестов на какой-нибудь модуль оптимизатора, или, тем более, на отдельные функции в оптимизаторе или парсере или кодгене или ещё чём, нет. И, вы знаете, после рефакторинга, как только тайпчекер стал доволен, тесты сразу оказываются зелёные.

Насчет дороговизны отсутствия тестов – нет, не измерял, вот честно. Но мне лично это кажется очевидным.

Кейс:
1. Разработчик пишет код без тестов. Запускает локально проект, вроде норм. Отдает тестировщикам
2. Тестировщики находят баги, возвращают
3. Разработчик продолжает ковыряться и получать зарплату

Вместо этого можно написать тесты, и тогда тестировщики не вернут задачу на доработку.


Осталось только подсчитать, программист больше времени потратит на починку багов или на написание тестов?

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

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

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

> Осталось только подсчитать, программист больше времени потратит на починку багов или на написание тестов?

Я не знаю специфику вашей работы, но в моем опыте написать юнит тест – это лишние 10 минут. А отправка кода в тестирование, возвращение на доработку, анализ логов и повторный вход в контекст – побольше.

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

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

Вы описали идеальную картину мира, как по мне. Но на деле это, как и любые другие идеалы, недостижимо.

Это не идальная картина, это реальная картина. Мы все пользуемся софтом с багами, где-то их больше, где-то их меньше, но наличие багов не делает софт неработоспособным.

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

А может и не стоить.

Для этого нужны тесты – чтобы вы не просто добавляли новые фичи, но при этом и не ломали бы старые.

Возможно поломать дешевле чем писать тесты, возможно дешевле дать на тест пользователям, и они сами найдет баги. Сейчас очень многие так и делают: EAP, бета-версии, early access и т.п. это все отдают пользователям, которые по сути являются бесплатными тестерами и это может быть намного дешевле чем писать тесты.

Это не их компетенция, им просто нужен работоспособный продукт. А его работоспособность обеспечивают не только хорошие специалисты, но и хорошее тестирование (как QA, так и модульное).

Им нужен продукт который решает задачи, опять же, очень много кода покрыто тестами, но это не озночает, что в этом коде нету багов, как и не означает что он работоспособен.
Вы хотите сказать, что тесты – это не самоцель, и важен баланс, или в принципе против тестов?
Я хочу сказать, что могут быть ситуации, когда написание тестов не является экономически выгодным. Тоесть, следует исходить из ситуации и требований, а не слепо следовать утверждению, что с тестами всегда лучше, чем без тестов.

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

Пост я писал из своего опыта – а это энтерпрайз с более-менее крупными модулями. Тут с тестами однозначно лучше, чем без них.
На мой взгляд, с тестами однозначно лучше, при неограниченных ресурсах, тоесть когда их хватает на все, и на на автоматические тесты всех мастей, и на код ревью, и на ручное тестирование, и на тысты с продакшен данными, и на альфа/бета версии для пользователей, и на частичные выкатку на прод, и на разработку новых фич и т.д.
Но если ресурсы ограниченны, что обычно и бывает, то тогда как раз надо оценивать, что делать выгоднее.
Я бы сказал, что лучший способ повышения качества — это вообще повышение квалификации исполнителей. А чтобы исполнители стали умнее — тесты вовсе не нужны, нужно разработчиков просто учить.


Сомневаюсь, что даже очень компетентные разработчики способны держать в голове все нюансы функционирования проекта хотя бы среднего размера. А без этого реализация новой логики легко может что-нибудь сломать. И узнавать об этом от пользователей — такое себе удовольствие. И главное, примерно то же самое опять может сломаться через две недели после починки. По-моему, без тестов вы не можете гарантировать, что реализованный вами функционал работает через пять минут после того, как сдали его в прод.
А я не говорю, что они дежат в голове все нюансы. Но однако же, практика показывает, что синьор реально делает намного меньше багов на том же коде, по сравнению с миддлом. И потом, я и не говорю, что это единственный способ повышения качества. Он не заменяет другие, и не должен.
Еще же есть вопрос ввода новых людей в проект. Пусть они даже синьоры. До того момента, как они достаточно погрузятся в систему, могут пройти месяцы. А до этого количество багов от них может быть даже выше, чем у давно сидящего там миддла. И без тестов процесс вливания будет протекать еще сложнее.
Я надеюсь, не нужно особо пояснять, что квалификация вообще не растет быстро? Поэтому лучше всего обычно как раз сочетание разных способов — включая и тесты тоже. В зависимости от того, что имеется в наличии — проект и люди.

И тесты как вариант ведения документации в том числе — да, полезны.
Проблема в том, что чтобы сказать, что качество кода достаточное (не высокое или низкое, да), вам надо его протестировать достаточным количеством тестов с подходящей методологией. В противном случае качество кода вам не известно, то есть по умолчанию оно не может быть достаточным.
>вам надо его протестировать достаточным количеством тестов с подходящей методологией
Видите ли, статья называется «вам не нужны юнит тесты». Как раз юнит тесты про качество конечного продукта не говорят зачастую вообще ничего. Вот наши потребители — они вполне могут сказать, устраивает ли их качество нашего кода (можно условно считать это ручным или приемочным тестированием, хотя это не обязательно оно). Или интеграционное тестирование. Ну в общем, речь все о том же — есть другие виды оценки и повышения качества, кроме юнит тестов. И их по-хорошему нужно сочетать, в зависимости от разных параметров.

Качество кода и качество продукта коррелируют, но не сильно.

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

Ну и в итоге получается, что инструмент иногда ставят не на свое место, заменяя им цели.

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


Всё дело в том, что я чаще всего работаю над каким-то проектом в одиночку. Писать тесты, поддерживать тесты, писать документацию, поддерживать её в актуальном состоянии — это очень большой кусок работы. Не всегда один человек может тянуть весь комплекс. И в этом можно увязнуть, когда 80% всего времени ты тратишь на изменение тестов, документации, и прочего, вслед за небольшой правкой фичи.


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

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

Грань тонка. Если вы работаете на результат и обеспечиваете его, то это здорово. Но разработка ПО – это сложный процесс, и основной его жизненный цикл проходит в сопровождении, а не написании. Я бы предполжил, что вам неплохо было бы добавить еще человека, чтобы вам вместе было проще проводить необходимый комплекс работ, но, как я уже упомянул, я не в курсе тонкостей вашей работы.

> Всегда думайте своей головой. Не делайте чего-либо по инерции, просто потому, что все говорят так делать.

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

Представим, я пишу какой-то инструмент. Утилитку для себя, но и выложил её бесплатно в публичный доступ и набрал небольшую аудиторию, скажем в 1000 пользователей.
В случае критической проблемы при очередном обновлении, я не потеряю ничего. Да, будут недовольные пользователи, но не больше. Никаких убытков. А вот затраты на написание и поддержку тестов есть, хоть и не материальные.


При таком сценарии наличие тестов — полезно, но не главное, на чем стоит сосредотачиваться.


Забавный случай: как-то в моём приложении был большущий баг — огромная неработающая кнопка. И он был актуальным долгое время, потому, что ни один пользователь его не заметил и не отправил репорт.


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

Это я написал скорее для случайного читателя :) Уверен любой опытный разработчик прекрасно разбирается в теме и умеет расставлять приоритеты в каждом отдельно взятом проекте.

То о чём вы пишите очень сильно зависит от специфики. Приведу контр пример. Может не разобраться — если не про «экономию на кадрах» — сильно зависит от языка. Компилируемые со статической типизацией — это рай. И от проекта — возможность быстро отдебажить многое упрощает. И если приложение для обычных юзеров, у которых можно стрясти требования. Если это всё выполняется, то не нужны ни документация, ни тесты, а работоспособность кода достаточна где-то на уровне 85%.

Но да, нужно уметь читать код, а не только названия функций. И уметь рефакторить. Ну и задавать или не задавать вопросы по требованиям(если нашёл старые баги не по теме задачи), в зависимости от типа и объема оплаты. И да, даже при этом условии можно системно итерационно повышать качество продукта(или что там от вас хотят).

А документацию могут и выкинуть вместе с кодом и написать заново, если человек не в состоянии поддерживать или понимать(лень и наглость тоже может вызывать эти состояния).
Я с вами согласен насчет специфики. Правильнее даже сказать, что пост написан исходя из моего личного опыта, в котором наличие тестов упрощало жизнь.

> Но да, нужно уметь читать код, а не только названия функций.

Хочу только добавить, что чтобы уметь читать код, нужно прежде всего уметь его писать :)
Меня в молодости посылали RTFM по средствам разработки(лень было — думал проканает). И думаю это оптимально. Юзерам лейблы к кнопочкам и инструкции по установке ПО и всех зависимостей, «крутым хацкерам» RTFM.
я очень надеюсь, что это пранк такой:))
Руль, заклинивший в крайнем правом или крайнем левом положении — всегда очень плохо.
Занимаюсь ERP(Dynamics AX), сотни проектов, типовой это 50-200 активных пользователей с 3-5 разработчиками.
Юнит Тесты никто не пишет, все попытки что-то наладить упирались в трудоемкость разработки и самое главное — поддержки тестов. Типовой флоу — программист что-то делает у себя, отдает аналитику, тот прогоняет тестовые сценарии.
А вы у себя выполняли замеры во сколько вам обходится разработка тестов? Во сколько обходится поддержка(ну т.е. например ложные срабатывания)? И сколько вы реальных ошибок смогли найти используя тесты(ну т.е. ошибки которые бы прошли все остальные стадии проверки, но нашлись только юнит-тестированием)
И сколько вы реальных ошибок смогли найти используя тесты

Чтобы написать тест нужно понимать какой конкретно результат нужно получить. Чтобы код писать достаточно абстрактного представления о том, что должна делать программа. Разницу в поверхностом и детальном понимании проблемы сложно померить в багах.


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


Если писать юниттесты вместе с кодом, то ложные срабатывания и баги в основном исправляются до коммитов.


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


Я достаточно сильно разбиваю код на модули и юнит-тесты у меня в среднем 3-5 строк с быстрым выполнением.

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

Но обычно так — заказчик (бизнес) пишет BRD и передает его аналитику. Тот пишет FSD и передает разработчику.

Дальше в обратном порядке. Разработчик минимально тестирует чтобы совсем сразу не падало и отдает аналитику. Тот проводит компонентное тестирование на соотвествие FSD и если все ок, передает заказчику. Те в свою очередь проводят бизнестест на соответствие BRD. Дальше уже проводится интеграционное и нагрузочное тестирование на копии промсреды (на тестовых средах объем данных на порядок меньше).

И только по завершении всего этого внедрение на пром.

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

Автотесты тоже бывают, но для типовых задач и в ограниченном объеме.
Это идеальный сценарий :) Есть еще такой
Разработчик минимально тестирует чтобы совсем сразу не падало и отдает аналитику. Аналитик думает — ну разработчик же тестировал, зачем мне напрягаться, передает заказчику. Те в свою очередь думает — ну парни же профи, им можно доверять, переносим на прод…
Разработчик минимально тестирует чтобы совсем сразу не падало и отдает аналитику. Аналитик думает — ну разработчик же тестировал, зачем мне напрягаться, передает заказчику. Те в свою очередь думает — ну парни же профи, им можно доверять, переносим на прод…


Такого у нас не бывает. Аналитик всегда знает что тестирование логики — его задача. Заказчик тоже знает что его задача проверять то ли он получил что хотел (тут сразу и аналитика проверяют — как он FSD по BRD написал, и разработчика).

Для этого есть библиотеки типа Faker:
Генеришь нужные данные для конкретного теста и работаешь с ними, проверяешь суммы и т.д.
Данные заново генерятся перед каждым прогоном теста и откатываются после


но потом кто-то внесет какое-то изменение и тест свалится

В том и суть — если он не учёл все последствия внесения своих изменений, это будет видно на тесте, а не в проде

С генераций тоже проблемы. К примеру даже взять мой простой пример, клиенты бывают локальные, бывают иностранные, валюты в проводках могут быть локальными валютами, могут быть иностранными. Т.е. это уже дает 4 разных комбинации данных. Любой процесс посложнее даст миллион различных комбинаций
если он не учёл все последствия внесения своих изменений, это будет видно на тесте, а не в проде

Ну вот это главное что вызывает вопрос — когда другой разработчик будет писать код, он сознательно меняет логику системы. Опять же для моего примера, изменили мы механизм пересчета курсов(к примеру вышел какой-нибудь банковский приказ, брать курс не на сегодня, а на завтра), все тесты которые считали сумму проводок автоматически стали падать. Какой в этом положительный смысл и кто их должен чинить и главное зачем. Это приведет к огромным затратам на поддержку, без положительного результа

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

А у вас есть общение с базой данных?

Вот тут юниттестам и конец. Это уже интеграция. Я и сам долго считал, что юниты это сложно, пока не понял, что на самом деле это были интеграционные тесты которые пытались тестировать инварианты в логике кода. Такие тесты зло и трата времени.


примеру пишем код который получает сумму проводок по клиенту в какой-то валюте.

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


Если бинзнес логика идёт в перемешку с кодом который генерирует SQL, выполняет запросы в базу и разбирает ответы, то юнит тесты здесь не применимы.


Я начал строить даже небольшие автономные кусочки кода (AWS Lambda, Python) через архитектуру (разделять получение и обработку данных) и остался доволен. Когда собираешь приложение из протестированных кусочков, то интеграционные тесты на взаимодействие этих кусочков не очень сложные (они проверяют что модуль А дёрнул метод модуля В). А на энве ловишь в основном интеграционные проблемы с внешними сервисами.

Ну вот попробую рассказать текущую задачу.

Есть некий «список». Он поступает в виде набора «субъектов», каждый из которых имеет уникальный идентификатор и содержит некоторый набор информации. Все это раскладывается по 9-ти таблицам.

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

Задача. Нужно взять последний загруженный список, определить какие субъекты в нем присутствуют, собрать по ним информацию из 9-ти таблиц и занести в 10-ю (сформировав для него новый набор записей). Причем, надо сравнивать что уже есть в этой таблице.

Варианты такие — в таблице есть записи по субъекту, которого не было в последнем загруженном списке. Их надо удалить. В таблице есть записи по субъекту, присутсвующему в загруженном списке — надо сравнить какая информация там лежит с тем что пришло и если есть расхождения, обновить ее (причем, запись-в-запись по ряду причин сравнивать невозможно — нужно прочитать все, составить наборы и сравнивать их). В таблице нет записей по субъекту, который пришел в новой версии списка — нужно добавить.

Тут и работа с БД и логика. Понятно, что все это разносится внутри — читаем 9 таблиц, строим новые информационные наборы. Читаем из 10-1 — строим старые информационные наборы.
Сравниваем наборы на предмет наличия расхождений.
Если расхождения есть — формируем из новых наборов набор записей для 10-й таблицы и пишем туда.

Но вот как-то так… И таких задач у меня сплошь и рядом.

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

В таких задачах обязательно нагрузочное тестирование — оценить общее время работы (а он может быть несколько часов), оценить нагрузку одного потока на машину (где в это время работает еще несколько тысяч процессов), выбрать оптимальное для соотношения загрузка машины-время обработки количество потоков…
Но вот как-то так… И таких задач у меня сплошь и рядом.

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


А сколько по времени проходит от начала работ до передачи в тестирование и от тестирования до прода?


В таких задачах обязательно нагрузочное тестирование

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

Я так понимаю, что задачи с коротким циклом разработки (нет постоянных узменений и улучшений).


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

Но вообще у нас больше «длинных» задач. Т.е. есть требования — разрабатываем под них. Потом требования меняются — дорабатываем под новые изменения.

Интеграционное тестирование обязательно т.к. очень много функций (мы это не называем микросервисами, скорее API, хотя по сути очень близко), которые вызываются потом очень много откуда. И изменение логики работы функции не должно ничего поломать.

А сколько по времени проходит от начала работ до передачи в тестирование и от тестирования до прода?


Ну вообще стремимся сокращать TTM (time-to-market). Но не в ущерб качеству. Какого-то усредненного показателя назвать затруднюсь — задачи очень разные по объему кода, логики, вариантов входных данных.

Есть задачи очень длинные. Вот сейчас у меня в работе задача, которой около года уже. Но там поставка под 200 объектов и только кода под мегабайт. Не считая таблиц, индексов, настроечных скриптов… Она уже практически завершена в разработке и большая часть оттестирована (тестирование готовых кусков шло параллельно разработке). Думаю, что после праздников таки внедримся. Описанное выше, кстати, есть ее небольшой кусочек.

Но разработка ее не шла непрерывно — часто приходилось отвлекаться на что-то более срочное. Недавно вот две срочных задачи за две недели. Разработано, оттестировано и внедрено.

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

Периодически еще бывают моратории на внедрение. Там только хотфиксы срочные по особому согласованию внедряются.
Интеграционное тестирование обязательно т.к. очень много функций (мы это не называем микросервисами, скорее API, хотя по сути очень близко),

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


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


Сложности интеграционных тестов растёт экспонентциально сложности сервиса. Микросервисы (строгий подход к работе с зависимостями) могут решить эту проблему не давая им разрастаться.

У нас это не проходит. Все происходит на достаточно изолированном сервере. Никакие запросы извне в него не пройдут. И интеграция вся внутри этого сервера.

Ну вот к примеру самый простой случай. Есть некая проверка CheckA. Которая получает на вход определенный набор информации и возвращает на выход некий код. Если мы поменяем внутри логику и набор возвращаемых кодов, то есть риск, что те 1000 (условно) модулей, которые эту проверку дергают для своих целей, просто не поймут что она возвратила и их логика сломается.

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

Это очень утрированные примеры, на самом деле все еще сложнее. Мы работаем в системе, где одновременно работают тысячи взаимосвязанных между собой объектов (задач). Даже при строгом сохранении интерфейсов (это вообще святое) всегда есть риск нарушить общую логику работы всей системы, изменив логику работы одного объекта. Поэтому очень часто прежде чем менять что-то внутри модуля, приходится выяснять а откуда он вообще вызывается и что там от него ждут.

Репликаторы — отдельная тема. Это задачи, которые постоянно крутятся и отслеживают изменения в различных таблицах. В случае такого изменения, они смотрят что изменилось и в при совпадении заданных условий выполняют некоторые действия. Тут попасть в клинч как с добрым утром — один репликатор отследил изменеия в таблице А и внес изменение в таблице Б. Но там тоже работает репликатор, который опять что-то меняет в таблице А (на самом деле, цепочка может быть достаточно длинной и затрагивать несколько таблиц)…

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

Публичный контракт cервиса, но при этом не часть API которое святое? Алгоритм генерации вполне попадает под юниттесты.


Даже при строгом сохранении интерфейсов (это вообще святое) всегда есть риск нарушить общую логику работы всей системы, изменив логику работы одного объекта.

Примерно так и описывают плохую архитектуру. Поменяли в одном углу, отвалилось в другом.


Тут попасть в клинч как с добрым утром — один репликатор отследил изменеия в таблице А и внес изменение в таблице Б.

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

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

Да вроде у вас тут нормально все тестируется. Есть функция loadListFrom10Table(), мокаем ее, чтобы мок возвращал фиксированный массив данных, в котором встречаются все варианты для заданного субъекта. Функции, которые пишут результат в базу, тоже перехватываем, и либо проверяем что произошел вызов с нужными аргументами, либо заменяем реализацию, чтобы они меняли этот фиксированный массив в памяти, и сравниваем получившийся результат с заданным.

Вот тут юниттестам и конец. Это уже интеграция.

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

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

Это да, но если делать упор на управление зависимостями то чистых и почти чистых становится больше.


К примеру придется использовать существующий механизм пересчета из разных валют

Если это внешний модуль по отношению к коду, то его в тестах можно замокать.


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

Тест это вещь в себе. И входящие занчения и результат известны стразу. Если результат теста зависит от состояния внешней системы, то это плохой тест: он упадёт, без изменений в коде.


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


Тут правдо нужно сделать оступление и сказать, что я пишу на Python с библиотекой pytest. Это очень мощная библиотека, после неё с Junit5 в Джаве чувствуешь себя как будто в каменный век вернулся.

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


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

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

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

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

Ну главный вопрос — какой в этом практический смысл. Т.е. меняя что-то(пересчет курсов), я ожидаю что все кто его использовал поменяют поведение. Для этого и нужна ООП собственно. То что они в своих тестах этого не покрыли, это как бы не хорошо, но никакой практической пользы проекту это не несет
Т.е. меняя что-то(пересчет курсов), я ожидаю что все кто его использовал поменяют поведение. Для этого и нужна ООП собственно.

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

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

Ну т.е. у вас предположение что наличие юнит тестов понизит кол-во багов? По моему ошибки в любом случае будут, каждая со своей стоимостью решения. пока тут никто не привел конкретных цифр сколько конкретно багов позволило это найти, кол-во затрат времени на написание таких тестов, кол-во ложных срабатываний и время исправления этих ложных срабатываний. Т.е. пока складываеся мнение если мы берем типовое приложение CRUD(где есть работа с базой данных) то трата времени на юнит тестирование это довольно неэффективный способ траты времени
В вашем примере с подпиской это может быть аналогично конкурентам, которые потратят это время на доп. функционал или снижение стоимости подписки

Понизит количество багов, выявленных после передачи задачи в тестирование.


А такие цифры вряд ли кто приведёт, потому что обычно они не документируются: юнит-тесты запускаются локально до коммита кода, в пайплайны попадает только код который должен пройти хотя бы "свои" юнит-тесты локально и только по нему можно собрать статистику малой кровью.


В типовом приложении CRUD будет очень мало юнит-тестов скорее всего, потому что будут использоваться типовые фреймворки, библиотеки, да и типовая база данных, которые юнит-тестами обычно хорошо покрыты. В таких приложениях обычно нужны интеграционные и функциональные тесты. Вот на проектах на Laravel (популярный PHP-фреймворк, заточенный под CRUD, имхо) настоящие юнит тесты редкость, даже если почти все тесты лежат в папочке tests/unit — им нужен поднятый контейнер (читай — весь фреймворк) и нужна база данных, часто очереди и т. п., а значит они по определению не юнит.

у т.е. у вас предположение что наличие юнит тестов понизит кол-во багов?

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

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

Вообще, я бы не стал отделять юнит-тесты от разработки. Это единое целое. Разработчик должен не просто писать код, ведь сам по себе код никому не нужен. Разработчик должен предоставить какой-то результат, и это единственное, что требуется. Причем код, который что-то делает, а что-то нет, результатом не является. Для того мы и пишем маленькие модульные тесты на свой код, чтобы удостовериться в том, что результатом нашей работы в принципе можно пользоваться.
Ну ложные срабатывания — вы меняете что-то, отваливаются какие-нибудь тесты, вы начинаете разбираться, понимаете что это не баг, а просто кто-то не учел ваше изменение, т.е. надо править тест
Вообще, я бы не стал отделять юнит-тесты от разработки. Это единое целое.

Это тоже сомнительное утверждение. Ну чтобы убедиться что результатом работы можно пользоваться, можно например сделать ручное тестирование(которое все равно надо делать) и не тратить время на написание автотестов.
Возьмите кстати для примера Киберпанк который недавно вышел. Они там и без всяких дополнительных тестов знали что игра содержит кучу багов, но все равное ее зарелизили. Т.е. какой тогда смысл тратить время на юнит-тесты(которые позволят найти еще больше багов), когда баги и так известны. Лучше это время потратить на их исправление
У вас какое-то поверхностное отношение к тестам. Ну, либо поверхностное понимание причин, по которым они нужны.

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

Такие штуки должны случаться очень редко. А то забавно у вас получается – тест сломался, значит надо менять тест. Если у вас отвалились какие-то тесты, то вам надо править как раз код до тех пор, пока они не перестанут отваливаться. Про «просто кто-то не учел ваше изменение» – совсем смешно. Кто-то должен учитывать ваши изменения, чтобы код оставался рабочим? Или это вы должны изменять код так, чтобы ни у кого ничего не отвалилась?

Ну чтобы убедиться что результатом работы можно пользоваться, можно например сделать ручное тестирование(которое все равно надо делать)

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

Насчет киберпнка – вы сами-то играли? Я наиграл 16 часов и получаю удовольствие от игры. Лично встретил пока что один баг (вражеский солдат завис), но он меня не лишил удовольствия. Но это другое, думаю, там ситуация такая все-таки не из-за юнит тестов)
Если у вас отвалились какие-то тесты, то вам надо править как раз код до тех пор, пока они не перестанут отваливаться.

Тут, наверное, ситуация:


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

И, наверное, имеется влияние стереотипа "тесты должны выявлять баги", хотя они должны выявлять отклонения от зафиксированного поведения.

Просто изменения логики приложения с последующей коррекцией тестов и непреднамеренное ломание других частей системы – разные вещи.

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


Да, баги в тестах бывают. Основной — когда он всегда зелёный :)

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

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

Думаю, суть кроется в тонкостях понимания пользователем принципов ООП с точностью до наоборот:
Т.е. меняя что-то(пересчет курсов), я ожидаю что все кто его использовал поменяют поведение. Для этого и нужна ООП собственно.

Я вообще не понял причём тут ООП.

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

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

Но ведь по условию поведение и должно было измениться...

Бинго! И надо было изменить в рамках задачи те части кодовой базы (а тесты, особенно юнит — её часть), которые опирались на старое поведение, а не называть их ошибочным кодом, который кто-то должен исправить.

Все эти "надо" не отменяют того факта, что с тестами объём кода, который нуждается в исправлении, повышается.

А это плохо? Я согласен с утверждением, что тесты гарантируют, что ранее рабочие части системы не перестали работать после правок. Да, увеличенный объем необходимых для внесения правок – это цена такой гарантии. Суть в том, чтобы платить умеренную цену и не тратить на правки тестов времени больше, чем на правки кода, как по мне.

Тут больше терминологический спор. Я не считаю, что падение тестов после внесения изменения в поведение, но до внесения изменений в тесты — это баг тестов, ложноположительное срабатывание. Это обычное положительное срабатывание: "поведение тестируемой системы изменилось" и означает, что тесты работают более-менее правильно, выполняют то, для чего созданы. Просто они уже не актуальны для наполовину сделанной задачи.

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

Наконец-то, кто-то вскрыл правду!

и сразу заметили иронию

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

Пускай себе говорят, это не мешает нам иронизировать на эту тему.

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

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

Зачем нужны тесты? Нужно просто не делать ошибок!
Хм. Ошибок где? В коде? Так 99% их вылазит на этапе сборки.

Тесты нужны для выявления ошибок логики. А она может быть весьма нетривиальной и запутанной.
Да нигде не делать!
И да, мой коммент выше — сарказм, в подражание статье. =)

Это если этап сборки у вас есть.

Если вы дочитали до этого момента и не бросились писать гневный комментарий, то либо вы прекрасно понимаете важность тестов и сразу заметили иронию, либо просто обратили внимание на теги :) Друзья, это были вредные советы.
Надеюсь, автор заметил по комментариям, что многие восприняли статью всерьез, или догадались об иронии не сразу.
Голосую за то, чтобы автор(ы) не применял(и) такой стиль изложения.

Время программистов – дорогое. Время тестировщиков – дешевое.
Не такое уж и дешевое — в среднем 80% от зарплаты программиста.

Ученые давно выяснили, что постоянное переключение между контекстами истощает ресурсы мозга.
Если у кого есть под рукой ссылки на исследования ученых, поделитесь, плиз. Можно на английском.

Я однажды слышал один забавный диалог:
– Сколько человек сейчас тестирует нашу систему?
– Один человек.
– Мы только что выкатили ее на прод.
– Ну… значит, нашу систему тестирует 1000 человек.
Это больше похоже не на забавный диалог, а на горькую правду жизни, к сожалению.

Хипстеры придумывают кучу парадигм – TDD, BDD, ПДД, ГИБДД – лишь чтобы создать иллюзию бурной деятельности и хоть как-то оправдать свою зарплату.
Злая шутка получилась. Многие своей кровью и жизнью за ПДД заплатили. И продолжают платить.
Надеюсь, автор заметил по комментариям, что многие восприняли статью всерьез, или догадались об иронии не сразу.
Голосую за то, чтобы автор(ы) не применял(и) такой стиль изложения.

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

Не такое уж и дешевое — в среднем 80% от зарплаты программиста.

Я бы эти цифры оспорил, но не в том суть. Время тестировщика не дешевое, и переоценить вклад хорошего тестировщика в проект сложно. Это очевидно, что написано про дешевизну времени было ради шутки и соответствовало духу статьи. Опять же, если ты тестировщик и обижаешься на это – тебе бы отдохнуть слегка.

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

Книга «Сила воли. Как развить и укрепить» Келли Макгонигал. Сама книжка очень крутая, и там есть ссылки на эти самые исследования. Речь идет не о переключении контекста по приходу домой с работы, а про постоянное переключение между разными задачами в пределах рабочего дня.

Злая шутка получилась. Многие своей кровью и жизнью за ПДД заплатили. И продолжают платить.

При чем тут это? Похоже, что ты просто решил докопаться до конкретных предложений и даже слов, даже поверхностно не понимая суть всего поста…
Когда мне начинает неуважительно «тыкать» человек, который почти на поколение моложе меня, желание продолжить обсуждение моментально пропадает.
Вы так пишете про свой возраст, как будто это на что-то влияет. Люди выстраивают свое мнение о ком-то базируясь не на сухом возрасте, а на знании дела и умении им делиться. Я не сомневаюсь, что знание дела у вас побольше моего, вы же как-никак на поколение старше, но вместо демонстрации этого знания вы просто придираетесь к конкретным словам без особого углубления в тему поста.
Вот так-то лучше. Продолжаем разговор.

вы просто придираетесь к конкретным словам без особого углубления в тему поста.
Приведите пример.
Да весь ваш комментарий выше) Зачем вы мне пишете про соотношение зарплат разработчиков и тестировщиков? Статья не про это. Зачем пишете про ПДД? Статья и не про это тоже.

Лучше расскажите, какой у вас был опыт с написанием/сопровождением тестов или какие были проблемы от их отсутствия. Это будет по теме.
Зачем вы мне пишете про соотношение зарплат разработчиков и тестировщиков? Статья не про это.
Раз вы упоминаете об этом в статье, значит она и про это. Вот вам еще один пример вреда завуалированной иронии.
Заголовки двух предыдущих статей вы начинали со слов «Вредные советы». Не знаю, сколько читателей меня поддержат, но я прошу вас впредь поступать так же.

Зачем пишете про ПДД? Статья и не про это тоже.
Потому что такими вещами не шутят. Это примерно то же самое, что пошутить «у меня папа умер».

Так что, ваши обвинения в том, что я «придираюсь к словам» беспочвенны.

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

А вам предлагаю исправить ошибку во фразе «тестировать, и тд», о которой я давно сообщил через Ctrl-Enter. И давайте на этом закончим.
Заголовки двух предыдущих статей вы начинали со слов «Вредные советы». Не знаю, сколько читателей меня поддержат, но я прошу вас впредь поступать так же.

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

Потому что такими вещами не шутят. Это примерно то же самое, что пошутить «у меня папа умер».

Где вы заметили шутку в негативном плане? Я лишь привел термин ПДД, потому что это созвучно с TDD, BDD, и это подошло под общий настрой статьи. Не более того.

Так что, ваши обвинения в том, что я «придираюсь к словам» беспочвенны.

Ага, и сразу же:
А вам предлагаю исправить ошибку во фразе «тестировать, и тд», о которой я давно сообщил через Ctrl-Enter.

Действительно, вы придираетесь не к словам, а к отдельным символам. Вам спасибо, разумеется, за то, что сообщили об ошибке. Но не нужно меня уже в ТРЕТИЙ раз просить вместо «и тд» написать «и т.д.». Это идиотизм.

Я ради интереса посмотрел ваши комментарии к другим постам. Господи, да вы тот еще буквоед. Я бы заменил последнюю букву, но правила это запрещают. Вас действительно не смущает указывать авторам (а не просто комментаторам) на грамматические ошибки? Даже при условии, что сама статья вам вполне понятна, то есть не кишит ими? Вы не видите контента как будто, вам нужно просто до чего-нибудь докопаться. Показать, что вы умнее, самоутвердиться.

Для начала сходите и сами исправьте свой комментарий здесь, к примеру: habr.com/ru/company/selectel/blog/533412/#comment_22436494
«-тся» и «-ться» – это из какого класса? 5-6? Или же это начальная школа? Ах да, вы же уже не можете исправить свой комментарий, и все увидят, что вы тоже неграмотный.

И да, я сейчас перехожу черту и веду себя как идиот. Но вам же неприятно, верно? Так и сами себя так не ведите. Ежу же понятно, что вы хотели донести мысль, и я ее понял, да и вообще я сильно сомневаюсь, что вы не знаете этого правила. Скорее всего, допустили такую ошибку по невнимательности или утомленности. Уж правила-то вы знаете, это видно. Но докапываться до «тд» vs «т.д.» ТРИ раза (дважды в личном сообщении еще) – это просто бред.

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

Ну так сходите и напишите! Поделитесь своим опытом, покажите, что вы хоть что-то знаете и умеете. А пока что я вижу лишь диванного комментатора, очень крутого, который все обещает написать про свой 15-летний опыт, но за 2 с лишним года на хабре этого еще не сделал. Который только в комментариях раздает указания тем, кто действительно что-то пишет.

И не нужно упоминать про свой почтенный возраст и неуважительное отношение. Было бы за что уважать.
Мне безусловно есть что ответить, по каждому пункту.
Но я вижу, что многократные объяснения вам в комментариях, что мир нельзя делить на евреев и не евреев не сделали вас чище.
Поэтому разговор окончен.

Не вчитывался в подробности, потому что из заголовка ясно, что это правильный тезис.
У бизнеса есть желание быть уверенным в качестве ПО и ресурс. Если у бизнеса есть ресурс, то он может его потратить на повышение качества. Некоторые в бизнесе считают что юнит-тесты повышают качество. Главный вопрос настолько же повышается качество насколько затрачивается ресурс? Очевидно, что достичь 100% качества с помощью юнитов навозможно, но потратить 100% ресурсов да. Еще один отрицательный эффект в том, что чем больше тестов, тем меньше прирост качества. Внимательному менеджеру часто заметно, что тесты — отличная возможность разработчику перевести срывы сроков, размазав их на тестирование, поскольку часто оно больше времени зафакапленной разработки. Притом логически не верно поручать делать тесты тому кто мог породить ошибки, тем более что разработчики чуть ли не самый дорогой ресурс проекта. Есть и такой эффект, который инкриминируют гомеопатии, что при использовании вероятностной методики могла быть фатально не оказана своевременная помощь, также и зеленые лампочки на CI имеют успокоительный эффект, который может убаюкать перед запуском некачественного релиза. В итоге юнит-тестирование — онанизм перфекционистов, просто религия невникающих в общий смысл проекта как достижение не просто качества, а недорого и в сроки.

Я определенно возьму некоторые ваши тезисы для следующих вредных советов. Про успокоительный эффект зеленых огоньков CI особенно понравилось. И правда, фигня все это! А вот красные огоньки ошибок на продакшене бодрят как следует!

делайте контракты в коде, заметите раньше CI

Притом логически не верно поручать делать тесты тому кто мог породить ошибки

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


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

Пост из серии "Если жизнь и научила меня чему-то, так это никогда не возвращаться за сумочкой" (с) Д. Адамс.


Девелопер с опытом не будет дискутировать на тему, что юнит-тесты не нужны, как и не будет дискутировать на тему, что юнит-тесты нужны. Границы применимости юнит-тестов — вот предмет для дискуссий. Но наброс на вентилятор зачётный (y)

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

Девелопер с опытом не будет дискутировать на тему, что юнит-тесты не нужны, как и не будет дискутировать на тему, что юнит-тесты нужны.

Так дискуссии пошли в комментариях, вы хотите сказать, что все отписавшиеся выше – девелоперы без опыта? Дискуссии созданы для того, чтобы делиться опытом.

Границы применимости юнит-тестов — вот предмет для дискуссий.

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

Вы читали "Автостопом по Галактике"? Забавная книга, рекомендую.


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


У вас уже есть опыт, показывающий важность юнит-тестирования. Когда-нибудь и у вас появится опыт, показывающий неважность юнит-тестирования, и останется самая малость — "научиться отличать один случай от другого". У меня такой опыт был и я своё видение изложил здесь (с тех пор оно не сильно изменилось).

«Не, я только Каштанку читал. Хочешь, за жопу укушу?» (с) Гоблин в переводе «Властелина Колец».

Не понимаю, зачем вы мне именно здесь рекомендуете художественную литературу ¯\_(ツ)_/¯ Как и утверждаете, что однажды у меня появится тот или иной опыт. Про применимость тестов есть отдельные посты, например ваш. И даже более объемные и фундаментальные. Но это не запрещает кому-то просто пообщаться на тему самих тестов и важности их применения. И это не говорит о том, что в беседе принимают участие только неопытные щенки, которые еще «в своем познании не настолько преисполнились...»
И это не говорит о том, что в беседе принимают участие только неопытные щенки, которые еще «в своем познании не настолько преисполнились...»

Могу лишь процитировать вас же: "каждый видит то, что хочет" (с) Или может. Я лишь имел в виду, что, имея какой-то опыт, невозможно отрицать полезность юнит-тестов. Как и невозможно рекомендовать их пихать во все проекты. Считайте, что я среагировал на ваш провокационный заголовок — "Вам не нужны юнит-тесты" ;)

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

Это понятно, что нет крайностей – либо покрытие каждой строки и каждой ветки, либо ничего. Где-то юнит-тестирование не имеет особого смысла, например, когда большая часть теста – это моки. Но это детали. Разумеется, тесты нужно писать с умом. Это все логично.

Опять же, пост – не провокация. Да, я предполагал, что это вызовет дискуссии, но не в этом была цель. Это просто вредные советы на тему важности тестов, это даже не рассуждения на тему грамотности их использования.

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

Вы увидели, что захотели. Или смогли.


Но это детали.

Детали — это самое интересное. В них прячется дьявол.


Опять же, пост – не провокация.

Я говорил только за заголовок.


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

Не запрещено. Бессмысленно. Имея некоторый опыт вы убедитесь как в полезности unit-тестирования, так и в бесполезности. "Unit-тестирование важно, но не для всех проектов" — попробуете подискутировать?

Или смогли.

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

Единственное, что раздражает, так это то, что вы в очередной раз надменно намекаете на то, что у вас этот опыт уже есть, а у меня – нет. И когда я вырасту, наберусь опыта, достигну вашего уровня, тогда я смогу узреть, о чем вы говорите. А говорите вы, как ни странно, об очевидном.
«Unit-тестирование важно, но не для всех проектов» — попробуете подискутировать?

Я не обладаю всеобъемлющим или каким-либо специфическим опытом, поэтому я бы перефразировал: «написание юнит (интеграционных) тестов зависит от специфики проекта».

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

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

Коллега, моя ошибка в том, что я посчитал, что "Автостопом по Галактике" — достаточно распространённое произведение, чтобы можно было его процитировать :)


Я попробовал обратить ваше внимание, что у "медали" "Вам не нужны юнит-тесты" есть другая сторона. Т.к. цитата из Адамса прошла мимо, я дал ссылку на свою статью, где о другой стороне говорится в явном виде (не вижу ничего крамольного в этом). "Девелопер с опытом" — это тоже отсылка к Адамсу. Нужен опыт, чтобы понять, что иногда за "сумочкой" возвращаться нужно, а иногда не стоит, и очень много опыта, чтобы знать, нужна ли "сумочка" в данной конкретной ситуации (границы применимости). У меня, например, такого опыта нет. Думаю, что такого универсального опыта вообще ни у кого нет.


Ваш пост я оценил положительно при первом своём комменте, плюсик в карму поставил. Всё, что я мог написать по этому поводу я уже написал. Ваше мнение о моих словах — это ваше мнение и я ничего не смогу с ним поделать. Только вы сами.


P.S.
"Например, вместо теста на определенную функциональность просто делать контрольную сумму на файл и алертить, когда он меняется. В вашем опыте это решение помогло, спасло время и было надежно."


Я этого не делал.

Можно подискутировать нужны или не нужны. Можно о границах применимости. Можно о целесообразности. Это всё субъективно, зависит от людей, от команд, от проектов. Решение внедрить юнит-тесты в проект может убить его в итоге, а может значительно улучшить скорость и/или качество разработки.

Девелопер с опытом не будет дискутировать на тему, что юнит-тесты не нужны, как и не будет дискутировать на тему, что юнит-тесты нужны.

Конечно он же с опытом, поэтому сделает КАКОБЫЧНО. :)

Нужно больше иронии!
Во время прочтения мысли постоянно скакали между «да этот человек сумасшедший» и «о, как забавно он пишет».
Особенно позабавило,
Но сегодня пятница
однако сегодня среда)
однако сегодня среда)

Завтра мы оба окажемся неправы :(
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.