Данное программное обеспечение, где...
- Система состоит из нескольких подсистем
- Каждая подсистема состоит из нескольких компонентов
- Каждый компонент реализуется с использованием многих классов
... Мне нравится писать автоматические тесты каждой подсистемы или компонента.
Я не пишу тест для каждого внутреннего класса компонента (за исключением того, что каждый класс вносит вклад в общедоступную функциональность компонента и, следовательно, тестируется/тестируется извне через открытый API компонента).
Когда я реорганизую реализацию компонента (который я часто делаю, как часть добавления новых функций), поэтому мне не нужно изменять какие-либо существующие автоматические тесты: поскольку тесты зависят только от общедоступного API компонента и публичные API обычно расширяются, а не меняются.
Я думаю, что эта политика контрастирует с документом, например Рефакторинг тестового кода, в котором говорится, что...
- "... unit testing..."
- "... тестовый класс для каждого класса в системе..."
- "... код тестового кода/производственного кода... идеально подходит для приближения к соотношению 1:1..."
... все из которых, я полагаю, не согласен (или, по крайней мере, не практикую).
Мой вопрос: если вы не согласны с моей политикой, объясните, почему? В каких сценариях недостаточно эта степень тестирования?
Вкратце:
- Общедоступные интерфейсы тестируются (и повторно тестируются) и редко меняются (они добавляются, но редко изменяются)
- Внутренние API-интерфейсы скрыты за общедоступными API-интерфейсами и могут быть изменены без перезаписи тестовых примеров, которые проверяют публичные API-интерфейсы
Сноска: некоторые из моих "тестовых случаев" фактически реализованы как данные. Например, тестовые примеры для пользовательского интерфейса состоят из файлов данных, которые содержат различные пользовательские входы и соответствующие ожидаемые выходы системы. Тестирование системы означает наличие тестового кода, который считывает каждый файл данных, повторяет ввод в систему и утверждает, что он получает соответствующий ожидаемый результат.
Хотя мне редко приходится менять тестовый код (потому что публичные API обычно добавляются, а не меняются), я обнаружил, что иногда (например, два раза в неделю) мне нужно изменить некоторые существующие файлы данных. Это может произойти, когда я меняю выход системы на лучшее (то есть новые функции улучшают существующий вывод), что может привести к тому, что существующий тест "сбой" (поскольку тестовый код только пытается утверждать, что выход не изменился). Для обработки этих случаев я делаю следующее:
- Перезапустите автоматизированный набор тестов, в котором используется специальный флаг времени выполнения, который говорит ему не утверждать вывод, а вместо этого записывать новый вывод в новый каталог
- Используйте средство визуального разграничения, чтобы увидеть, какие файлы выходных данных (например, какие тестовые примеры) были изменены, и чтобы убедиться, что эти изменения являются хорошими и ожидаемыми с учетом новой функциональности
- Обновите существующие тесты, скопировав новые выходные файлы из нового каталога в каталог, из которого выполняются тестовые примеры (переписывание старых тестов)
Сноска: по "компоненту" я имею в виду что-то вроде "одной DLL" или "одной сборки"... что-то достаточно большое, чтобы быть видимым на архитектуре или диаграмме развертывания системы, часто реализуемой с использованием десятков или 100 классы и публичный API, который состоит только из 1 или нескольких интерфейсов... что-то, что может быть назначено одной команде разработчиков (где другой компонент назначен другой команде), и, следовательно, согласно Закон Конвей, имеющий относительно стабильный публичный API.
Сноска: статья объектно-ориентированное тестирование: миф и реальность гласит:
Миф: проверка черного ящика достаточно.Если вы выполняете тщательную работу по тестированию дизайн с использованием интерфейса класса или спецификации, вы можете быть уверены, что класс полностью реализован. Проверка белого ящика (просмотр реализация метода для проектирования тесты) нарушает саму концепцию инкапсуляция.
Реальность: важна структура ОО, часть II.Многие исследования показали, что ящики с черным ящиком считаются мучительно тщательно разработчики только упражнение от одной трети до половины (не говоря уже о путях или государств) при реализации контрольная работа. Существует три причины это. Во-первых, входы или состояния выбранные обычно осуществляют нормальное пути, но не заставляйте всех возможных дорожки/состояния. Во-вторых, черный ящик тестирование само по себе не может выявить сюрпризов. Предположим, мы проверили все заданное поведение системы под испытаниями. Чтобы быть уверенными, есть нет неопределенного поведения, которое нам необходимо знать, есть ли в какой-либо части системы не выполнялся черным ящиком тестирование. Единственный способ информация может быть получена по коду измерительные приборы. В-третьих, часто трудно осуществлять исключение и обработки ошибок без проверки исходный код.
Я должен добавить, что я выполняю функциональное тестирование whitebox: я вижу код (в реализации), и я пишу функциональные тесты (которые приводят публичный API) для реализации различных ветвей кода (подробности реализации функции).