Основы тестирования
Одно поле «пароль»: 8 знаков, каждый из 95 печатных символов клавиатуры. Я посчитал перебор - 6 634 204 312 890 625 вариантов. Даже если гнать тысячу проверок в секунду, это 210 369 лет на одно поле одной формы. Все базовые принципы тестирования растут из этой цифры.
Стержень: проверить всё нельзя даже теоретически, поэтому тестирование не доказывает отсутствие багов, а говорит, где риск и что смотреть первым.
// Формулировки: «можно ли доказать, что багов нет?», «чем верификация отличается от валидации?», «что такое парадокс пестицида?».
Арифметика невозможного
Считаем дальше. Форма оформления заказа: тип клиента (3 значения), способ оплаты (4), валюта (3), доставка (3), промокод (есть или нет). Перемножаем: 3 × 4 × 3 × 3 × 2 = 216 сочетаний. По три минуты на прогон - 10,8 часа ручной работы, чтобы один раз проверить одну скромную форму. А полей в реальном заказе больше.
Исчерпывающее тестирование - это прогнать все возможные сочетания входов, состояний и путей. Как видно из чисел, оно невозможно нигде, кроме учебных примеров. Значит, вопрос не «как протестировать всё», а «что из этих 216 брать первым».
// Ответ даёт риск: вероятность, что сломается, умноженная на цену поломки. Оплата картой сломается редко, но стоит денег и репутации - в начало списка. Промокод на 50 рублей у 1% клиентов - в конец. Это и называется риск-ориентированным тестированием, и это единственный честный способ жить с бесконечностью комбинаций.
- исчерпывающее тестирование
- прогон всех сочетаний входов и состояний; на практике недостижим
- риск
- вероятность поломки, умноженная на цену последствий
Зелёные тесты не значат, что багов нет
Я взял функцию расчёта цены на 7 строк и 4 теста к ней. Покрытие строк - доля строк кода, которые хоть раз выполнились во время тестов - вышло 100%: все 7 строк отработали. Потом я 7 раз ломал код по одной правке: сдвигал границу скидки (было «от 10 штук», стало «больше 10»), менял скидку с 10% на 9%, переворачивал условие про премиум.
Тесты, которые сверяют результат с ожидаемым, поймали 6 поломок из 7. Тесты, которые проверяют только «вызвалось и не упало», поймали 0 из 7 - при тех же 100% покрытия. Отсюда первое: покрытие говорит, что строка выполнилась, и ничего не говорит о том, проверили ли её результат.
// А та единственная поломка, что прошла мимо даже хорошего набора, сидела в проверке «если цена меньше нуля - обнулить». Я заменил «меньше» на «меньше или равно», и ни один тест этого не заметил: ни в одном не было цены ровно ноль. Вот в этом и суть принципа «тестирование показывает наличие дефектов, а не их отсутствие». Зелёный прогон - это «мои проверки прошли», а не «багов нет».
- покрытие строк
- доля строк кода, выполнившихся под тестами; о качестве проверок молчит
- наличие, не отсутствие
- тесты доказывают, что баг есть; что его нет - не доказывают
Раньше дешевле, а тесты выдыхаются
Вернись к той границе скидки. В требовании написано «скидка при заказе от 10 штук». Десять - это уже скидка или ещё нет? Пока никто не спросил, разработчик и тестировщик прочитают одинаково и, может быть, одинаково неправильно - тест подтвердит баг. Вопрос аналитику стоит 30 секунд в чате. Тот же вопрос после релиза - это правка кода, новая сборка, повторная проверка, разбор с поддержкой и деньги клиентов, посчитанные не в вашу пользу.
Отсюда shift-left («сдвиг влево»): тестирование начинается не после кода, а на требованиях, где дефект стоит дешевле всего. Заодно это отвечает на вопрос про верификацию и валидацию. Верификация - «правильно ли мы строим», сходится ли продукт со спецификацией, то есть с документом, где записано, как должно работать. Валидация - «то ли мы строим», нужно ли это живому пользователю. Продукт без единого бага, решающий не ту задачу, всё равно провал.
// И два наблюдения из практики. Скопление дефектов: баги живут кучно, основная масса - в малой части модулей (тот самый принцип Парето про «малая часть причин даёт основную часть эффекта»), так что история багов подсказывает, где копать. Парадокс пестицида: мой набор из 4 тестов ловит ровно те поломки, под которые написан, - как вредители привыкают к яду, код «привыкает» к старому регрессу. Набор пополняют, иначе он тихо превращается в ритуал.
- shift-left
- тестирование начинается на требованиях, а не после кода
- верификация / валидация
- строим по спецификации / строим то, что реально нужно
- парадокс пестицида
- старый набор тестов перестаёт находить новое
Как отвечать: «Можно ли тестированием доказать, что багов нет?»
Нет, и это не пессимизм, а арифметика. Чтобы доказать отсутствие багов, надо перебрать все входы и состояния. Возьмите одно поле пароля: 8 знаков из 95 печатных символов - это больше шести квадриллионов вариантов, при тысяче проверок в секунду перебор занял бы двести тысяч лет. Исчерпывающее тестирование невозможно, поэтому тестирование по своей природе показывает наличие дефектов, а не их отсутствие. Больше того, зелёный прогон не значит даже, что проверено то, что казалось проверенным: я как-то брал функцию со стопроцентным покрытием строк и ломал её по одной правке - часть поломок набор не заметил, потому что покрытие говорит лишь, что строка выполнилась, а не что её результат сверили. Поэтому я никогда не говорю «багов нет». Я говорю, что закрыл риски: вот что вероятнее всего ломается и дороже всего обходится, вот эти области проверены так-то, вот здесь осознанно не смотрел. Это честная информация для решения о релизе, а обещание «после тестирования багов нет» - красный флаг: так говорит человек, не знающий границ метода.
Почему это сильный ответ: принцип назван и подкреплён счётом (перебор одного поля - двести тысяч лет), добавлено, что покрытие не равно проверке, и цель переформулирована как закрытые риски плюс информация для решения.
На чём валят
- −Сказать «мы протестировали всё» - даже форма из 5 полей это 216 сочетаний и почти 11 часов ручного прогона.
- −Считать 100% покрытия доказательством качества: при слабых проверках такой набор поймал 0 поломок из 7.
- −Обещать «после релиза багов не будет» вместо «закрыты такие-то риски».
- −Гонять годами один и тот же набор тестов и не пополнять его - пестицид, новое проходит мимо.
- −Путать верификацию с валидацией: по спецификации сходится, а пользователю не нужно.
Проверьте себя
Пять вопросов из банка по этой подтеме. Всего их 15, остальные разбираются в тренажёре.
- Чем верификация отличается от валидации?A)Верификация — это ручное тестирование, а валидация — автоматизированноеB)Верификация — «делаем ли правильно» (спека); валидация — «то ли делаем» (нужда)C)Это синонимы: оба термина означают одну и ту же проверку соответствия требованиямD)Верификация выполняется после релиза, а валидация — до начала разработки продукта
показать ответ и разбор
+B)Верификация — «делаем ли правильно» (спека); валидация — «то ли делаем» (нужда)// разбор: Верификация проверяет, что продукт построен согласно спецификации и требованиям (правильно ли мы делаем) — сюда входят ревью, статический анализ, проверка соответствия ТЗ. Валидация проверяет, что построенный продукт вообще решает задачу пользователя и нужен ему (то ли мы делаем). Можно идеально выполнить спецификацию (верификация пройдена), но сделать не тот продукт (валидация провалена), если требования были неверны. Поэтому обе нужны: одна ловит отклонения от ТЗ, другая — ошибочность самого ТЗ.
- Как соотносятся QA, QC и тестирование?A)Это три полных синонима одного и того же: контроль качества выпускаемого программного продуктаB)QC отвечает за построение процессов, а QA — за ручную проверку готовой сборки перед релизомC)QA — процессы предупреждения дефектов; QC — проверка готового продукта; тестирование ⊂ QCD)Тестирование шире QA и QC и включает их обоих как свои частные подвиды деятельности
показать ответ и разбор
+C)QA — процессы предупреждения дефектов; QC — проверка готового продукта; тестирование ⊂ QC// разбор: Это вложенные, а не синонимичные понятия. QA (quality assurance) — про процесс: выстроить работу так, чтобы дефекты не возникали (стандарты, ревью, метрики, улучшение процессов) — предупреждение. QC (quality control) — про продукт: проверить уже сделанное на соответствие требованиям — обнаружение. Тестирование — конкретная активность внутри QC (прогон проверок). То есть QA ⊃ QC ⊃ тестирование. Путать их — типичная ошибка: «тестировщик» строго говоря занимается QC/тестированием, а QA-инженер влияет и на процесс.
- Верно ли, что тщательное тестирование доказывает отсутствие дефектов в продукте?A)Да, если покрыть тестами все строки кода, отсутствие дефектов обеспеченоB)Да, при достаточном числе тест-кейсов можно математически доказать полную корректность продуктаC)Да, зелёный прогон всех тестов формально означает, что в продукте не осталось ошибокD)Нет: тестирование показывает наличие дефектов, но не доказывает их отсутствие
показать ответ и разбор
+D)Нет: тестирование показывает наличие дефектов, но не доказывает их отсутствие// разбор: Принцип «тестирование демонстрирует наличие дефектов, а не их отсутствие». Даже если все тесты зелёные, это не гарантирует, что багов нет — лишь что найденные сценарии отработали. Исчерпывающе проверить все входы и пути невозможно (комбинаторный взрыв), поэтому всегда остаётся непокрытое пространство. Прохождение тестов снижает вероятность и риск дефектов, но не обнуляет их. Отсюда практический вывод: «все тесты прошли» — не то же самое, что «продукт без ошибок»; это аргумент против ложной уверенности от зелёного прогона.
- Что описывает принцип «скопления дефектов» (defect clustering)?A)Малое число модулей обычно содержит большинство дефектов — баги группируются неравномерноB)Дефекты распределены строго равномерно по всем модулям, поэтому тестировать нужно всё одинаковоC)Каждый исправленный дефект порождает ровно один новый в том же модуле продуктаD)Повторный прогон одних и тех же тестов со временем находит всё больше и больше новых дефектов
показать ответ и разбор
+A)Малое число модулей обычно содержит большинство дефектов — баги группируются неравномерно// разбор: Принцип defect clustering (проявление правила Парето): дефекты распределяются неравномерно — как правило, малая часть модулей даёт основную массу багов (сложная логика, спешка, частые правки, слабый автор). Практический вывод: тестирование стоит концентрировать там, где дефекты уже находили и где риск выше, а не размазывать усилия равномерно. Связанный нюанс — «парадокс пестицида»: если гонять одни и те же тесты по этим местам, они перестают ловить новое, поэтому наборы надо обновлять. Оба принципа управляют приоритизацией усилий.
- Чем статическое тестирование отличается от динамического?A)Статическое тестирование запускает программу без данных, а динамическое — с реальными даннымиB)Статическое проверяет артефакты без запуска кода; динамическое — прогоняет саму программуC)Статическое выполняется вручную, а динамическое — автоматизированными средствамиD)Статическое проверяет вёрстку интерфейса, а динамическое — серверную логику приложения
показать ответ и разбор
+B)Статическое проверяет артефакты без запуска кода; динамическое — прогоняет саму программу// разбор: Статическое тестирование анализирует продукт без его выполнения: ревью требований, спецификаций и кода, статический анализ (линтеры, сканеры). Оно ловит дефекты рано и дёшево — прямо в документе или коде, до того как они станут работающим багом. Динамическое тестирование запускает программу и проверяет её поведение на входных данных (то, что обычно и называют тестированием). Оба дополняют друг друга: статическое дешевле и ловит проблемы в требованиях/коде на ранней стадии, динамическое проверяет реальное поведение в рантайме, которое из документа не видно.
дальше
Теорию прочитали. Навык ставится повторением
В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.