Тестирование: как сосредоточиться на поведении, а не на реализации, не теряя скорости?

Кажется, что существует два совершенно разных подхода к тестированию, и я хотел бы привести оба из них.

Дело в том, что эти мнения были высказаны 5 лет назад (2007), и мне интересно, что изменилось с тех пор и в какую сторону мне идти.

Брэндон Киперс:

Теория заключается в том, что тесты должны быть агностическими по отношению к реализация. Это приводит к менее хрупким испытаниям и фактическим испытаниям. результат (или поведение).

С RSpec я чувствую, что общий подход полностью высмеивает вас модели для тестирования контроллеров в конечном итоге заставляют вас выглядеть слишком много в реализацию вашего контроллера.

Это само по себе не так уж и плохо,но проблема в том, что он тоже аналогичен много в контроллере, чтобы диктовать, как модель используется. Почему это происходит Имеет значение, если мой контроллер вызывает Thing.new? Что делать, если мой контроллер решает взять Thing.create! и спасательный маршрут? Что делать, если у моей модели есть специальный метод инициализатора, как Thing.build_with_foo? Моя спецификация для поведение не должно потерпеть неудачу, если я изменяю реализацию.

Эта проблема становится еще хуже, когда у вас есть вложенные ресурсы и создание нескольких моделей для каждого контроллера. Некоторые из моих методов настройки заканчиваются до 15 или более линий длиной и ОЧЕНЬ хрупким.

Цель RSpec состоит в том, чтобы полностью изолировать логику контроллера от ваши модели, что звучит неплохо в теории, но почти идет вразрез с зерно для интегрированного стека, такого как Rails. Особенно, если вы практикуете дисциплина тощего контроллера/толстой модели, количество логики в контроллер становится очень маленьким, а настройка становится огромной.

Так что же делать BDD-wannabe? Делая шаг назад,поведение, которое я реально хочу тестировать не то, что мой контроллер вызывает Thing.new, а что задавая параметры X, он создает новую вещь и перенаправляет на нее.

Дэвид Челимски:

Все дело в компромиссах.

Тот факт, что AR выбирает наследование, а не делегирование, ставит нас в тупик тестовая привязка – мы должны быть связаны с базой данных ИЛИ мы должны быть более близким к реализации. Мы принимаем этот выбор дизайна потому что мы пожинаем плоды выразительности и сухости.

В борьбе с дилеммой я выбрал более быстрые тесты за счет немного более хрупкий. Вы выбираете менее хрупкие тесты по цене из них работают немного медленнее. Это компромисс в любом случае.

На практике я провожу тесты сотни, если не тысячи раз в год. день (я использую автотест и делаю очень детальные шаги) и я изменяю, Я использую «новый» или «создать» почти никогда. Также благодаря гранулированным шагам, новый модели, которые появляются, поначалу довольно изменчивы.valid_thing_attrs подход немного минимизирует боль от этого, но это все равно означает, что каждое новое обязательное поле означает, что я должен изменить valid_thing_attrs.

Но если ваш подход работает на вас на практике, то это хорошо! В На самом деле, я настоятельно рекомендую вам опубликовать плагин с генераторами которые производят примеры так, как вам нравится. Я уверен, что много людей выиграют от этого.

Райан Бейтс:

Из любопытства, как часто вы используете макеты в своих тестах/спецификациях? Возможно, я делаю что-то не так, но я нахожу это серьезным ограничивающий. С тех пор, как я перешел на rSpec более месяца назад, я занимаюсь Что они рекомендуют в документах, где контроллер и просмотр слоев не попадают в базу данных вообще и модели полностью макетируются вне. Это дает вам хороший прирост скорости и облегчает некоторые вещи, но я нахожу, что минусы этого намного перевешивают плюсы. С Используя макеты, мои спецификации превратились в кошмар обслуживания.Очки предназначены для тестирования поведения, а не реализации. Меня не волнует Если был вызван метод, я просто хочу убедиться в результирующем выводе правильно. Потому что издевательство делает спецификации придирчивыми к реализация, он делает простые рефакторинги (которые не изменяют поведение) невозможно обойтись без необходимости постоянно возвращаться и «исправить» спецификации. Я очень уверен в том, что должна быть спецификация / тесты крышка. Тест должен прерываться только тогда, когда приложение прерывается. Это один Причина, по которой я почти не проверяю слой представления, потому что я нахожу его слишком жестким. Это часто приводит к прерыванию тестов без прерывания приложения, когда изменение мелочей в представлении. Я нахожу ту же проблему с Издевается. Вдобавок ко всему этому, я только что понял сегодня, что издевательство / стаббинг метод класса (иногда) застревает между спецификациями. Технические характеристики должны быть самодостаточным и не зависеть от других спецификаций. Это нарушает то, что правило и приводит к хитрым ошибкам. Что я узнал из всего этого? Быть осторожно, где вы используете издевательства.Стаббинг не так плох, но все же имеет некоторые из тех же проблем.

Я взял последние несколько часов и удалил почти все макеты из своих спецификаций. Я также объединил контроллер и просмотр спецификаций в один с помощью "integrate_views" в спецификации контроллера. Я также загружаю все приспособления для каждой спецификации контроллера, поэтому есть некоторые тестовые данные для заполнения взгляды. Каков конечный результат? Мои характеристики короче, проще, больше последовательный, менее жесткий, и они тестируют весь стек вместе (модель, вид, контроллер), поэтому никакие баги не могут проскользнуть через трещины. Я не говоря уже о том, что это «правильный» путь для всех. Если ваш проект требует очень строгого случая, тогда это может быть не для вас, но в моем В случае, это миры лучше, чем то, что у меня было до использования макетов. Я до сих пор Думаю, что стаббинг является хорошим решением в нескольких местах, поэтому я все еще делаю тот.

43
задан krn 13 June 2012 в 01:15
поделиться