2010-09-02 3 views
13

Я писал тесты некоторое время, и я начинаю разбираться в вещах. Но у меня есть некоторые вопросы относительно того, сколько действительно необходимо для тестирования. Консенсус кажется довольно ясным: больше охвата всегда лучше. Но, по крайней мере, с точки зрения новичка, я задаюсь вопросом, действительно ли это так.Что не тестировать в Rails?

Возьмите это полностью ванильное действие контроллера, например:

def create 
    @event = Event.new(params[:event]) 
    if @event.save 
    flash[:notice] = "Event successfully created." 
    redirect_to events_path 
    else 
    render :action => 'new' 
    end 
end 

Просто сгенерированные строительные леса. Здесь мы не делаем ничего необычного. Почему важно написать тесты контроллера для этого действия? В конце концов, мы даже не писали код - генератор сделал для нас работу. Если в рельсах нет ошибки, этот код должен быть в порядке. Кажется, тестирование этого действия не слишком отличается от тестирования, скажем, collection_select, - и мы этого не сделали. Кроме того, предполагая, что мы используем огурец, у нас уже должны быть основаны основы (например, где он перенаправляется).

То же самое можно сказать и о простых методах модели. Например:

def full_name 
    "#{first_name} #{last_name}" 
end 

Нужно ли нам писать тесты для таких простых методов? Если есть синтаксическая ошибка, вы поймаете ее на обновлении страницы. Точно так же огурец поймает это, пока ваши функции попадут на любую страницу, которая называется методом full_name. Очевидно, мы не должны полагаться на огурец для чего-то слишком сложного. Но действительно ли full_name действительно нуждается в модульном тесте?

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

Но, как я уже сказал, я вряд ли эксперт-тестер. Я не обязательно выступаю за меньшее покрытие теста. Скорее, я ищу совет экспертов. Есть ли веская причина писать такие простые тесты?

+0

http://www.railway.at/articles/2008/05/14/do-we-really-need-controller-and-view-tests/ – prograils

+0

https://www.justinweiss.com/articles/ how-much-test-is-too-much/ – prograils

+0

https://signalvnoise.com/posts/3159-testing-like-the-tsa – prograils

ответ

9

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

Для меня тестов облегчают три вещей:

  1. Они garantuee неразрывной старой функциональности Если я могу проверить, что ничего нового, что я положил в сломался моих старых вещей, запустив тесты, это в хорошая вещь.

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

  3. Это документация моей работы Нетривиальный код должен быть документирован. Если, однако, вы согласитесь со мной, что комментарии в коде работы дьявола, имея четкие и краткие блок-тесты, которые делают вас понять, что должно быть правильно. что-то есть, есть (еще раз) a must.

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

1

Для сгенерированного кода нет необходимости иметь покрытие для тестирования там, потому что, как вы сказали, вы его не пишете. Если есть проблема, это выходит за рамки тестов, которые должны быть сфокусированы на вашем проекте. Аналогично, вам, вероятно, не нужно будет явно тестировать любые библиотеки, которые вы используете.

Для вашего конкретного метода похоже, что это эквивалент сеттера (это было немного с тех пор, как я сделал Ruby on Rails) - тестирование этого метода будет проверять возможности языка. Если вы меняете значения или генерируете выходные данные, тогда вы должны пройти тест. Но если вы просто устанавливаете значения или возвращаете что-то без каких-либо вычислений или логики, я не вижу преимуществ, связанных с тем, чтобы тесты охватывали эти методы, как если бы они были неправильными, вы должны иметь возможность обнаруживать проблему при визуальной проверке или в проблеме это языковой дефект.

Что касается других методов, если вы их пишете, вероятно, вы должны пройти тест на них. В тестовой разработке это важно, поскольку тесты для определенного метода существуют до того, как этот метод выполняет, и вы пишете методы для прохождения теста. Если вы сначала не пишете свои тесты, вы все равно получите хоть какую-то выгоду, чтобы иметь хотя бы простой тест, если этот метод когда-либо изменится.

4

Основным преимуществом, которое вы получили от написания единичного теста или двух для этого метода, было бы регрессионное тестирование. Если в какой-то момент в будущем что-то изменилось, что негативно повлияло на этот метод, вы бы смогли его поймать.

Независимо от того, стоит ли это усилий, в конечном счете, зависит от вас.

Второе преимущество, которое я могу видеть, глядя на него, будет проверять граничные случаи, например, что он должен делать, если last_name - ""10 или nil. Это может показать неожиданное поведение.

(т.е. если last_name является nil и first_name является "John", вы получаете full_name =>"John ")

Опять же, преимущество затрат против-это в конечном счете, зависит от вас.

6

Больше покрытия лучше для качества кода, но оно стоит дороже. Здесь есть скользящая шкала, если вы кодируете искусственное сердце, вам нужно больше тестов. Чем меньше вы платите авансом, тем больше вероятность, что вы заплатите позже, может быть, больно.

В примере full_name, почему вы разместили пробел между ними и упорядочивали по первому имени, а затем last_name - это важно? Если позже вас попросят сортировать по фамилии, нормально ли менять порядок и добавить запятую? Что, если фамилия - это два слова - будет ли лишнее пространство влиять на вещи? Может быть, у вас также есть xml-канал, который кто-то разбирает? Если вы не уверены, что тестировать, для простой недокументированной функции, возможно, подумайте о функциональности, подразумеваемой именем метода.

Я бы подумал, что культура вашей компании тоже важна. Если вы делаете больше, чем другие, то вы действительно теряете время. Не помогает иметь хорошо протестированный нижний колонтитул, если основной контент неисправен. Причинить взломы основной сборки или других разработчиков, было бы еще хуже. Найти баланс сложно - если только он не является решающим, потратьте некоторое время на чтение тестового кода, написанного другими членами команды.

Некоторые люди используют подход к проверке корпусов кромок и предполагают, что основные функции будут разработаны с помощью использования. Принимая во внимание getter/setters, я бы хотел, чтобы какой-то модельный класс, у которого есть несколько тестов для этих методов, возможно, тестируйте диапазоны типов столбцов базы данных. Это, по крайней мере, говорит мне, что сеть в порядке, соединение с базой данных может быть выполнено, у меня есть доступ к записи в существующую таблицу и т. Д. Страницы приходят и уходят, поэтому не учитывайте, что загрузка страницы является заменой фактической модульный тест. (Обратите внимание, что при автоматическом тестировании на основе временной отметки времени обновления файла (автотеста) этот тест не запускается, и вы хотите знать как можно скорее)

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

Если вы автоматизируете свое тестирование, не имеет значения, сколько времени потребуется на запуск. Вы выигрываете каждый раз, когда тестовый код запускается - в этот момент вы знаете, что минимальная функциональность вашего кода работает, и вы получаете представление о том, насколько надежны проверенные функциональные возможности со временем.

100% покрытие не должно быть вашей целью - хорошее тестирование должно быть. Было бы неверно думать, что один тест на регулярное выражение выполняет что-либо. Я бы предпочел не испытывать ни одного теста, потому что мой отчет о автоматическом покрытии напоминает мне, что RE ненадежен.

6

Единственное абсолютное правило заключается в том, что тестирование должно быть экономичным.

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

Unit

  • Не проверять частные методы напрямую, только оценить их влияние косвенно через публичные методы, которые вызывают их.
  • Не испытывайте внутренние состояния
  • только проверить нетривиальные методы, где различные контексты могут получить разные результаты (расчеты, конкатенация, регулярные выражения, ветвь ...)
  • Не оценивай вещи, которые вам не нужны, например полная копия на каком-то сообщении или бесполезные части сложных структур данных, возвращаемых API ...
  • Заблокируйте все объекты в модульных тестах, они называются модульными тестами, потому что вы тестируете только один класс, а не его соавторы , С помощью заглушек/шпионов вы проверяете отправленные вами сообщения, не проверяя их внутреннюю логику.
  • Рассмотрим частные вложенные классы как частные методы

Интеграция

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

Контроллер

  • В тестах контроллера, только тест логика контроллера: перенаправления аутентификации, разрешение, состояние HTTP. Заблокируйте бизнес-логику. Рассмотрите фильтры и т. Д., Как частные методы в модульных тестах, проверяйте только действия открытого контроллера.

Другие
  • Не писать маршрутные тесты, за исключением того, что если вы пишете API для конечных точек, которые не охвачены интеграционных тестов.
  • Не писать тосты просмотра. Вы должны иметь возможность изменять классы копирования или HTML, не нарушая своих тестов. Просто оцените критические элементы представления как часть ваших интеграционных тестов в браузере.
  • Проведите проверку своего клиента JS, особенно если он содержит некоторую прикладную логику. Все эти правила также применимы к испытаниям JS.

Игнорирование любого из этих правил для бизнес-критичные вещи, или когда что-то на самом деле разрушает (никто не хочет, чтобы объяснить их босса/пользователей, почему же ошибка случилось дважды, поэтому вы, вероятно, следует написать по крайней мере, регрессивные тесты при исправлении ошибки).

См. Более подробную информацию о that post.

+0

«Это сообщение» - неработающая ссылка. – prograils

Смежные вопросы