Очень редко люди задумываются о том, чем отличаются качественные тесты от посредственных. Если тест отличный, то его попросту незаметно - он растворяется в процессе и про него вспоминают только в том случае, когда он ловит баг.
Мы работали над несколькими миллионами автоматизированных тестов (работа такая) и пришли к выводам, что есть 7 характеристик отлично написанных тестов:
Тест полностью автоматизирован (очевидно)
Тест повторяем: тест не ломается, если приложение не поменялось
Тест заканчивается валидацией
Тест достаточно стабилен, чтобы его использовать в CI/CD
Тест очень легко читать
Тест требует минимальной поддержки
Тест работает параллельно с другими тестами и не ломается
Давайте поясню, что имеется в виду.
Тест полностью автоматизирован
Иногда попадаются такие тесты, которые автоматизированы не полностью. Самые распространенные причины: либо это очень сложно (как в случае с медленными джобами), либо просто невозможно (как проверить, что касса таки открылась?). Мы не рассматриваем такие неполные тесты в этой статье.
Тест повторяем: тест не ломается, если приложение не поменялось
Это относится к основам генерации уникальных данных. Например, мы тестируем регистрацию. Очевидно, что если не генерировать уникальный емейл, то на продакшене такой тест, скорее всего, не будет работать.
Тест заканчивается валидацией
За исключением случаев, где нужно выполнить действия по зачистке данных и подобных действий, завершение валидацией является лучшей практикой. Это помогает убедиться, что последнее действие прошло успешно.
Тест достаточно стабилен, чтобы его использовать в CI/CD
Если тест регулярно ломается, то он недостаточно стабилен, чтобы использовать его в CI/CD. Так как практически любая компания пытается добиться CI или даже CD, то часто такой тест не просто бесполезен, но даже вреден, так как отнимает большое количество времени и все равно не может использоваться в CI автоматически.
Тест очень легко читать
Мы обычно не пишем тесты в одиночку. Часто это команда людей и нашим коллегам тоже приходится поддерживать наши тесты. Крайне важно, чтобы любой член команды мог разобраться в структуре теста, не тратя на это излишнее количество времени. Даже если мы пишем тесты в одиночку, иногда бывает очень тяжело понять, что тест делает и как, если он не написан специально для облегчения понимания.
Тест требует минимальной поддержки
Пункт очевидный, но не всегда соблюдаемый. Чем меньше мы тратим времени на поддержку, тем больше у нас времени на то, чтобы сделать что-то полезное, как, например, написать больше тестов.
Тест работает параллельно с другими тестами и не ломается
В какой-то момент, особенно для end-to-end тестов, мы сталкиваемся с тем, что прогон тестов занимает слишком много времени, это снижает скорость разработки и приводит к таким эффектам, как неоттестированный патч. На этом этапе мы обычно задумываемся о параллелизации, чтобы ускорить исполнение тестов. Если тесты были написаны так, что они могут быть запущены параллельно в любой последовательности и не пересекаться друг с другом, то это делает задачу параллельного исполнения просто задачей настройки инфраструктуры, а не задачей переписывания тестов.
Оригинально тут.
Комментарии (39)
AndreySinelnikov
06.01.2022 20:27Короче, изобрели F.I.R.S.T.?
artem_testr Автор
06.01.2022 22:49Ой, а ссылочку можете дать? Никогда про него не слышал.
Vadem
07.01.2022 03:39Это из книги "Чистый код" Роберта Мартина. Глава про юнит тесты.
F.I.R.S.T. - Fast, Independent, Repeatable, Self-validating, Timely.
artem_testr Автор
07.01.2022 04:58Тут я пишу в основном про end-to-end тесты, поэтому, мне кажется, немного другие критерии
Tellamonid
07.01.2022 20:14А, вы про end-to-end. Для них мы перед прогоном всей пачки тестов чистим базу. И обеспечиваем независимость тестов, чтобы они могли бежать в параллель. В нашем случае достаточно, чтобы каждый тест бежал за свою бизнес-дату. И, конечно, есть отдельный тест, который проверяет, что бизнес-даты у тестов не пересекаются.
souls_arch
07.01.2022 23:51Предусмотреть все масштабы содеянного не возможно в любых случаях, можно лишь отсечь частные, руководствуясь определенными масштабами. Пользуйтесь, хотя я думаю, это сказали задолго до меня. "Даже взмах крыла бабочки на одном конце атлантики может привести к тайфуну - на другом" (с)
ivanych
08.01.2022 00:08Пункты 2 и 4 это одно и то же.
Пункты 5 и 6 бессмысленны. Вернее, это просто констатация очевидного, подходящая для чего угодно, хоть для тестов, хоть для тестируемого.
Пункт 3 - о чём он вообще? Что это за тест, который не является валидацией? Тест - это по определению валидация.
Не хватает пункта "Тест должен быть говорящим - разработчик, заваливший тест, должен по выводу теста понять, что сломано, не привлекая автора теста для расшифровки".
Ommonick
08.01.2022 12:50Меня пункт "валидация" тоже смутил. Можно было написать "ассерты" - было бы понятней. А валидацию оставьте на проверку параметров в функциях например.
gecube
кстати, не очень очевидно. Во-первых, почему тест на продакшене? На продакшене тестов быть не должно вообще. Во-вторых, окей, давайте рассмотрим сценарий регистрации. Нам нужно нагенерировать пачку логинов (почт), которые мы будем пытаться регистрировать. Но если между прогонами тестов они будут меняться - тест может флапать (скажем, мы сгенерировали валидный логин или почту, но по какой-то причине тест на ней завалился, скажем, был какой-то спецсимвол). Как в этом случае грамотнее написать тесты? Все-таки генерировать некий рандомный набор входных данных, но в рамках определенных критериев? Или все-таки зафиксируем большое количество тест-кейсов и будем идти по ним? Ну, и не раскрыта тема негативных тестов. Т.е. если у нас некорректный имейл - мы тоже должны проверить, что регистрация не пройдет...
tzlom
Для регистрации вы делаете тесты которые проверяют ветки сценариев, т.е. зарегался, уже есть такой логин, плохой пароль итд. Для каждого сценария достаточно одного теста.
Далее есть правила валидации мейла, и их много, для них делается юнит тест тестирующий все правила. Таким образом юнит тест проверяет правила, а интеграционный проверяет что проверка была вызвана.
Генерация случайных логинов в этом случае скорее всего не нужна
nin-jin
Почему?
amedvedjev
тут очевидно зависит от того что тестим. скажем в банке на ПРОДе особо не потестишь.
nin-jin
Почему?
amedvedjev
Потому что не посоздаешь реальных пользователей и денег ниоткуда. Уже молчу о генерации платежей и карт.
nin-jin
Берёте реальных пользователей, деньги и в путь.
amedvedjev
Вы брали или вы фантазируете?
Я в 3 банках работал. Никто на проде реально не тестит автотестами.
nin-jin
А ещё недавно везде всё вручную тестировали.
amedvedjev
Вот вот. Руками. И только на личном счете.
Ommonick
Я работал в двух. В одном тестили на проде даже с переводами. В другом тестили read-only сценарии, но возможно будут и иные.
gecube
автотестами?
Ommonick
да. и следили за балансом, комиссий не было.
Tellamonid
Я помню как на DevOps-конференции ребята из Monzo-банка рассказывали, что когда, например, в три часа ночи нет транзакций, то непонятно, это потому, что их действительно нет, или потому, что система лежит.
И если в течение часа не было транзакций, то они сами делали транзакцию на один фунт между своими счетами или картами, и смотрели, отразится ли она в системе.
По их словам, в изначальной версии это был механический паровозик, который проезжал с карточкой мимо бесконтактного терминала по специальной кольцевой железной дороге.
gecube
Первое, что Вы абсолютно правильно обратили внимание на важность мониторинга. С этим я абсолютно полностью согласен. Причем мониторинг не только технических параметров, но и бизнесовых.
Во-вторых, касательно примера - он какой-то странный. Дело в том, что Банк сам по себе никогда не транзачит. Транзакция всегда является сущностью, которая санкционирована человеком, ну, либо какой-то автоматизированной системой. Но вот как раз тут можно опять же закрыться мониторингом. Смотрите. Человек работает с банк-клиентом - будь это мобильное приложение, или веб сайт Банка. А раз так, то транзакция - это всегда HTTP запрос. Мы их можем считать и смотреть, что в нашей АБСке столько же реальных транзакций, сколько было запросов. ОКей. В какой-то момент времени мы могли понять, что к нам клиенты не могут постучаться. Но это решается вторым слоем мониторинга - не знаю, тот же downdetector прекрасно ловит каскадные отказы. Та же история с интеграциями по API... В конце-концов можем внедрить в приложение модуль слежения типа Sentry...
Поэтому механический паровозик, хоть и звучит круто, и как продающая история для компании, но абсолютно лишний.
souls_arch
Знаете, что мне сказали крайний раз в втб24 и на горячей и в отделении? Они сказали, под сафари банк-клиент работает збс, им глубоко плевать что больше он ни под одним браузом много месяцев не запускается под https вовсе или работает с косяками и в ограниченном режиме в том же гуглохроме. Который они честно предупредили, что наклали на саппорт. Сказали юзайте мобайл апп. Которое тоже ужас как кривое. Хотя на айос уверен все мб ок. Скоты, ворочая миллиардами экономят на разрабах нанимая индусов подешевше и это инфа из первых рук. Теряют миллионы клиентов из-за этого только. Уважения такому бизнесу нет. Сбер не лучше. А уж многие банки поменьше..
gecube
Согласен, проблемы есть. И не только у ВТБ. Но то, что Вы рассказываете - и к юнит тестам, ни к интеграционным тестам отношения не имеет. Это вообще отдельный класс UI тестов со своими подходами. И, увы, что ВТБ со своми многомиллионными бюджетами на разработку не может это осилить. Зато эджайл, скрам и девопс.
К тому же, если продукт дерьмо, то от того, что он стал айти продуктом, он пахнуть не перестанет. Поэтому я полностью согласен, что сначала надо думать о клиенте, о его потребностях. Формировать правильные и корректные юзер стори, а потом уже качественно это все выражать в виде продуктов...
souls_arch
Система чаще лежит на местах и по вине железа. И до этого никому нет дела сутками. Так что это все пыль в глаза. Как доходит до дела и у клиента пинкомат сожрал карточку или сдох всем на клиента накласть, - видел не раз. Систему надо строить с отнешений к людям, к клиенту. Когда на коленях извинились и выплатили неустойку за косяк. А потом уже ищут виноватых. А не как у нас - клиент всегда не прав.
amedvedjev
Это все крайне скудный набор. А я упомянул как раз про сильные ограничения. Создания пользователей, выдача карт и т.д.
Поэтому и сказал что не разгонишься.
А перевод и лирика это конечно легко и на Проде. Но этого крайне мало и не проверяет важную бизнес логику.
Ommonick
Это был автосмок. Для остального есть регресс на stage контуре, который гораздо легче автоматизировать, больше возможностей.
GospodinKolhoznik
Работал в финансовом секторе и в России и в США. И там и тут прод системы тестами были обмазаны с головы до ног. И руководство постоянно давило на то, что надо добавит ещё и ещё всех возможных и невозможных проверок как на тестовые системы, так и на продакшн.
amedvedjev
Не знаю какие у вас требования но где я работал максимум анинимизированный прод клали на тест и уже на нем тестили.
Еще прокатывало создание счета без каких либо транзакций.
Все остальное боялись проверок.
Я говорю о больших скандинавских банках.
gecube
Регулятор не позволяет. Если речь про банки.
Я уж не говорю о том, что, например, решать фейковых пользователей плохая идея, разве что есть гарантия того, что у Вас есть свой почтовый сервер, который гарантированно пользователь никогда не задействует. Либо какой-то флажок "тестовый пользователь" вводить, но тогда это ещё одна возможность получить глюки на ровном месте
Deosis
Вы согласны, чтобы джун сделал тестовый перевод 100 тысяч с вашего счета на свой?
nin-jin
Да, если мне на следующий день вернут деньги вместе с 10% его зарплаты.
gecube
На всякий случай уточню, что речь не про А/Б или функционал, закрытый фиче-флагом. В Банках этим тоже активно пользуются... но это не те тесты, о которых речь в статье.
artem_testr Автор
Я просто постарался привести простой пример. Если честно то я ОЧЕНЬ редко видел на практике что люди стартуют тесты с чистой базой - обычно стейджинг и никто его никогда не чистит
Tellamonid
мы с базой только так и тестируем. Приводим нужные таблицы в изначальное состояние (fixture), делаем, что нужно, и проверяем конечное состояние.
Мы пишем на Джаве, поэтому обычно используем для наката датасета, и для проверки (assert'а), библиотеку dbUnit.
artem_testr Автор
@TellamonidУверяю Вас, Вы круты и мы это видем очень редко )
artem_testr Автор
Я не упоминал негативных тестов отдельно потому что и позитивные и негативные тесты должны удовлетворять этому же критерию IMHO