Еще раз. То что при изменении свойства Visible кнопки меняется ее видимость — это тестировали за вас. Правильную в данном конкретном случае надпись кнопки тоже устанавливает модель и именно там и надо писать модульный тест, подставляя вместо кнопки какой-нибудь mock и проверяя в конце теста что надпись действительно изменилась. Модульные тесты — это максимально изолированные тесты без внешних зависимостей, таких как файловая система, база данных, библиотека пользовательского интерфейса, парсер html который из <button> нарисует на экране кнопку и т.д.
Практически отменяет. Если кнопка «обновить» вызывает метод metamodel.Refresh(true) то тестировать надо метод модели, а не кнопку — кнопку (то что если на нее нажать — возникнет событие) уже протестировал разработчик используемого вами библиотеки пользовательского интерфейса.
Unit-тесты предназначены для тестирования логики и поведения отдельных классов.
Если обработчик нажатия кнопки на пользовательском интерфейсе содержит какую-то бизнес-логику, то это сигнал пересмотреть архитектуру приложения и, как минимум, разделить, слои (layers).
Статью, безусловно, читал, но то что первое исключает второе, хоть убейте, не помню. Если несложно, приведите полную цитату.
Вы всё-таки путаете модульные тесты поведения с интеграционными тестами, это разные вещи, определения я попытался дать в статье. Первые тестируют конкретный объект и то, что он корректно меняет состояние других объектов, вторые — совокупность из 2 и более объектов.
Похожи они разве что тем, что для их написания используются одинаковые фреймворки. «С технологической точки зрения интеграционное тестирование является количественным развитием модульного, поскольку так же, как и модульное тестирование, оперирует интерфейсами модулей и подсистем и требует создания тестового окружения, включая заглушки (Stub) на месте отсутствующих модулей. Основная разница между модульным и интеграционным тестированием состоит в целях, то есть в типах обнаруживаемых дефектов, которые, в свою очередь, определяют стратегию выбора входных данных и методов анализа.»Интуит
Значит наш с вами опыт, банально, различается. Потому что я знаю множество людей, которые пишут такие юнит тесты, которые хочется удалить и переписать заново.
Какие примеры? Используя какой-либо конкретный xUnit фреймворк что ли?
Основной мыслью статьи была мысль, что не стоит писать тесты «абы как». Что написание качественных тестов дело достаточно непростое и к коду с тестами стоит относиться также как и к коду основной системы. Как писать правильно, говорите… Как минимум, используя описанные тестовые объекты :) Я могу написать про AAA, рекомендации по именованию проектов и отдельных методов согласно рекомендациям того же Roy Osheron, если интересно. Просто думал что тема достаточно избита.
Не совсем. Интеграционные тесты — это тесты, проверяющие работоспособность двух или более модулей системы, но в совокупности, то есть нескольких объектов как единого блока. В тестах взаимодействия тестируется всё-таки определенный объект, а вместо зависимостей используются тестовые объекты, такие как моки или тестовые шпионы.
Например, есть класс, который при определенных условиях «дёргает» веб-сервис через зависимый объект. И нам надо проверить, что определенный метод зависимого объекта действительно вызывается. Логичным будет в качестве зависимого класса передать не реальный класс, работающий с вебсервисом (это будет интеграционное тестирование), и не заглушку, которую мы возможно заходим использовать при тестировании состояния, а тестовый шпион, и в конце теста проверить, что определенный метод зависимого объекта при требуемых условиях действительно был вызван (тест взаимодействия).
Думаю, стоит перефразировать на: "неправильно написанные юнит тесты не увеличивают надёжность".
Юнит тесты повышают надёжность и снижают количество возможных багов. Не делают их количество равными нулю, а именно снижают. Точно также как снижают количество багов кодревью и ручное тестирование.
Если нет планирования — то нет ограничений на итерацию.
Это уже скорее канбан, а не скрам.
Модульные тесты — это максимально изолированные тесты без внешних зависимостей, таких как файловая система, база данных, библиотека пользовательского интерфейса, парсер html который из <button> нарисует на экране кнопку и т.д.
Хорошая статья, спасибо.
Imho, было бы неплохо также сравнить TDD с BDD, которое является развитием первого.
Если обработчик нажатия кнопки на пользовательском интерфейсе содержит какую-то бизнес-логику, то это сигнал пересмотреть архитектуру приложения и, как минимум, разделить, слои (layers).
Ну да, некое «обобщение», но мне кажется это уже некоторый «перебор» что ли… :)
Можно еще про 'seams' написать, или про strict и unstrict mocks в приближении уже к более-менее конкретным isolation frameworks.
Вы всё-таки путаете модульные тесты поведения с интеграционными тестами, это разные вещи, определения я попытался дать в статье. Первые тестируют конкретный объект и то, что он корректно меняет состояние других объектов, вторые — совокупность из 2 и более объектов.
Похожи они разве что тем, что для их написания используются одинаковые фреймворки. «С технологической точки зрения интеграционное тестирование является количественным развитием модульного, поскольку так же, как и модульное тестирование, оперирует интерфейсами модулей и подсистем и требует создания тестового окружения, включая заглушки (Stub) на месте отсутствующих модулей. Основная разница между модульным и интеграционным тестированием состоит в целях, то есть в типах обнаруживаемых дефектов, которые, в свою очередь, определяют стратегию выбора входных данных и методов анализа.» Интуит
Какие примеры? Используя какой-либо конкретный xUnit фреймворк что ли?
Какая суть-то? Как, прочитав про шаблоны тестовых объектов, теперь их создать в коде?
Наверное, использовав оператор new, или аналог.
Может быть вы также не используете и шаблоны проектирования, потому что «начхать, всё итак работает»?
Не совсем. Интеграционные тесты — это тесты, проверяющие работоспособность двух или более модулей системы, но в совокупности, то есть нескольких объектов как единого блока. В тестах взаимодействия тестируется всё-таки определенный объект, а вместо зависимостей используются тестовые объекты, такие как моки или тестовые шпионы.
Например, есть класс, который при определенных условиях «дёргает» веб-сервис через зависимый объект. И нам надо проверить, что определенный метод зависимого объекта действительно вызывается. Логичным будет в качестве зависимого класса передать не реальный класс, работающий с вебсервисом (это будет интеграционное тестирование), и не заглушку, которую мы возможно заходим использовать при тестировании состояния, а тестовый шпион, и в конце теста проверить, что определенный метод зависимого объекта при требуемых условиях действительно был вызван (тест взаимодействия).
Юнит тесты повышают надёжность и снижают количество возможных багов. Не делают их количество равными нулю, а именно снижают. Точно также как снижают количество багов кодревью и ручное тестирование.