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

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

Если вы покажете своим разработчикам полезность и целесообразность тестирования как основного способа разработки, а не просто как одной из частей процесса разработки, то все вопросы про барское дело отпадут само собой.
Спасибо, добавил примечание в начале статьи. Идея применить TDD к автотестам давно витает в воздухе, но пока не очень понятно, как её реализовать на практике..
Есть подходы BDD и Speс by Example. Есть Cucumber и подобные фреймворки, с помощью которых можно описывать требования (в виде фич и сценариев) и автоматизировать прогон тестов по этим требованиям.
На своей практике сталкивался даже с DSL для приемочных тестов на ruby. Это очень упрощало жизнь нашей QA команде, т.к. предметно-ориентированный язык скрывал все сложности загрузки данных, вызова функций проекта и проверки результатов.

В нынешнем проекте мы все-таки перешли от велосипедов в функциональном тестировании, к более стандартным вещам. Gherkin подобный язык есть не только в Cucumber, но и в Jbehave. А jbehave субьективно удобнее, если если проект написан на java.

Но еще интереснее дело обстоит с нефункциональными приемочными тестами. В этом случае для проверки NFR применяются кластерные фрейморки и jmeter, отдельная деплоймент инфраструктура и т.п.

В случае интеграционных проектов отличные средства для тестирования есть в apache camel
Правильные вещи говорите, жаль заказчики не оценят всех этих трудов и не заложат на это денежек.
Если тесты увеличивают стоимость разработки, а не уменьшают, то нафиг нужны такие тесты.
Ну дешёвое ПО с багами оно конечно круче ;)
Дело в том, что заказчику не нужно объяснять про тесты. Решение должно приниматься внутри команды: хотим ли мы разрабатывать говнософт, или не хотим.

Чтобы не проиграть конкурентам, нужно доводить заказчику бюджеты: или 1) делаем (как «те дешёвые» парни) быстро, недорого без закладывания на будущее развитие, 20 млн. запуск и по 10 млн. существенные изменения логики. или 2) играем в долгую, делаем тщательно, 40 млн. запуск и по 5 млн. на изменение. Заказчик может сознательно выбрать первый вариант, он лучше знает свои планы. Может, он хочет быстро запуститься на прототипе, а потом вообще перейти на коробочную энтерпрайз-систему, а эту выбросить.
Увы обычно бывает так — заказчик говорит " я хочу быстро за 20 ". Все делается быстро как заказчик и просил. А потом — " я теперь я хочу чтобы вы это дородотали чтобы изменения были по 5 млн " и это хорошо если проект как-то грамотно спроектирован, но обычно это не так ибо заказчик четко деклариловал что ему нужно «быстро». Они какбы могут отказываться понимать и брать ответственность за какой-либо выбор :)
Именно это я и имел ввиду. Есть знаменитая картинка, на которую заказчики обычно почему-то не обращают внимания
Частый случай: делайте побыстрее, потом отрефакторите. Потом в этом говнокоде копаться никому не интересно, а на переразработку с нуля заказчик не согласен. Что-ж, заказчику придётся всю жизнь пользоваться плохим продуктом. Защита только одна — ставить ценник выше и делать хорошо.
Автотесты, приёмочные тесты, функциональные тесты (синонимы) — это всё не «метод улучшить ПО», а метод хоть как-то сдержать разваливающийся проект под наплывом большого числа разработчиков.

Если проект может жить и развиваться без таких тестов — ок. Если нет — надо делать. Громоздить их до того, как «припекло» экономически нерентабельно, ибо написание хотя бы небольшого репрезентативного комплекта тестов сложнее, чем написание самого ПО. То есть это как с «преднапряжённым бетоном» в строительстве. Если ты можешь построить без его участия — не надо его использовать. Если уж не можешь никак иначе — тогда, да.
Имхо есть простые end-to-end тесты, которые могут помочь контроллировать целостность приложения. Они не так сложны в написании и поддержке, но разные простые вещи типа «изменили формат X но забыли поменать его разбор в Y» могут проверить.
Большой Вам плюс. Есть классический треугольник тестирования image т.е, основа тестов должны быть unit tests, они самые дешевые и быстрее всего дают обратную связь; потом integration tests с иммитацией частей системы, они дороже, чаще падают от «вуду» проблем, но все еще достаточно дешевы чтобы часто использоваться; ну и наконец идут end to end тесты, которых должен быть самый минимум, проще говоря — они должны проверять, что система работает и можно делать самые базовые операции. Почему e2e тестов должно быть минимум? Потому что их ОЧЕНЬ дорого писать и они, по своей натуре, не стабильны (зависимость от внешних API, реальные денежные транзакции, ошибки распознования в таких иструментах как Selenium: все эти маленькие вероятности падений банально перемножаются). Грубо говоря, чем выше мы поднимаемся в этой иерархии, тем меньше конечное соотношение «цена к ценности».
Предположу, что очень дорого писать первый тест и поддерживать инфраструктуру е2е тестов (отлавливать гейзен баги, разбираться, почему падают тесты).

Сейчас работаю над соц. сетью написанной на скале, есть 500 селениум тестов, которые кроют всю функциональность ui (весьма сложную, написанную на ангуляре). Сбоев нет (были, но разобрались почему и исправили инфраструктуру).
Как долго писать тест на селениуме у нас? Примерно за время написания двух-трех юнит-тестов.

Но мы кроем всю функциональность юнит-тестами. Для меня это нецелесообразно и затрудняет рефакторинг, потому что все основные юз кейсы кроют селениум тесты.
В своих проектах у меня есть только селениум тесты и интеграционные тесты апи за исключением border-cases. Например, надо проверить, что в апи, который выдает список сущностей параметр count не должен превышать 100 элементов, если пришло больше — юзаем значение 100. Для таких случаев пишется юнит-тест.
Результат: фактически покрыто 100% юз кейсов, свобода рефакторинга, меньше времени тратится на разработку (в том числе за счет написания малого количества тестов).
А в нашем проекте есть 3 сторонних API, плюс наш REST API который (скорее всего) будут использовать в догонку к UI. Поэтому шанс на поломку очень сильно возрастает. Плюс, из за любви к e2e тестам, в них так же проверяются всякие исключительные ситуации, что приводит к частым падениям и 2 часа полного прогона. Но мы папуасы и не пользовались Селениумом.
Но, за юнит тесты замолвлю слово. Юнит тесты объясняют как должен работать код. Написание юнит тестов приводит к лучшему пониманию что надо писать. И в юнит тестах очень дешево проверять потенциально скользкие ситуации (моким эксепшн, оттуда уже пляшем). К тому же, еще один огромный плюс юнит тестов — их (если писать правильно) можно запускать паралельно и моментально получать фидбэк (славься TeamCity pre-commit build), в отличии от e2e, где тесты привязаны к определенной среде.
Написание юнит тестов приводит к лучшему пониманию что надо писать

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

Юнит тесты объясняют как должен работать код

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

Конечно, если в команде 3 человека. А если 10 и многие из них новички + недавно с конкретным стаком технологий познакомились + они смертные, то увы. Много фич в узкие дедлайны приводят к говнокоду, а если дедлайн требует юнит тестов, то можно выторговать заодно пару часов на рефакторинг. Тем более что легче рефакторить, когда уже есть готовые тесты.

К тому же, если мудрить с самого начала с сложностью кода, есть шанс не угадать все (увы, мы не можем держать в голове все). Поэтому и есть TDD: пишем тест, пишем говнокод который его проходит, рефакторим говнокод — ведь уже есть тесты.

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

Граница между сложными и простыми вещами очень размыта. Плюс требования меняются и модуль, который вчера был простым, уже сегодня стал с заковыркой.
Проблема юнит-тестов в основании пирамиды: их много.
Хотя они и дешёвые, но всё равно имеют цену, надо поддерживать. При рефакторинге, изменении требований.
Один интеграционный тест заменит два десятка unit.
Многое зависит от организации работы. Если выполняются штучные заказы, т.е. за небольшие деньги и нет возможности повторно использовать код, то тесты будут экономически не целесообразны (долго и дорого). Один черт заказчик примет и будет «ездить» на том что сделано. Если идет разработка продукта для широкого круга пользователей с большим временем жизни и желанием дожить до третьего релиза без переписывания всего, то тесты будут выгоднее, чем в предыдущем случае.
Продуктовые разработчики звучат странно. Как продуктовые магазины.
Никогда не удавалось увидеть в проекте трудоемкость тестов в 10-20% от всей стори. Если бы это было так, никто бы никогда не спорил об их целесообразности, а просто делали бы и не парились. Мои субъективные наблюдения скорее приближают эту цифру ближе к 50% — половина код и половина тесты. Что не делает их менее важными.
У нас сейчас автотесты выглядят следующим образом: по коду продукта расставлены метки, которые генерируют специальные события для тестов. Тесты в этом случае представляют собой довольно простой скрипт, который анализирует корректность произошедших событий. В тесте формализуется ожидаемый «шаблон» событий (в простейшем случае — это просто линейная последовательность), и в случае расхождения с этим шаблоном, тест краснеет. Благодаря этому тесты дешевы в разработке и пригодны для legacy кода. Но это стало возможным только благодаря тому, что программисты могут модифицировать код и добавлять в него генерацию событий. Но это тема для отдельной статьи.
очень интересная тема, очень ждем статей :)
Самое интересно — как устроен запуск тестов.
Сложно ведь не проверить ассерты, а изолировать отдельные функции приложения, чтобы они могли выполняться независимо и без вмешательства оператора.
Хороший вопрос, это тоже будет описано в другой статье. Если коротко, то тесты делятся на два класса:
1) Интеграционные. Это трудоёмкие медленные тесты, но их очень мало. Они проверяют, что продукт может корректно общаться с внешним миром. Эти тесты не проверяют, что продукт реализует конкретный пункт ТЗ, они проверяют, например, что если продукт зачем-то захочет отправить email, то он сможет в принципе это сделать и письмо действительно будет отослано куда надо с корректной темой, телом и т.д.
2) Функциональные. Это уже тесты по ТЗ, их много, они дешевы, работают быстро, но они не совсем «честные». Тест с помощью специального тестового фасада инициирует некоторую операцию и, например, проверяет, что от продукта пришло событие, что он захотел отправить email с правильной темой, телом и получателем согласно ТЗ. При этом то, что письмо реально отправилось уже не проверяется. При этом тестовый фасад может опубликовать любой участок кода продукта, находящийся на любом уровне абстракции.
Ваши определения отличаются от общепринятых, насколько я понимаю. Принято называть интеграционными тестами быстрые тесты, в которых работает в сборе много кода, но другие части мокаются, а функциональными — честный полный запуск Application Under Test
Согласен, но общепринятых терминов для классификации функциональных тестов я не встречал, поэтому приходится выкручиваться. Если подскажете, буду благодарен.
Интересный вопрос. Я только что понял, что просто поменять местами определения у вас не получится =) Не назовешь тесты на отправку email функциональными никак.
Для какого-нибудь стандартного enterprise (возьми отсюда, запиши сюда) это так.

Но если появляется изолированный кусочек со сколь либо сложной логикой, удобно запускать его через тесты. Всё равно программист будет дебажить свеженаписайнный код, и классически получается долго — запускать весь продукт (логиниться), доходить до места, вызывающего новый код, убеждаться, что в коде банальная опечатка, останавливать проект, исправлять, запускать заново, снова докликивать до нужного места. С тестом сразу попадаешь на отладку нового кода.
Для сложной логики есть юниттесты, мы ж не про них говорим сча.
Я думал про них, из исходного комментария непонятно.
Ну а так, да — только юнит-тесты могут ускорить фазу кодирования, остальные пишутся под готовый и уже отлаженный код.
В свое время был очень успешный опыт разработки проекта так: QA писали сценарии на Gherkin, а девелоперы их имплементили вместе с имплементацией фичи. Работало просто отлично. Команда из 15 девелоперов и 4 QA, деплоили проект на прод два раза в неделю. На подготовку релиза у команды QA уходило 2 часа (на ручное тестирование не покрытого автотестами функционала).
Очень правильная мысль: автотесты дело команды, а не заказчика. Точно так же как и стек технологий, фреймворк, воркфлоу и время митингов.

То есть, если уважающий себя разработчик пишет юнит-тесты на свой код, то уважающая себя команда пишет автотесты… либо просто не занимается проектом, если заказчик не может позволить себе эту команду.
Уважающая себя команда помогает бизнесу клиента, а не делает то, что ей нравится делать.
Может и о десятиминутных стендапах, ревью кода заказчика спрашивать — можно или нет их проводить? Ведь это трата времени не на реализацию фич, а на то, чтобы поболтать! Какая тут помощь бизнесу, прохлаждаться хотят…
«помогает бизнесу клиента» != «клиент одобряет»
Клиент приходит с проблемой, девелопер предлагает решение. Если эта проблема решается лучше без автотестов, но девелопер «уважает себя» и не хочет ее делать без автотестов, то это плохой девелопер. Не понимаю, откуда взялось «спрашивать у клиента».
Потом этот хороший девелопер сдаёт проект, в котором не то что тестов — классов нет, всё написано одним сплошным полотном. Имена переменных a, b, c, n1, n2, x, чтобы быстрее набирать. И говорит: «насяльника, я зе старался сделать тебе подешевле».
Почему когда начинаешь говорить про эффективность, сразу все передергивают, будто бы ты говорил про дешевизну независимо от качества?
Если проект небольшой, то 3-4 написанных теста погоды не сделают, но могут поднять мотивацию разработчика, если он любит писать тесты.
Если тестов написано 100500, а проект небольшой, то навряд ли такой проект получит одобрение в проф. среде у коллег, поэтому делать заведомо глупые вещи никто не будет для «улучшения уважения».
Если проект большой, то нужны тесты или нет, разработчик заранее не знает (и клиент ему не скажет). Поэтому нельзя предвидеть, как выгоднее бизнесу — писать или не писать.
Все эти best practices не на пустом месте родились. И для каждого правила есть исключение.
Поэтому даже для простых проектов надо брать по-дефолту ревью, юнит тесты, и т.д. А потом стараться понять, что можно соптимизировать и нужно ли?

Фраза «помогать бизнесу клиента» для меня означает только одно — спрашивать у него самого, что ему поможет или нет. Потому что только клиент знает, что поможет, а что нет его бизнесу. Если только бизнес не в айти, а программист — консультант.
Вот именно! Проблема в том, что «бизнес» не эксперт, и на предложение построить фундамент под домом ответит вяло — давайте потом, сейчас на это времени нет.

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

Публикации