ZenTest, autotest and growl - Update

Long time no serious news in my blog. I apologize for that and hopefully I have for time in the future to write about new and cool ruby and rails stuff. Until then here is some news on ZenTest, autotest and growl integration for ruby on rails projects.

I wrote about this setup and the things you have to do to get all this up and running in my older blogposts (here and here). ZenTest has changed in its newer versions (currently v4.1.4). To get all up and running do the following:

sudo gem uninstall ZenTest

Select all version if more than one is installed!

Then re-install the required gems. ZenTest doesn’t provide all the plugins any more. They have to be installed seperately as you can see above.

sudo gem install ZenTest autotest-rails autotest-growl

Maybe you’ll get the error “no such file to load — autotest/fsevent (LoadError)”. Then install the autotest-fsevent gem. I had this error on my macbook but I can’t tell you why … Just wanted to mention that.

To use growl just require it in your .autotest file in your home directory. My .autotest file:

require 'autotest/growl'

If you don’t install autotest-rails an error will occur:

macpro:mysedcard sb$ autotest
loading autotest/cucumber_rails
Autotest style autotest/cucumber_rails doesn't seem to exist. Aborting.

RubyFoo London 2009

On October 2nd and 3rd RubyFoo London 2009 is happening. According to the speakers table I think this is going to be a good conference.

As I am one of the leaders of the ruby user group Karlsruhe I am proud to announce a 10%-off promotion code for anyone interested going to RubyFoo.

The promotion code: RUGKarlsruhe_RubyFoo

The registration site: https://secure.trifork.com/ruby-london-2009/registration/processConference.m

Have fun attending the conference and if you’re in the mood just drop me a line in case you’re finally attending RubyFoo.

Rails Konferenz 2009

On September 2nd Rails Konferenz 2009 is happening in Frankfurt / Main (Germany). This year I made a request for a talk and I got it.

My topic is “Testing with cucumber”. As it is every year I believe the conference is going to be well attended and the talks will be great.

Find more information on the conference page.

Rails Konferenz 2009

iX Special - Web on rails - and meinkabinett.de

On Monday, June 8th a new iX magazine special was published. I wrote an article together with Marcus Schiesser on rich clients. The goal was to show how easy it is to combine ruby on rails and ExtJS.

This is my first publication and I’m little bit proud of it :) The magazine covers a lot of good topics. Just check it out!

iX Spezial

A votingmachine served as an example application for this article. We completed it and named it meinkabinett.de.

meinkabinett

Give your tests some love - cruisecontrol.rb, rails, git, rcov, unit tests and cucumber

Long time passed since I wrote my last blog post. Things happened and I was very busy. But now I have some news to write about.

Refactoring my current project mysedcard.tv produced a bunch of cucumber features. Those are great and I love to see them running in my console. But that can’t be enough so I remembered RCov and said to myself. Let’s go get it and doing this I decided to finally set up a continuous integration server - cruisecontrol.rb.

Setting up cruisecontrol.rb

As usual I have some unnormal settings I need to cover. I want to combine rails, git, cucumber, unit tests, rcov and cruisecontrol.rb

Take this as a good starting point and install cruisecontrol. I took the official cruisecontrol.rb from thoughtworks

Change the cruisecontrol.rb settings to your needs. Mine look like those:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# config/site_config.rb.example
# site_config.rb contains examples of various configuration options for the local installation
# of CruiseControl.rb.
 
# YOU MUST RESTART YOUR CRUISE CONTROL SERVER FOR ANY CHANGES MADE HERE TO TAKE EFFECT!!!
 
# EMAIL NOTIFICATION
# ------------------
 
# CruiseControl.rb can notify you about build status via email. It uses ActionMailer component of Ruby on Rails 
# framework. Obviously, ActionMailer needs to know how to send out email messages. 
# If you have an SMTP server on your network, and it needs no authentication, write this in your site_config.rb:
 
ActionMailer::Base.smtp_settings = {
  :address =>        "mxgate.mydomain.com",
  :domain =>         "myemaildomain.com",
  :port =>           25
}
 
#
# If you have no SMTP server at hand, you can configure email notification to use GMail SMTP server, as follows
# (of course, you'll need to create a GMail account):
#
# ActionMailer::Base.smtp_settings = {
#   :address =>        "smtp.gmail.com",
#   :port =>           587,
#   :domain =>         "yourdomain.com",
#   :authentication => :plain,
#   :user_name =>      "yourgmailaccount",
#   :password =>       "yourgmailpassword"
# }
# 
# The same approach works for other SMTP servers thet require authentication. Note that GMail's SMTP server runs on a 
# non-standard port 587 (standard port for SMTP is 25).
#
# For further details about configuration of outgoing email, see Ruby On Rails documentation for ActionMailer::Base.
 
# Other site-wide options are available through Configuration class:
 
# Change how often CC.rb pings Subversion for new requests. Default is 10.seconds, which should be OK for a local
# SVN repository, but probably isn't very polite for a public repository, such as RubyForge. This can also be set for
# each project individually, through project.scheduler.polling_interval option:
Configuration.default_polling_interval = 1.minute
 
# How often the dashboard page refreshes itself. If you have more than 10-20 dashboards open,
# it is advisable to set it to something higher than the default 5 seconds:
Configuration.dashboard_refresh_interval = 20.seconds
 
# Site-wide setting for the email "from" field. This can also be set on per-project basis,
# through project.email.notifier.from attribute
Configuration.email_from = 'cruisecontrolrb@mydomain.com'
 
# Root URL of the dashboard application. Setting this attribute allows various notifiers to include a link to the
# build page in the notification message.
Configuration.dashboard_url = 'http://cc.local/'
 
# If you don't want to allow triggering builds through dashboard Build Now button. Useful when you host CC.rb as a
# public web site (such as http://cruisecontrolrb.thoughtworks.com/projects - try clicking on Build Now button there
# and see what happens):
# Configuration.disable_build_now = true
 
# If you want to only allow one project to build at a time, uncomment this line
# by default, cruise allows multiple projects to build at a time
# Configuration.serialize_builds = true
 
# Amount of time a project will wait to build before failing when build serialization is on
# Configuration.serialized_build_timeout = 3.hours
 
# Amount of time a project will wait for git to load new changesets before failing
Configuration.git_load_new_changesets_timeout = 5.minutes
 
# To delete build when there are more than a certain number present, uncomment this line - it will make the dashboard 
# perform better
BuildReaper.number_of_builds_to_keep = 20
 
# any files that you'd like to override in cruise, keep in ~/.cruise, and copy over when this file is loaded like this
site_css = CRUISE_DATA_ROOT + "/site.css"
FileUtils.cp site_css, RAILS_ROOT + "/public/stylesheets/site.css" if File.exists? site_css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# config/cruise_config.rb.example
# Project-specific configuration for CruiseControl.rb
 
Project.configure do |project|
 
  # Send email notifications about broken and fixed builds to email1@your.site, email2@your.site (default: send to nobody)
  project.email_notifier.emails = ['my@email.com']
 
  # Set email 'from' field to john@doe.com:
  project.email_notifier.from = 'cruisecontrol@mydomain.com'
 
  # Build the project by invoking rake task 'custom'
  # project.rake_task = 'custom'
 
  # Build the project by invoking shell script "build_my_app.sh". Keep in mind that when the script is invoked,
  # current working directory is <em>[cruise&nbsp;data]</em>/projects/your_project/work, so if you do not keep build_my_app.sh
  # in version control, it should be '../build_my_app.sh' instead
  # project.build_command = '../build_my_app.sh'
 
  # Ping Subversion for new revisions every 5 minutes (default: 30 seconds)
  # project.scheduler.polling_interval = 5.minutes
 
end

check out if cruisecontrol.rb is set up correctly

1
CRUISE_DATA_ROOT=/Absolute/path/cruisecontrol.rb/.cruise ./cruise start

I provide CRUISE_DATA_ROOT because cruisecontrol searches projects in ~/.cruise by default. I changed this to store all projects within my cruisecontrol installation.

Go to cruisecontrol.local:3333 (cruisecontrol.local in /etc/hosts and 3333 is the default port for cruisecontrol). You should see something like this:

empty_cruisecontrol

Your first project

After changing settings and testing cruisecontrol’s basic functionality to your needs initialize your first project:

1
CRUISE_DATA_ROOT=./.cruise ./cruise add <myproject> --url git@mygitserver:mygitproject.git -s git

or with a specific branch:

1
CRUISE_DATA_ROOT=./.cruise ./cruise add <myproject> --url git@mygitserver:mygitproject.git -s git -b coverage

When you now go to cruisecontrol.local:3333 now shows you a (failed) first build. It fails because you have to set up your project.

You can achieve this in two way. The first is to initialize the test database for your project manually with:
(change or create config/database.yml)

1
2
RAILS_ENV=test rake db:create
rake db:test:prepare

I show you the second way later together with a new rake task.

Now your continous integration server is up and running, polls frequently for changes in your git repo and hopefully your tests aren’t broken ;)
( Unfortunately only your tests are included but not your features :( )

By default cruisecontrol polls your git repo frequently for updates and - if found any - gets the changed code and executes
rake db:migrate and rake db:test:prepare

Add RCov

You noticed that this blog’s title is “Give your tests some love“. So let’s visualize the impact of your testing efforts with rcov.

First you have to install rcov and the rails_rcov plugin. because I’m using cucumber I follow cucumber’s recommendation and take relevance-rcov.

1
sudo gem install relevance-rcov

The rails_rcov plugin brings in some new rake tasks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
rake test:benchmark:clobber_rcov                # Remove Rcov reports for benchmark tests
rake test:benchmark:rcov                        # Run all benchmark tests with Rcov to measure coverage
rake test:functionals:clobber_rcov              # Remove Rcov reports for functional tests
rake test:functionals:rcov                      # Run all functional tests with Rcov to measure coverage
rake test:integration:clobber_rcov              # Remove Rcov reports for integration tests
rake test:integration:rcov                      # Run all integration tests with Rcov to measure coverage
rake test:plugins:clobber_rcov                  # Remove Rcov reports for plugin tests
rake test:plugins:rcov                          # Run all plugin tests with Rcov to measure coverage
rake test:profile:clobber_rcov                  # Remove Rcov reports for profile tests
rake test:profile:rcov                          # Run all profile tests with Rcov to measure coverage
rake test:recent:clobber_rcov                   # Remove Rcov reports for recent tests
rake test:recent:rcov                           # Run all recent tests with Rcov to measure coverage
rake test:test:clobber_rcov                     # Remove Rcov reports for test tests
rake test:test:rcov                             # Run all test tests with Rcov to measure coverage

To run all your test with rcov hit rake test:test:rcov This rake commands looks a bit strange in the beginning but when you inspect the code you notice that every test task is appended with its own name and “:rcov”. For example “rake test” gets a new brother “rake test:test:rcov”

Running it creates a coverage/ directory which contain all the different coverages. See coverage/index.html for the report.

Cucumber and RCov

follow http://wiki.github.com/aslakhellesoy/cucumber/using-rcov-with-cucumber-and-rails and change the cucumber rake task.

1
t.rcov = true

I added some rcov options to beautify the output:

1
t.rcov_opts << '--exclude gems --sort coverage --aggregate coverage.data'

After getting rcov running we need to integrate it to cruisecontrol.rb.

In order to get this done we add a new rake file for which does the work in cruisecontrol.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# lib/tasks/cruise.rake
desc 'Continuous build target'
task :cruise => ["notes", "stats", "db:migrate", "db:test:prepare"] do
  out = ENV['CC_BUILD_ARTIFACTS']
  mkdir_p out unless File.directory? out if out
 
  ENV['SHOW_ONLY'] = 'models,lib,helpers'
  Rake::Task["test:units:rcov"].invoke
  mv 'coverage/units', "#{out}/unit test coverage" if out
 
  ENV['SHOW_ONLY'] = 'controllers'
  Rake::Task["test:functionals:rcov"].invoke
  mv 'coverage/functionals',"#{out}/functional test coverage" if out
 
  #Rake::Task["test:integration"].invoke
  Rake::Task["test:features"].invoke
end

This task creates all the different coverages and stores them in subfolders. Not enough it prints the coverage output to the commandline so cruisecontrol is able to display everything in the build log.

Notice the last 2 lines:

1
2
#Rake::Task["test:integration"].invoke
Rake::Task["test:features"].invoke

Chose to invoke test:integration or test:features (or both). I namespace the shipped cucumber rake task to :test to have them all in one namespace.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# lib/tasks/cucumber.rake
$LOAD_PATH.unshift(RAILS_ROOT + '/vendor/plugins/cucumber/lib') if File.directory?(RAILS_ROOT + '/vendor/plugins/cucumber/lib')
 
namespace :test do
  begin
    require 'cucumber/rake/task'
 
    Cucumber::Rake::Task.new(:features) do |t|
      t.fork = true
      t.cucumber_opts = %w{--format pretty}
      t.rcov = true
      t.rcov_opts << '--exclude gems --sort coverage --aggregate coverage.data'
    end
    task :features => 'db:test:prepare'
  rescue LoadError
    desc 'Cucumber rake task not available'
    task :features do
      abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
    end
  end
end

The last thing we have to do is to tell cruisecontrol to use this rake task to build our project. Remember the config/cruise_config.rb.example file? We have to change one line:

1
# project.rake_task = 'custom'

gets

1
project.rake_task = 'cruise'

Change the example file in /path/to/cruisecontrol.rb/config/cruise_config.rb.example and /path/to/cruisecontrol.rb/.cruise/projects/ /config/cruise_config.rb for all existing projects.

Now hit the Build button of your project and see the coverage. Hopefully this leads some light in the continuous integration space.

You like what I’m doing? Recommend me on Working With Rails

More links:
http://codeintensity.blogspot.com/2008/04/setting-up-cruisecontrolrb-withfor-git.html
http://github.com/thoughtworks/cruisecontrol.rb
http://morshed-alam.blogspot.com/2008/09/implementation-of-cruisecontrolrb-and.html
http://deadprogrammersociety.blogspot.com/2007/06/cruisecontrolrb-and-rcov-are-so-good.html
http://wiki.github.com/aslakhellesoy/cucumber/using-rcov-with-cucumber-and-rails
http://github.com/relevance/rcov
http://agilewebdevelopment.com/plugins/rails_rcov

RailsWayCon here I come

In a couple of hours I’m leaving good old Karlsruhe by train to hit Berlin and RailsWayCon. This will take about 6 hours but as my buddy Marco is coming with me I think it won’t last that long. Besides that I’m going to have enough time to finally check out my personal timetable.

What can I expect of RailsWayCon?

On Monday, day one, there are two workshops. One is about deploying ruby on rails applications with all its different faces by Jonathan Weiss and Mathias Meyer. The other one is about behaviour driven design in practice by Jens Christian Fischer. As I already visited a workshop about BDD with RSpec held by J.C. Fischer - which was really good - and I’m not that familiar with RSpec and don’t want to, I decided to visit the workshop about deploying ruby on rails applications. So I’m looking forward to learn something new and cool about deploying rails apps :)

On day two and three a couple of good looking talks are taking place. We’ll see how all the talks are going to be.

See ya at RailsWayCon!

p.s: anyone else in putinn hotel? Let me know!

EDIT:
As I missed an after report for RailsWayCon, here are some links which tell you everything you need to know about the conf.
http://railsmagazin.de/railswaycon-in-6-minuten-1411
http://railslove.com/weblog/2009/05/30/railswaycon-09-in-berlin-ruckblick/
http://www.jrubyonrails.de/2009/05/aktuelles-von-der-railswaycon.html

web2.nullify your name

Ever wanted to see your name in famous web2.0-services’ characters? No, problem. 0write does this for you. Here’s how my company’s name and mine look like:

basiszwo-web20


stefanbotzenhart-web20

Cucumber, autotest and growl

Using cucumber and bdd is just fun. Shoulda have used it earlier … Sorry, I need to write that :)

When you use cucumber (at the beginning) you always have to run

cucumber features

in your console to run all your features. Or you specify one by running

cucumber features/session.feature

There are some more ways but have a look at the documentation for that.

Ok, back to topic. I want to include my cucumber features in autotest. No big deal about that. As usual, just read the f****** manual -> http://wiki.github.com/aslakhellesoy/cucumber/autotest-integration.

Just paste

export AUTOFEATURE=true

in your .bashprofile, .bashrc or whatever you use.

As you can read in another blog post of mine I use growl to notify about failing and passing tests. How to get this for cucumber features? And again … rtfm :) Here we go! Just install the cucumber_growl plugin in your application and it just works. (I linked my fork because I want to use my autotest images). As with every external repository I use braid to keep track of it.

That’s all. Now autotest includes your cucumber features and growl notifies you about the results. Have fun with bdd!

braid - keep track of external git and svn repositories within a git repository

Attending Euruko 2009 was great! I recommend this conference to every ruby enthusiast. The authors auf braid held a flash talk and tried to demonstrate the power of braid. Unfortunately the didn’t manage to although they typed their commands incredibly fast :)

Back home I gave braid a try and this tool is great. Before I used git submodules but it’s not the same …

To make use of braid you have to install the gem. Just hit

sudo gem install braid

Now you can start using braid in your git repository. For example I want to use my forked acts_as_state_machine gem

braid add git://github.com/basiszwo/aasm.git vendor/gems/basiszwo-aasm-2.0.5

Notice the ‘basiszwo-aasm-2.0.5′. It’s important to add gems to your vendor/gems directory with name and a version number. If you don’t you’ll receive an error while loading your rails application.

You’ll get a .braids file where all your external repositories are listed.

To keep track of these repositories just type

braid update

That’s all! Pretty easy …

Have a look a the project’s github page for more infos!

git-sh - a customized bash shell suitable for git work

Due to a buddy’s tip I installed git-sh from github. Git-sh is a customized bash shell for your daily work with git. It ships along with some handy shortcuts within your new git shell and it’s fully customizable:

Aliases from ~/.gitshrc
commit                  'git commit --verbose'
amend                   'git commit --verbose --amend'
ci                      'git commit --verbose'
ca                      'git commit --verbose --all'
n                       'git commit --verbose --amend'
a                       'git add'
aa                      'git add --update'
ap                      'git add --patch'
c                       'git checkout'
f                       'git fetch'
r                       'git rebase --interactive HEAD~10'
d                       'git diff'
p                       'git diff --cached'   # mnemonic: "patch"
s                       'git status'
L                       'git log'
l                       'git log --pretty=oneline --abbrev-commit'
ll                      'git log --pretty=oneline --abbrev-commit --max-count=15'
mirror                  'git reset --hard'
stage                   'git add'
unstage                 'git reset HEAD'
pop                     'git reset --soft HEAD^'
review                  'git log -p --max-count=1'

Just check it out! Great tool, easy usage!