суббота, 22 декабря 2012 г.

На этой неделе я постиг тестирование RSpec

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

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

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

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

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

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

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

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

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

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

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

например: http://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 истории

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

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

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

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

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

- заполнить поле 1 данными 1

- нажать княпу сабмит

- проверить, что на странице появились записи с данными 1

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

visit services_path

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

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

 

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

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

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

Комментариев нет:

Отправить комментарий