Лично для меня, довольно тертого разработчика, процесс внедрения TDD был непростым и местами тернистым.

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

Теоретически процесс TDD должен выглядеть так:



1. Написали падающий тест, прогнали rspec, убедились что тест не проходит (красный)

2. Написали кусок кода, прогнали rspec, убедились что тест проходит (зеленый)

3. Отрефакторили, убедились что все хорошо и тесты не падают.

4. Отправили код в продакшн



Тестирование довольно медленно запускается само по себе, поэтому люди делают ухищрения: ставят spork, который держит инстанс приложения в памяти и экономит время при каждом запуске рельс. Уменьшение времени тестов на время запуска (у меня секунд 7-10) гарантировано.
UPDATE: Как подсказали в комментариях (о, слава хабру) имеет смысл обратить внимание на zeus.

Далее. То, что раньше делал autotest, сейчас модно делать с guard. Суть в том, что бы мониторить изменения файлов и запускать только те тесты, которых это изменение касалось, что, очевидно, ускорит получение обратной связи от тестирования. Довольно удобно, только система не всегда ловит эти самые изменения. Так, например, изменение в factory не приведет к тестам, для этого я лишний раз дергаю измененный файл спека модели и, вроде как, поехало.

Раньше тестовые наборы данных хранились в YAML файлах и назывались фикстурами (fixtures). Каждый тест загружал фикстуры из файлов в базу, и, хотя, их можно было загружать выборочно, такая процедура была довольно медленной и ресурсоемкой. Ребята из thoughtbot решили данную проблему тем, что фикстуры стали генерить программно и назвали фабриками (factories). Фабрики действительно ощутимо быстрее и позволяют без проблем создавать связанные ассоциативные инстансы, изменяемые наборы данных (sequence), например, разные emailы пользователей и другие прикольные штуки. Сейчас все еще модно использовать FactoryGirl.

Все эти технологии также требуют наличия хорошего напильника. При чем, порой, если бы не стековерфлоу, я бы отчаялся применять TDD:

например: stackoverflow.com/questions/8303491/how-do-i-make-sure-the-helpers-and-models-reload-in-rspec-when-im-using-spork

Само тестирование



Сейчас модно использовать RSpec, поскольку он лаконичнее и описательнее чем Test::Unit, который идет в комплекте с рельсами. Тесты в rspec называются спеками (от слова спецификация). Вроде само тестирование рельс сейчас тоже переехало на rspec, не знаю. Самый писк моды – приблизиться к человеческому языку, так что бы тесты были как бы метаописаниями, как бы объясняли на примерах как должен работать код. Чем меньше сам текст теста и чем он выразительнее, тем лучше. Мне в этом плане был очень близок cucumber (огурец). Сейчас rspec научился собой заменять cucumber чуть менее чем полностью.

Как сейчас водится, люди тестируют в трех направлениях.

1. Тесты моделей, или юнит-тесты


Здесь мы проверяем корректность методов в моделях, корректность валидаций.

validate_presence_of(:model) не идет в комплекте бойца с rspec, поэтому приходится ставить и подключать shoulda

gem "shoulda-matchers"

и далее в spec_helper.rb

require 'shoulda-matchers'

2. Тесты контроллеров, или как их еще называют, функциональные


Проверяются вещи, что бы create действительно создавал объект или рендерил 'new' и такое прочее

типовой тест будет включать в себя вызов контроллера

post :create, mymodel: param1

и проверку результатов. Например в assigns идет то, что должно присвоиться в методе контроллера

assigns(:mymodel){ should == MyModel.last }

проверяем, что отрендерится темплейт new. Это очевидно, но не интуитивно.

response.should render_template('new')

3. Интеграционные тесты, bdd истории


BDD история это то, как выглядит фича в глазах заказчика в переводе на язык разработчика. Обычно история это одновременно и описание и кусок кода для проведения тестирования этой же фичи.

Это больше парафия Cucumber, однако, rspec в базовой установке тоже создает spec/request/ папку, куда и помещаются интеграционные тесты.

Мне очень нравится подход Cucumber тем, что происходит осмысление «зачем нужна эта фича» при каждом взгляде на тест, поскольку там собственно и написано «зачем». Но мы же знаем, что фичу можно сделать разными способами, главное, чтобы «зачем» осталось тем же самым.

Так вот, интеграционный тест прогоняет це��очку действий при помощи эмуляции браузера.

Чаще всего что бы работала такая хрень подключаются gem capybara или webrat, которые собственно и делают эмуляцию браузера

Тестирование обычно выглядит так:

  • заполнить поле 1 данными 1
  • нажать княпу сабмит
  • проверить, что на странице появились записи с данными 1

примерно такой код

visit services_path

page.should have_content("Сервис антивирусных")


visit и have_content нам достается из гема капибары.

Немного про то, что и как тестировать. Следует проверять пограничные случаи, например, если код должен создавать юзера, то проверьте это двумя тестами:

1. Юзер создается корректно, проверяем что в базке запись появилась.

2. Что мы действительно получаем ошибку, если юзер не создается корректно.

Все, кто уже тестируют, молодцы, а всем, кто еще этого не делает, рекомендую начать.