Pull to refresh

Comments 22

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

Плюс полноценное внедрение подобных методологий требует наличие развитых DevOps процедур и технологий, внедрение которых часто тоже ложится на разработчиков. То есть они воспринимают это как перекладывание на них ещё и обязанностей опсов-админов.
TDD действительно не то, что должны делать тестировщики. Их задача писать функциональные тесты и, если хвататет квалификации, интеграционные. TDD не TDD, но разработчики испокон веков занимались тестированием, запуская свой код и проверяя как он работает, юнит-тестирование это скорее формализация этого процесса.
Разработчики привыкли, что базовое тестирование функциональности — это полностью их зона ответственности, никто их не ограничивает в ней, не диктует и не проверяет объёмы, форму, инструменты и даже саму необходимость тестирования. Это с одной стороны. С другой — привыкли, что результат их работы (читай — то, что коммитится в репозиторий) — основной код, максимум конфиги для него.
Одной из причин НЕ внедрения тестов может быть бизнес. Тестирование увеличивает стоимость разработки, в ближайшей перспективе, в несколько раз. Это оплачивает клиент. Возможно, иногда можно продать продукт без тестов, в то время как с тестами нельзя. Впоследствии внедрить тесты в такой продукт может быть очень сложно.

Если тестировать только то, что действительно нужно тестировать, и делать это правильно (читай — не писать хрупкие юнит-тесты, которые постоянно ломаются и нуждаются в непрерывной поддержке) — то не в несколько раз. По моему опыту на разработку нормальных юнит-тестов (с покрытием 80-90%) нужно примерно столько же времени, сколько и на разработку кода, который они тестируют. Таким образом время (стоимость) непосредственного написания кода удваивается, но в общей стоимости проекта написание кода это далеко не 100%, так что в финале стоимость разработки увеличивается примерно в 1.5 раза.


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


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

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

Абсолютно верно.

то не в несколько раз

Может быть вы правы, и добавьте еще приемочные тесты, не говоря про интеграционные тесты, обучение тестировщиков, аналитиков. И все это можно умножить на специфику продукта.

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

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

Отсутствие тестов на код не оставляет шансов на изменение скоупа продукта как в ходе разработки, так и после нее, и делает багфиксинг неприемлемо дорогим.
Да.

Мне нравится картинка на тему багфикса на таких проектах:

Так и не понял — на чём автор основывает свою статью? Можно ли увидеть где-нибудь увидеть методы исследования, цифры опросов разработчиков и ПМ?
Или всё это одно большое IMHO? Ну так нужно так и писать тогда: «по моему мнению, в компаниях, в которых я работал, автоматическое тестирование развито слабо», вместо безаппеляционного мнения, преподносимого как.истина в последней инстанции.
Я вот работал в компании, которая автоматические тесты пишет с 90х годов. Что дальше, моё мнение против мнения автора?
Тем более, для внедрения TDD/BDD и изобретать ничего не нужно, в современных средах разработки достаточно добавить тестовый проект. На самом деле это единственно возможный способ убедиться что твой собственный код отвечает всем требованиям, других способов попросту не существует. Любой программист так и или иначе всегда делал отдельные маленькие проекты, в которых пробовал новые идеи. Ну так вот — место таким проектам — в тестах!
зачем выделять отдельный проект, когда достаточно сделать git checkout -b?
Может быть это имеет смысл чтобы разбить «кухню». На одной стороне продукт, который пишут разработчики. На другой стороне группа тестирования, которая не вникает в исходники проекта, не вклинивается в процессы разработки продукта, и эту группа параллельно разработке покрывает продукт приемочными тестами.

Maxik77, зачем в вашем случае понадобилось выносить тесты в отдельный проект?
Separation of concerns.
Без разницы кто пишет тесты. Место тестам — в отдельном проекте и отдельной области видимости
Место тестам — в отдельном проекте


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

Как именно деплоится только то, что нужно для продакшена? Скриптовый язык какой-то?
Как раз рилиз диплой подразумевает, что там нет всех этих левых зависимостей, которые неизбежно тянутся за тестами, да и самих тестов нет, которые неизбежно раздувают результирующий бинарник. К тому же тесты могут обладать сайд-эффектами, т.е. код работает только в присутствии тестов, что является очень неприятной фичей.
На CI деплоится весь солюшен, который с нуля собирается и прогоняются тесты. Потом собирается инсталлятор, пекеджи и т.д.
Именно так всё работает во всех C/C++/C# проектах, в которых я участвовал.
В скриптовых языках возможно это и не так актуально, так как зависимости все грузятся на этапе пре-компиляции или вообще в рантайме.
Скажу за приложения на JavaScript.

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

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

В JavaScript приложениях мы можем держать всё в одном проекте, и не смешивать одно в другое.
Я понимаю, что для скриптовых языков — это не так актуально. В языках же где на выходе — бинарник, это большое NO NO.
В модулях на джаваскрипте что я видел — тесты вынесены в отдельную директорию, и релиз на выходе в поддиректории dist. Никакой особой проблемы с этим не вижу, просто особенность инструментария и языка.
Вот что я реально видел — это тесты положены в ту же папку, что и сорс файл, только у него суффикс _test.java, они даже в одном пространстве имён находятся и потом собираются в один .jar. Вот это реально бред, так делать нельзя
В том же джаваскрипте это (тесты в одной папке с продакшен кодом и ресурсами) тоже имеющая место быть практика, имеющая вполне логичное объяснение: изоляция модуля/компонента от остального кода, всё что касается этого модуля/компонента лежит в одной папке и может быть легко скопировано в другой проект или выделено в отдельную библиотеку/фреймворк. Насчёт одного бинарника именно в джаве не скажу, мало с ней знаком, но на си/плюсах есть практика генерировать два бинарника — собственно продакшен-реди код и тестовый бинарник, который динамически линкуется с первым, используя его как библиотеку. Как вариант — вынос подавляющего большинства продакшен кода в библиотеку, оставляя в непосредственно исполняемом бинарнике по сути лишь «main», и создание второго исполняемого бинарника, у которого main принадлежит тестовому фреймворку.
Статья ни о чем. Много воды смысла нуль. Автоматизированное тестирование и TDD тоже надо применять с умом. Почему вы не раскрываете деталей и условий когда это хорошо и когда плохо?
Разрабатывать по TDD? Иди поучи свою жену щи варить. Что нам говорит TDD, сначала пишем тест. Он не проходит. Имплементируем функционал — проходит. Такой подход иррационален. Зрелый продукт внутри представляет собой иерархическую структуру с компонентами и слоями, которые в свою очередь тоже покрыты тестами. TDD двойное покрытие. Учитывая что бизнес логика меняется, то со временем придется еще поддерживать и тесты.
Как на мой взгляд должно производиться тестирование. Чем важнее и «базовее» компонент, тем лучше он должен быть покрыт тестами. TDD хорошо подходит для некоторых фич фреймворков.
Интеграционное тестирование хорошо подходит для критических вещей всего продукта.

Автоматизацию надо начинать с рутинных или приемочных тестов, без которых продукт выпускать смысла нет. В идеале можно использовать DSL подход, и прямо в требовании писать сценарий на DSL для тестирования.
Например проводник винды: select menu «File», submenu «New». Keyboard «My Folder». Check: Explorer.FolderExists("%PATH%\My Folder").
Например у нас в приложении есть большое количество независимых окон, автоматизировали сценарий открытия окна, пока кодом, следующий шаг выделить DSL и дать возможность тестерам писать DSL.
Зрелый продукт внутри представляет собой иерархическую структуру с компонентами и слоями, которые в свою очередь тоже покрыты тестами. TDD двойное покрытие.


TDD предполагает юнит-тестирование каждого компонента и слоя изолированно, без двойного покрытия.
Sign up to leave a comment.

Articles

Change theme settings