Единицы
1. Введение в искусственный интеллект в тестировании программного обеспечения и обеспечении качества: роли, границы, риск подделки и проверка 2. Генерация тестовых сценариев и тест-кейсов: от требования к комплексному контролю 3. Исследовательское тестирование и генерация тестовых идей: творческий поиск ошибок с помощью ИИ 4. Автоматизация тестирования пользовательского интерфейса: генерация кода Selenium, Playwright и Cypress с помощью ИИ 5. Автоматизация тестирования API: контракт, схема и сквозная проверка с помощью ИИ 6. Генерация и тестируемость модульных тестов: надежное тестирование с помощью ИИ 7. Написание отчетов об ошибках и определение приоритетов: четкие, воспроизводимые записи с помощью ИИ 8. Анализ тестового покрытия и тестирование на основе рисков: правильный подход с помощью ИИ 9. Регрессионное тестирование, сопровождение тестов и борьба с хрупкими тестами 10. Риск ложного доверия, качество тестов и тестирование мутаций: тестовые тесты 11. Сквозной рабочий процесс, интеграция CI/CD, этика и безопасность: ответственное использование ИИ
Единица 6 / 11

Генерация и тестируемость модульных тестов: надежное тестирование с помощью ИИ

Прибыль:

  • Возможность предотвратить принятие искусственным интеллектом ошибочного поведения как «правильного» путем расчета ожидаемого значения в модульных тестах независимо от правила приемки.
  • Возможность распечатывать быстрые, независимые и повторяемые тесты, применяя принципы AAA и FIRST и имитируя внешние зависимости.
  • Умение тестировать тесты с мутациями (взломом кода) и распознавать трудный для тестирования код как запах дизайна.

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

Качества хорошего модульного теста: ПЕРВОЕ

Хорошие модульные тесты следуют принципам FIRST: быстро, независимо (тесты не должны зависеть друг от друга), повторяемость (повторяемость — одинаковый результат в любой среде), самопроверка (однозначное прохождение/неудачность), своевременность (вовремя). Напоминайте себе об этих принципах, когда ИИ проводит тесты; конкретно попросите, чтобы тест не зависел от внешнего мира (реальной базы данных, сети, часов) и был «независимым» и «повторяемым».

Шаблон AAA и выразительное утверждение

Надежный модульный тест следует структуре AAA: Arrange (подготовка — настройка входных данных и зависимостей), Act (выполнение — вызов тестируемой функции), Assert (проверка — сравнение результата с ожидаемым значением). Критическим является утверждение. Самая распространенная ошибка, которую допускает ИИ, — это получение утверждения из выходных данных тестируемого кода — логика «все, что возвращает код, истинно». Это делает тест бессмысленным. Правильный путь – определить ожидаемое значение самостоятельно (из критериев приемки рассчитать его вручную).

Внимание: если вы скажете ИИ «написать тест для этой функции», ИИ может запустить функцию и записать ее вывод как «ожидаемый». Этот тест проходит, даже если функция ложна. Вместо этого скажите: «Вы рассчитываете ожидаемые результаты в соответствии с этими правилами, не ссылайтесь на текущий вывод функции».

Моки, заглушки и зависимости

Модульное тестирование требует изоляции. Если ваша функция зависит от базы данных или API, при тестировании они заменяются фиктивными объектами (макет/заглушка — контролируемая фиктивная замена реальной зависимости). Это делает тест быстрым, независимым и воспроизводимым. ИИ может создать макет установки; Но остерегайтесь чрезмерного издевательства: если вы издеваетесь над всем, тест будет проверять только «то, что возвращает макет», а не реальную логику. Баланс: эмулируйте внешний мир, выполняйте реальную тестируемую логику.

Тестируемость и ИИ

Есть интересный отзыв: код, который сложно тестировать, зачастую плохо спроектирован. Если у ИИ проблемы с написанием тестов для функции (слишком много зависимостей, скрытое глобальное состояние, побочные эффекты), это запах дизайна. Если задать ИИ вопрос «как бы вы провели рефакторинг этого кода, чтобы сделать его тестируемым», это приведет как к лучшему тестированию, так и к более качественному коду.

Параметризованные тесты и разнообразие данных

Написание отдельного теста каждый раз для проверки одного и того же правила с разными входными данными утомительно и сложно в обслуживании. Параметризованное тестирование — структура, которая многократно запускает одну и ту же логику тестирования для списка входных данных и ожидаемых результатов — исключает это повторение: в одно тело теста подаются десятки пар входных данных. ИИ очень эффективен в создании таблиц ожидаемых результатов, когда вы даете ему свои правила приемки; В частности, систематически сводятся в таблицы предельные значения и классы эквивалентности.

Но и здесь есть ловушка: ИИ стремится получить ожидаемые результаты в сгенерированной таблице из тестируемого кода. Эта ошибка еще более опасна при параметризованном тестировании, поскольку одна неправильная логика делает недействительными десятки строк. Поэтому всегда рассчитывайте столбец ожидаемого результата независимо в соответствии с правилом приемки и вручную проверяйте хотя бы несколько строк. Также попросите столбец описания «что представляет каждая строка»; поэтому, когда строка разрывается, вы сразу видите, какое состояние нарушено.

Совет: Намеренно добавьте «строку ловушки» в параметризованную тестовую таблицу, то есть заведомо опечатайте результат. Если эта линия не становится красной при запуске теста, ваш тест на самом деле не проверяет эту ситуацию. Это быстрая пробная проверка.

Слабая подсказка / Сильная подсказка

Слабое: «Напишите модульный тест для этой функции».
Сильное: Напишите [язык/фреймворк] модульные тесты для функции "taxCalculate(amount,rate). Правило приемки: результат = сумма * ставка, округленная до 2 десятичных знаков; отрицательная сумма или ставка выдает ошибку; возвращает 0, если ставка равна 0. Используйте структуру AAA. Вычисляйте ожидаемые значения вручную в соответствии с ЭТИМИ правилами; не ссылайтесь на текущий вывод функции. Охватывайте ограниченные и отрицательные случаи (0, отрицательный, очень большой, округление до десятичных знаков). Пусть имя каждого теста опишите правило, которое он проверяет. Внешняя зависимость «Нет».

Мощная подсказка; Он дает правило приемки, независимое ожидание ожидаемой стоимости, структуру и крайние случаи. Таким образом, тест становится хранителем правил, а не зеркалом кода.

Таблица качества модульного теста

симптом

Плохой тест (ложное доверие)

хороший тест

утверждать

Нет или «не ноль»

Ожидаемая конкретная стоимость

Источник ожидаемой стоимости

Вывод функции

Правило приемки/расчет вручную

зависимость

Фактический БД/сеть/час

Изолирован с помощью макета/заглушки

крайний случай

Только счастливая дорога

предел, отрицательный, ошибка

Когда ты нарушаешь код

остается зеленым

становится красным

Имя

тест1, тестМетод

описывает правило, которое оно подтверждает

Четыре копируемых шаблона

1) Модульное тестирование на основе правил:

Ваша роль: старший инженер по тестированию программного обеспечения. Напишите модульный тест для следующей функции с помощью [язык/фреймворк]: [подпись]. Правила приемки: [правила].- Используйте структуру AAA.- Вручную рассчитайте ожидаемые значения в соответствии с ЭТИМИ правилами; НЕ ссылайтесь на текущий выход функции. - Покройте предел, негатив, ошибку и счастливый путь отдельными тестами. - Пусть каждое имя теста описывает правило, которое он проверяет. - Имитировать внешние зависимости; Заставьте реальную логику работать.

2) Контроль устойчивости к мутациям:

Посмотрите эти модульные тесты. Перечислите 5 незначительных изменений, которые я мог бы внести в тестируемый код (a - вместо +, >= вместо >, сдвиг границы) и скажите мне для каждого, КАКОЙ из этих тестов станет красным? Если ничего не возвращается, тест недостаточен. Код + тесты: [вставить]

3) Проверка тестируемости:

Почему сложно написать модульный тест для этой функции? Скрытая зависимость, глобальный статус, побочные эффекты, много ли обязанностей? Предложите минимальный рефакторинг, чтобы сделать его тестируемым; не меняйте поведение. Код: [вставить]

4) Неполное завершение сценария:

Приведены следующие функции и доступные тесты. Перечислите, какое поведение/крайний случай НИКОГДА не тестировалось (пробел в объеме), и добавьте тест для каждого. Функция+тесты: [вставить]

три мини-кейса

Случай 1. Тестирование зеркального отображения кода. Разработчик поручил ИИ написать тест для функции округления; 10 тестов были зелеными. На самом деле функция округляла не в ту сторону, но ИИ взял из вывода функции ожидаемые значения, поэтому тесты посчитали ошибку «истинной». Когда ожидаемые значения были рассчитаны вручную с помощью «управляемого правилами» шаблона, 4 теста стали красными и выявилась реальная ошибка.

Случай 2 — Ценность контроля над мутациями. Одна команда полагалась на 45 модульных тестов. Пробовал 20 незначительных изменений в коде с помощью «проверки устойчивости к мутациям»; тесты поймали только 11 из них. Остальные 9 срывов прошли молча. Команда усилила слабые тесты; Эти расширенные тесты в следующем выпуске выявили фактическую ошибку расчета.

Случай 3. Непроверяемость — это запах дизайна. ИИ не мог писать тесты для функции заказа, ему постоянно требовалась реальная база данных. Шаблон «Проверка тестируемости» показал, что функция встроена в доступ к базе данных. Когда внедрение зависимостей было удалено, можно было писать тесты, и код стал чище.

Распространенные ошибки

  • Получение ожидаемого значения из кода. ИИ принимает вывод функции как «правильный»; тест, подтверждающий ошибочный код.
  • Тестируйте без утверждения или с тривиальным утверждением. «Он не выдал ошибку, он передал» логику; Это ничего не подтверждает.
  • Экстремальный издевательство. Издевательство над всем и тестирование только того, что возвращает макет; реальная логика не проверяется.
  • Просто счастливая дорога. Обход предельных, отрицательных и ошибочных состояний.
  • Не тестирование путем взлома кода. Доверять зеленому, не проверяя мутацию.
  • Игнорирование непроверяемости. Не распознавать и исправлять плохой дизайн вместо жесткого тестирования.

В заключение

Модульные тесты — это самый быстрый и самый большой уровень пирамиды тестирования; Он ловит ошибку в самый дешевый момент. ИИ очень способен создавать модульные тесты, но его самая большая ошибка — это написание тестов, которые предполагают неправильное поведение как «правильное», получая ожидаемое значение из самого кода. Решение: дать правила приемки, рассчитать ожидаемые значения вручную, обеспечить соблюдение принципов AAA и FIRST, имитировать внешний мир и запустить реальную логику, а также протестировать каждый тест путем мутации (взлома кода). Код, который сложно тестировать, — это признак дизайна, который требует исправления.

Задача приложения

Выберите функцию, содержащую бизнес-правило, из вашего собственного проекта. Напишите правила приемки и попросите ИИ написать тесты с шаблоном «модульное тестирование на основе правил»; Ожидаемые значения рассчитываются вручную. Затем примените «проверку устойчивости мутаций»: сделайте минимум 5 небольших перерывов в коде и замерьте, сколько тестов покраснело. Добавить новый тест на необнаруженные повреждения. Сообщите, сколько сбоев было обнаружено (например, оценка мутаций).

контрольный список

  • [ ] Я дал правила приемки, и ожидаемые значения были рассчитаны вручную.
  • [ ] Я убедился, что тесты не извлекают из кода ожидаемого значения.
  • [ ] Я организовал независимое тестирование в соответствии с рекомендациями AAA и FIRST.
  • [ ] Я высмеивал внешние зависимости и запускал реальную логику.
  • [ ] Я рассмотрел предельные, отрицательные и ошибочные случаи.
  • [ ] Взломом кода (мутацией) я доказал, что тесты действительно защищают.