Будучи консультантом по тестированию, я за годы работы прочитал массу статей по QA. Большинство из них — это в какой-то степени полезные, но часто случайные материалы, которые не всегда стоят времени. Но иногда я натыкался на удивительно хорошие, по моему мнению, статьи, которые действительно могут помочь улучшить навыки написания тестов. Я отобрал эти статьи и написал к ним аннотации. Половина из них относится непосредственно к JavaScript / Node.js, вторая половина охватывает общие концепции тестирования, которые применимы в любом языке.
Почему эти статьи показались мне выдающимися? Во-первых, они отлично написаны. Во-вторых, они посвящены «новому миру тестирования» — не общеизвестным «TDD-шным» вещам, а современным концепциям и инструментам.
Если у вас мало времени — ищите статьи, отмеченные тремя звездочками *** — это шедевры, которые ни в коем случае нельзя пропускать.
1. «Выборочное юнит-тестирование — плюсы и минусы»
Автор: Стив Сандерсон (Steve Sanderson)
9 мин (1850 слов), статья
Аннотация: Все мы хотя бы раз участвовали в оживленной дискуссии о «юнитах» и «интеграции». В этой статье автор выходит на более высокий уровень конкретики и рассуждает о том, КОГДА юнит-тесты хороши, рассмотрев затраты на написание этих тестов в различных сценариях. Многие относятся к своей стратегии тестирования как к статической модели — технике тестирования, к которой они прибегают всегда, независимо от контекста. «Всегда пишите юнит-тесты на функции», «Пишите в основном интеграционные тесты» — такие аргументы часто можно услышать. В данной статье, напротив, предлагается оценивать целесообразности юнит-тестов, исходя из затрат на модуль и выгод. В статье классифицируется несколько сценариев, в которых чистая ценность юнит-тестов высока или низка, например:
Если ваш код в принципе очевиден — то есть с первого взгляда понятно, что именно он делает, — то дополнительное проектирование и верификация приносят крайне минимальную пользу.
Автор также использует модель 2x2 для визуализации того, когда привлекательность юнит -тестов высока или низка:
Примечание, не относящееся к статье: лично я (Йони) всегда начинаю с компонентных тестов, охватывая сначала высокоуровневые детали пути пользователя (так называемый ромб тестирования). Затем, когда появляются функции, я добавляю юнит-тесты, основываясь на их чистой ценности. Эта статья помогла мне классифицировать и оценить преимущества юнит-тестов в различных сценариях.
2. «Тестирование деталей реализации» (пример на JavaScript)
Автор: Kent C Dodds (Kent C Dodds)
13 мин (2600 слов), статья
Аннотация: Автор на примере кода описывает неизбежную трагичность веры тестировщика, который делает ставку на детали реализации. Если не принимать во внимание усилия, затрачиваемые на тестирование такого количества деталей, то такой путь всегда заканчивается «ложноположительными» и «ложноотрицательными» результатами. Это ставит под сомнение надежность тестов. Статья иллюстрирует этот тезис на примере фронтенд-кода, но выводы из урока универсальны для любого вида тестирования.
«Есть две причины, почему важно избегать тестирования деталей реализации. Тесты, проверяющие детали реализации:
Могут сломаться при рефакторинге кода приложения. Ложноотрицательные результаты
Могут не сработать, когда вы ломаете код приложения. Ложноположительные результаты».
p.s. У этого автора есть еще одна замечательная статья о современной стратегии тестирования.
3. «Разумный способ тестирования микросервисов»
Автор: Синди Сридхаран
Время чтения: > 2 часов (10 500 слов с большим количеством ссылок), статья
Аннотация: Это целая библия по тестированию микросервисов и современного распределенного тестирования, упакованная в одну длинную увлекательную статью. Помню, когда я наткнулся на нее четыре года назад, я каждый день перед сном проводил час с улыбкой на лице, читая ее. Я внимательно переходил по каждой ссылке, делал паузу после каждого абзаца, чтобы подумать — передо мной открывался совершенно новый мир. Это было настолько увлекательно, что мне захотелось специализироваться в этой области. Спустя годы это стало основной часть моей работы, и я наслаждаюсь каждым моментом.
Эта статья начинается с объяснения, почему E2E и юнит-тесты не оправдывают ожиданий в распределенной среде. А также почему любого вида закодированных тестов будет недостаточно, а необходим богатый набор методик. В статье рассматривается ряд современных методов тестирования, незнакомых большинству разработчиков. Одна из ключевых частей книги посвящена тому, что должно быть канонической техникой тестирования у разработчиков: автор выступает за «большие юнит-тесты» (т.е. компонентные тесты), поскольку они обеспечивают баланс между удобством для разработчиков и реалистичностью.
Я придумал термин "step-up testing", общая идея которого заключается в том, чтобы тестировать на один уровень выше того, что обычно пропагандируется. Согласно этой модели, юнит-тесты будут больше походить на интеграционные (рассматривая ввод/вывод как часть тестируемого модуля в ограниченном контексте), интеграционное тестирование будет больше походить на тестирование в продакшене, а тестирование в продакшене будет больше походить на мониторинг и исследование. Реорганизованная тестовая пирамида (тестовая воронка) для распределенных систем будет выглядеть следующим образом:
Вне зависимости от того, с каким типом системы вы имеете дело, эта статья расширит ваш взгляд на тестирование и подарит множество новых идей.
4. «Как проводить юнит-тестирование с Node.js?» (примеры на JavaScript, для начинающих)
Автор: Райан Джонс (Ryan Jones)
16 мин (3000 слов), статья
Аннотация: это единственная статья из списка, подходящая новичкам в тестировании.
Это руководство я выбрал из множества других вариантов потому, что оно относительно полное и хорошо написано. В нем рассматриваются шаги, о которых новичку следует узнать в первую очередь: интерфейс программ для запуска тестов, CLI программы Test Runners, проверка утверждений и асинхронные тесты. Разумеется, этих знаний будет недостаточно для того, чтобы покрыть тестами реальное приложение, но они позволят благополучно перейти к следующему этапу. Мой личный совет: после прочтения этой статьи стоит перейти к изучению тестовых дублеров (моков).
5. «Фетиш юнит-тестов»
Автор: Мартин Сустрик
5 мин (1000 слов), статья
Аннотация: Статья начинается словами: «Я слышал, что в наши дни люди испытывают неконтролируемое желание писать юнит-тесты. Если вы один из них, потратьте несколько минут на изучение причин, по которым писать юнит-тесты НЕЛЬЗЯ». Несмотря на такое неоднозначное вступление, автор статьи не выступает против юнит-тестов как таковых, а скорее подчеркивает, когда и где юнит-тесты оказываются неэффективными. В этих случаях следует рассмотреть другие методы. Вот пример: Юнит-тесты по своей природе имеют более низкий ROI (return on investment, рентабельность вложений), и автор приводит звучную метафору: «Приступая к покраске дома, вы начинаете с самой большой кисти, а маленькую кисть оставляете на конец, чтобы разобраться с мелкими деталями». Начиная свою работу по QA с юнит-тестов, вы, по сути, пытаетесь расписать весь дом самой тонкой китайской кисточкой для каллиграфии...».
6. «Наличие моков — это признак плохого кода» (примеры на JavaScript)
Автор: Эрик Эллиотт
32 мин (6 300 слов), статья
Аннотация: Большинство статей из этого списка относятся скорее к «современной волне тестирования», здесь же представлено нечто более «классическое» и привлекательное для любителей TDD или просто тех, кому необходимо писать юнит-тесты. Эта статья о том, КАК уменьшить количество моков (тестовых дублеров) в тестах. Не только потому, что написание моков влечет за собой расход ресурсов, но и потому, что они намекают на то, что что-то может быть не так. Другими словами, написание моков не является однозначно неверным решением, но большое количество моков является признаком того, что код далек от идеала. Подумайте о модуле, который наследуется от многих других, или о модуле, который взаимодействует с множеством других модулей для выполнения своей работы — тестирование и изменение такой структуры является тяжелым бременем:
«Моки необходимы, когда стратегия декомпозиции терпит неудачу».
Автор рассматривает различные приемы проектирования более автономных модулей, такие как:
использование чистых функций, что поможет изолировать от остальной логики программы возможные побочные эффекты,
использование pub/sub,
изоляция ввода/вывода,
объединение модулей с помощью паттернов, таких как монадические композиции, и др.
В целом тон статьи сбалансирован. В некоторых частях она поощряет функциональное программирование и методы, далекие от мейнстрима, поэтому читайте эти несколько частей с долей скептицизма.
7. «Почему хорошие разработчики пишут плохие юнит-тесты»
Автор: Майкл Линч
11 мин (2,2000 слов)
Аннотация: Мне очень нравится эта статья. Автор наглядно показывает, как неожиданно иногда хорошие разработчики с прекрасными намерениями пишут плохие тесты:
Слишком часто разработчики ПО подходят к юнит-тестированию, руководствуясь одним и тем же ошибочным мышлением... Они механически применяют все «правила», которые они изучили за время написания продакшн кода, не проверяя, подходят ли они для тестов. В результате «строят небоскребы на пляже».
В статье на конкретных примерах кода показано, как ухудшается читаемость тестов при излишне сложном подходе, и как сохранить простоту. В одной из частей автор демонстрирует, как вдумчивое нарушение принципа DRY позволяет читателю оставаться внутри теста, сохраняя при этом поддерживаемость кода. Эта 11-минутная статья поможет значительно улучшить тесты, написанные разработчиками, которые склонны писать сложно. Если в вашей команде есть такой человек, вы теперь знаете, что делать.
8. «Обзор тестирования JavaScript в 2022 году»
Автор: Виталий Зайдман
37 мин (7 400 слов), статья
Аннотация: эта статья уникальна тем, что в ней не рассматривается одна тема, а проводится обзор инструментов тестирования JavaScript. Это позволяет существенно обогатить свой инструментарий для любой ситуации. Например, знание о том, что существуют расширения IDE, которые показывают информацию о покрытии прямо в коде, может помочь вам повысить уровень внедрения тестов в команде. Знание о том, что существуют надежные, бесплатные и опенсорсные средства определения визуальной регрессии, может вдохновить вас глубже погрузиться в эту тему, и это лишь несколько примеров.
«Мы рассмотрели наиболее актуальные стратегии и инструменты тестирования в сообществе веб-разработчиков и, надеемся, облегчили вам тестирование сайтов. В конечном счете, наилучшие решения в отношении архитектуры приложений сегодня принимаются путем понимания общих закономерностей, модных в активном сообществе разработчиков, и сочетания их с собственным опытом и особенностями приложений».
В статье рассматриваются такие категории, как библиотеки для проверки утверждений, системы выполнения тестов, средства покрытия кода, средства определения визуальной регрессии, E2E тест-сьюты и многое другое.
9. «Безопасный способ тестирования в продакшене»
Автор: Синди Сридхаран
54 мин (10 725 слов), статья
Аннотация: «Тестирование в продакшене» — это провокационный термин, который звучит как рискованный и безответственный подход к тестированию и противопоставляется предварительной проверке (еще один случай неудачной терминологии тестирования). На практике тестирование в продакшене не заменяет тестирования во время кодирования, а лишь добавляет дополнительный уровень уверенности за счет безопасного тестирования еще на трех этапах: деплой, релиз и пост-релиз. В этой обширной статье рассматриваются десятки методов. Некоторые из них необычны, например, traffic shadowing, tap compare. Но главное, она иллюстрирует всесторонний процесс тестирования, начиная с компьютера разработчика и заканчивая версией, работающей у пользователей в продакшене.
Я все больше убеждаюсь в том, что промежуточные среды как моки — в лучшем случае это бледная имитация подлинного продукта, а в худшем — предвзятость подтверждения (confirmation bias).
Это все равно лучше, чем ничего — но состояние «работает на промежуточной среде» лишь на один шаг лучше, чем «работает на моей машине».
10. «Please don't mock me» (выступление с JSConf) ***
Автор: Джастин Сёрлз
39 мин, выступление
Аннотация: Это фантастическое выступление Justin Searls на JSConf US 2018 посвящено ахиллесовой пяте тестирования: где именно писать моки. Дилемма о том, где заканчивается область тестирования, что нужно имитировать, а что нет — это, пожалуй, наиболее стратегические решения в тест-дизайне. Рассмотрим модуль A, который взаимодействует с модулем B. Если изолировать A с помощью имитации B, то A всегда пройдет тест, даже если интерфейс B изменился, а код A не изменился вслед за ним. Это делает тесты A очень стабильными, но... продакшн упадет через несколько часов. В своем выступлении Джастин говорит:
«Тест, который никогда не бывает красным, — это плохой тест, потому что он ни о чем не говорит. Создавайте тесты так, чтобы они могли завершиться ошибкой».
Также он рассуждает о многих других интересных и непростых вопросах, связанных с мокингом, с прекрасными визуальными эффектами и массой идей. Не пропустите это выступление.
Материал подготовлен для будущих студентов онлайн-курса "JavaScript QA Engineer". А всех заинтересованных тестировщиков приглашаем на открытые уроки: