Увлекся я тут тестированием rspec не на шутку, вот, нашел хороший сайт
Прикольный форматтер Fuubar, рекомендую подключить к тестированию rspec как --format fuubar к запуску спеков
Увлекся я тут тестированием rspec не на шутку, вот, нашел хороший сайт
Прикольный форматтер Fuubar, рекомендую подключить к тестированию rspec как --format fuubar к запуску спеков
cd /www/itservice
rvm wrapper 1.9.3@itservice itservice unicorn
создает враппер совместимый с rc.d
Пришлось поправить ссылку на git:
sudo ln -nfs /usr/local/bin/git /usr/bin/git
как описано здесь:
http://ficial.wordpress.com/2011/07/13/phusion-passenger-fixing-no-such-file-or-directory-git-ls-files/
в итоге в rc.d
#
# Add the following lines to /etc/rc.conf to enable unicorn:
# unicorn_enable (bool): Set to "NO" by default.
# Set it to "YES" to enable unicorn
# unicorn_profiles (str): Set to "" by default.
# Define your profiles here.
# unicorn_flags (str): Set to "" by default.
# Extra flags passed to start command.
. /etc/rc.subr
name="unicorn"
rcvar=`set_rcvar`
pidfile="/www/itservice/shared/pids/unicorn.pid"
unicorn_flags="-c /www/itservice/current/config/unicorn/colo.rb -E production -D"
start_cmd="unicorn_start"
command="/usr/local/rvm/bin/itservice_unicorn"
#pidprefix="/var/run/unicorn"
[ -z "$unicorn_enable" ] && unicorn_enable="NO"
load_rc_config $name
unicorn_start() {
echo "Starting ${name}"
${command} ${unicorn_flags}
}
extra_commands="reload"
sig_reload="USR2"
run_rc_command "$1"
и в config/unicorn/colo.rb
deploy_to = "/www/itservice"
app_path = "#{deploy_to}/current"
shared_path = "#{deploy_to}/shared"
pid_file = "#{shared_path}/pids/unicorn.pid"
socket_file= "#{shared_path}/pids/unicorn.sock"
rails_root = "#{deploy_to}/current"
# Set unicorn options
worker_processes 1
preload_app true
timeout 180
listen "127.0.0.1:9000"
# listen socket_file
# Spawn unicorn master worker for user apps (group: apps)
user 'nexus', 'nexus'
# Fill path to your app
working_directory app_path
# Should be 'production' by default, otherwise use other env
rails_env = ENV['RAILS_ENV'] || 'production'
# Log everything to one file
stderr_path "log/unicorn.log"
stdout_path "log/unicorn.log"
# Set master PID location
pid "#{shared_path}/pids/unicorn.pid"
before_fork do |server, worker|
ActiveRecord::Base.connection.disconnect!
old_pid = "#{server.config[:pid]}.oldbin"
if File.exists?(old_pid) && server.pid != old_pid
begin
Process.kill("QUIT", File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
# someone else did our job for us
end
end
end
after_fork do |server, worker|
ActiveRecord::Base.establish_connection
end
Лично для меня, довольно тертого разработчика, процесс внедрения TDD был непростым и местами тернистым.
Вкратце законспектирую, поскольку порог входа в тестирование действительно выше, чем просто сесть и писать код. Сделаю несколько, как написали бы пиндосы, highlights.
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 чуть менее чем полностью.
Как сейчас водится, люди тестируют в трех направлениях.
Здесь мы проверяем корректность методов в моделях, корректность валидаций.
validate_presence_of(:model) не идет в комплекте бойца с rspec, поэтому приходится ставить и подключать shoulda
gem "shoulda-matchers"
и далее в spec_helper.rb
require 'shoulda-matchers'
Проверяются вещи, что бы create действительно создавал объект или рендерил 'new' и такое прочее
типовой тест будет включать в себя вызов контроллера
post :create, mymodel: param1
и проверку результатов. Например в assigns идет то, что должно присвоиться в методе контроллера
assigns(:mymodel){ should == MyModel.last }
проверяем, что отрендерится темплейт new. Это очевидно, но не интуитивно.
response.should render_template('new')
Это больше парафия Cucumber, однако, rspec в базе создает request/ папку, куда и помещаются интеграционные тесты
Мне очень нравится подход Cucumber тем, что происходит осмысление "зачем нужна эта фича" при каждом взгляде на тест, поскольку там собственно и написано "зачем". Но мы же знаем, что фичу можно сделать разными способами, главное, чтобы "зачем" осталось тем же самым.
Так вот, в базе интеграционный тест прогоняет цепочку действий при помощи эмуляции браузера.
Чаще всего что бы работала такая хрень подключаются gem capybara или webrat, которые собственно и делают эмуляцию браузера
Тестирование обычно выглядит так:
- заполнить поле 1 данными 1
- нажать княпу сабмит
- проверить, что на странице появились записи с данными 1
примерно такой код
visit services_path
page.should have_content("Сервис антивирусных")
visit и have_content нам достается из гема капибары.
Немного про то, что и как тестировать. Следует проверять пограничные случаи, например, если код должен создавать юзера, то проверьте это двумя тестами:
1. Юзер создается корректно, проверяем что в базке запись появилась.
2. Что мы действительно получаем ошибку, если юзер не создается корректно.
Итак, при очередном деплое на FreeBSD было решено добиться автоматизированной взаимности от Capistrano в неожиданной конфигурации.
Для того, что бы использовать разные версии руби (1.9.3 например) мне пришлось использовать вместо удобного Passenger неудобный Unicorn.
Для отладки использован multistage в виде строки
require 'capistrano/ext/multistage'
в deploy.rb
и в виде конфигов в config/deploy/xxxxxx.rb для каждого случая (у меня staging, aws, colo)
баг возник неожиданно, капистрано не распознавал deploy_to, что решил stackoverflow http://stackoverflow.com/questions/8213376/capistrano-multistage-deploying-to-wrong-directory
каждый файл должен содержать
set(:deploy_to){ "/var/www/#{application}" }
set(:releases_path) { File.join(deploy_to, version_dir) }
set(:shared_path) { File.join(deploy_to, shared_dir) }
set(:current_path) { File.join(deploy_to, current_dir) }
set(:release_path) { File.join(releases_path, release_name) }
а конструкция
set :deploy_to, "/var/www/#{application}" попросту не работала :(
======================================================================
Запуск на colo (FreeBSD) закончился удачно, но авторизация OAuth слетала с известной SSL багой, которая вылечилась скачиванием ca-bundle.crt в config приложения, и с указанием на нее в config/initializers/device.rb
config.omniauth :google_oauth2, "xxxxx", "yyyyyyyyyy", { :access_type => "offline", :approval_prompt => "", :client_options => { :ssl => { :ca_file => "#{Rails.root}/config/ca-bundle.crt" }}}
======================================================================
к Апачу unicorn подключили как балансер по http, через unix socket Unicorn с апачем не работает
что описано здесь http://stackoverflow.com/questions/5780886/proxy-apache-load-balancers-to-a-unix-socket-instead-of-a-port
<VirtualHost *:80>
ServerName itservice
DocumentRoot /www/itservice/current/public
<Proxy balancer://unicornservers>
BalancerMember http://127.0.0.1:9000
</Proxy>
ProxyRequests Off
ProxyPass /assets/ !
ProxyPass / balancer://unicornservers/
ProxyPassReverse / balancer://unicornservers/
ProxyPreserveHost on
</VirtualHost>
set(:releases_path){File.join(deploy_to, version_dir)}set(:shared_path){File.join(deploy_to, shared_dir)}set(:current_path){File.join(deploy_to, current_dir)}set(:release_path){File.join(releases_path, release_name)}
При всей моей любви к FreeBSD все у нее не слава богу. Не ориентируется на нее майнстрим, поэтому ничего на ней не тестируется и не работает искаропки.
Пример тому http://code.google.com/p/rubyenterpriseedition/issues/detail?id=61 установка ree-head тот что 2012.02
Просто тупо из-за небольшого известного бага с библиотеками не инсталлится.
А порты? Все, перехожу или на убунту lts или на центос. При чем первый мне нравится больше благодаря богатому внутреннему миру apt-get.
посеять данные с первичными связями не такая уж и простая задача
дядя Бейтс тут рассказал про правильные способы: http://railscasts.com/episodes/179-seed-data?view=asciicast
Если деплоить unicorn+nginx, то можно поставить nginx из портов и просто аплоадить конфиги. С другой стороны Леня Шевцов написал cuoco, что может еще более облегчить жизнь.