(first posted: Nov 20, 2007)
(2177 Reads)
keywords: capistrano rspec story runner
Permalink
Running rspec after you deploy
OK, so you've got Capistrano going for deploying you app to a server. Now you should also run your tests there just to ensure everything's A-OK. Here's what I did.
deploy:spec task
The first thing was to make server-specific versions of several files, namely:
- config/database.yml.deploy
- config/environments/production.rb.deploy
- config/environments/test.rb.deploy
The database.yml.deploy is your server-side database.yml file. It just needs a production: and test: configurations (not development:), with the database name and credentials for access on the server.
Optionally, you can also create server-specific environment files. I did this because, for example, my local dev machine uses smtp for email while the server I use sendmail.
Some people just make these in the shared/ directory on the server rather than deploy them, but I prefer to keep all my files in the Subversion repos, even these.
Note: I originally tried to avoid this multiple conf file thing by adding a new environment called "staging", which would be my test environment on the server. But this ran into several issues, basically going against the grain where some plugins assumed just the 3 standard environment names (including rspec itself and fixture_replacement). Even as I worked through these issues making some custom changes, it still gave me problems so I backed out.
Next, we add a few custom tasks to the Capfile,
- task :after - copy the server-specific files
- task :spec - run rake spec on the server
- task :story - run stories/all.rb on the server
Here's the code:
namespace :deploy do
task :after, :roles => :app do
# config on server
run "cd #{release_path}/config && cp -f database.yml.deploy database.yml" run "cd #{release_path}/config/environments && cp -f production.rb.deploy production.rb" run "cd #{release_path}/config/environments && cp -f test.rb.deploy test.rb"end
task :spec, :roles => :app do
run "cd #{current_path} && rake db:test:prepare RAILS_ENV=production" # copy schema from production rather than development run "cd #{current_path} && rake spec RAILS_ENV=production"end
task :story, :roles => :app do
run "cd #{current_path} && rake db:test:prepare RAILS_ENV=production" run "cd #{current_path} && ruby stories/all.rb"end
end
after "deploy:finalize_update", "deploy:after"
Note, with "RAILS_ENV=production" we tell rspec to setup the current db schema from the production environment, rather than the default development one. Its not actually running any tests against the production datatbase (although be sure you have backups till you know for sure!)
Now, when you "cap deploy" it'll copy the *.deploy files to their useful names. And you can run your specs with
$ cap deploy:spec
$ cap deploy:story
Getting the Results
The next step is to generate the output of the runs into a file that can be viewed in a browser.
There's probably a better way to do this but I just keep a server-side version of spec.opts
- spec/spec.opts.deploy
In particular, my specifies html output format,
--format
html
--loadby
mtime
And when we run the tests, we'll pipe the output to files in a private directory. That directory should be protected from prying eyes. So we create a file in the shared directory, lets say app/shared/private.htaccess file like this:
AuthUserFile /path/to/app/public/private/.htpasswd
AuthGroupFile /dev/null
AuthName "Protected files"
AuthType Basic
<Limit GET>
require valid-user
</Limit>
(in my case its
AuthUserFile /home/foobar/www/public/private/.htpasswd
where www is a symlink to ~/apps/myapp/current/public)
And generate a .htpasswd file, something like this
$ cd ~/apps/myapp/shared
$ htpasswd -c .htpasswd admin
New password:
Re-type new password:
Adding password for user admin
Thus, the Capfile changes to
namespace :deploy do
task :after, :roles => :app do
# config on server
run "cd #{release_path}/config && cp -f database.yml.deploy database.yml" run "cd #{release_path}/config/environments && cp -f production.rb.deploy production.rb" run "cd #{release_path}/config/environments && cp -f test.rb.deploy test.rb"# spec on server
run "cd #{release_path}/spec && cp -f spec.opts.deploy spec.opts" run "cd #{release_path} && mkdir private" run "cd #{release_path} && chmod 755 private" run "cd #{release_path}/private && cp -f #{shared_path}/private.htaccess .htaccess" run "cd #{release_path}/private && cp -f #{shared_path}/private.htpasswd .htpasswd" # symlink the ActiveScaffold frontend
run "cd #{release_path}/vendor/plugins/active_scaffold/frontends && ln -s #{release_path}/app/views/a_s_frontends/tablenav ." end
task :spec, :roles => :app do
run "cd #{current_path} && rake db:test:prepare RAILS_ENV=production" # copy schema from production rather than development run "cd #{current_path} && rake spec RAILS_ENV=production >public/private/specs.html"end
task :story, :roles => :app do
run "cd #{current_path} && rake db:test:prepare RAILS_ENV=production" run "cd #{current_path} && ruby stories/all.rb >public/private/stories.txt"end
end
after "deploy:finalize_update", "deploy:after"
Now when you run
$ cap deploy:spec
$ cap deploy:story
You can get the results by pointing your browser to
http://www.yoursite.com/private/specs.html
http://www.yoursite.com/private/stories.txt
NOTE, I believe html output is coming soon to story runner.
One more NOTE, I havent gotten the htpasswd to work under my mongrel server deployment. When I do I'll change this message and correct this article.




Running rspec after you deploy
Posted by: Scott Taylor on November 20, 2007 07:11 PM#