Точные ожидаемые списки для всех входов заранее не заданы. Как применить метаморфное тестирование к этой функции?
def normalize_tags(tags):
return sorted(set(tag.strip().lower() for tag in tags))
Нужно проверять не только конкретный результат, а метаморфные свойства функции — отношения между результатами на связанном наборе входов. Для этой функции перестановка элементов не должна менять результат, а добавление дубликата после нормализации не должно его изменять.
Такой подход позволяет выявлять дефекты даже без заранее подготовленного эталонного ответа для каждого входа.
Метаморфное тестирование применяется для ситуаций, где вычислить правильный результат для каждого тестового входа сложно, дорого или невозможно. Исходная проблема — отсутствие доступного тестового оракула, то есть надёжного способа определить правильный ответ.
Вместо полного знания результата тестировщик использует известное отношение между несколькими запусками одной функции. Если отношение нарушено, поведение считается подозрительным.
Для произвольного списка тегов трудно вручную перечислить ожидаемый результат, особенно если входы генерируются автоматически. При этом у функции есть очевидные свойства: регистр, пробелы, порядок элементов и повторения должны обрабатываться определённым образом.
Если проверять только отдельные примеры, можно пропустить дефект, который проявляется на перестановках, дубликатах или комбинации пробелов и регистра. Наличие одного корректного результата ещё не подтверждает сохранение этих свойств на связанных входах.
Сначала формулируются метаморфные отношения:
Например, для входа [' Dev ', 'QA'] можно сравнить результат с результатом для ['QA', 'dev']. Также можно добавить ' dev ' и ожидать тот же нормализованный набор.
Тесты проверяют связь между результатами, а не только конкретное значение. Например, ошибка, из-за которой функция не удаляет дубликаты, нарушит второе отношение; ошибка, зависящая от порядка входных данных, нарушит первое.
Метаморфное тестирование не заменяет обычные проверки известных примеров. Его ограничение в том, что выбранное свойство может быть сформулировано неверно или оказаться слишком слабым: тест может подтвердить согласованность результатов, но не доказать их соответствие бизнес-требованиям.
Команда тестирует обработчик поисковых запросов, который возвращает ранжированный список результатов. Полный эталонный список для каждого запроса построить трудно: он зависит от большого индекса и часто меняется.
Рассматривались два варианта. Ручное поддержание ожидаемых списков даёт понятные проверки, но дорого в сопровождении и быстро устаревает. Случайное сравнение ответов разных версий сервиса дешевле, однако само по себе не показывает, какой ответ правильный.
Было выбрано метаморфное тестирование: изменение регистра запроса не должно менять результаты для регистронезависимого поиска, добавление стоп-слова не должно менять выдачу, если оно игнорируется правилами поиска, а повторное выполнение запроса должно сохранять заданные инварианты. Такой набор обнаружил ошибку в нормализации запроса без необходимости хранить эталон для каждого возможного текста.
1. Чем метаморфное тестирование отличается от проверки ожидаемого результата?
При обычной проверке тест содержит вход и конкретный ожидаемый ответ. При метаморфной проверке главным объектом контроля является отношение между несколькими ответами на связанными преобразованиями входа. Конкретные значения результатов могут быть неизвестны, но нарушение отношения всё равно указывает на дефект или ошибку в предположении о поведении.
2. Как отличить метаморфное свойство от случайного совпадения?
Свойство должно следовать из требования или из математической модели функции, а не просто наблюдаться на нескольких примерах. Для данной функции инвариантность к перестановке обоснована тем, что результат представляет множество отсортированных уникальных тегов. Если такое обоснование отсутствует, совпадение результатов нельзя считать надёжным критерием корректности.
3. Может ли прохождение метаморфных тестов доказать отсутствие дефектов?
Нет. Оно показывает, что проверенные отношения сохраняются на выбранных входах. Дефект может нарушать другое требование, например некорректно обрабатывать пустые строки или Unicode-пробелы, не нарушая проверенных инвариантов. Поэтому метаморфные свойства нужно сочетать с требованиями, позитивными и негативными тестами, а при необходимости — с проверками конкретных эталонных результатов.