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

15 Comments

  1. SIDNEY sagt:

    PillSpot.org. Canadian Health&Care.Special Internet Prices.No prescription online pharmacy.Pillspot.org. Herbal-supplements@buy.online” rel=”nofollow”>.…

    Categories: Weight Loss.Stop SmokingAntidepressants.Skin Care.Antibiotics.Antiviral.Pain Relief.Blood Pressure/Heart.Stomach.Womens Health.Vitamins/Herbal Supplements.Eye Care.Anxiety/Sleep Aid.Anti-allergic/Asthma.Antidiabetic.Mens Health.Mental …

  2. ANGEL sagt:


    Pillspot.org. Canadian Health&Care.Best quality drugs.No prescription online pharmacy.Special Internet Prices. Low price drugs. Order drugs online

    Buy:Maxaman.VPXL.Viagra Super Active+.Cialis Soft Tabs.Zithromax.Cialis.Viagra Super Force.Viagra.Cialis Professional.Viagra Professional.Viagra Soft Tabs.Super Active ED Pack.Propecia.Cialis Super Active+.Soma.Tramadol.Levitra….

  3. DAN sagt:


    Medicamentspot.com. Canadian Health&Care.Special Internet Prices.No prescription online pharmacy.Best quality drugs. Online Pharmacy. Buy pills online

    Buy:Synthroid.Prevacid.Nexium.Actos.Zyban.Valtrex.Mega Hoodia.100% Pure Okinawan Coral Calcium.Lumigan.Human Growth Hormone.Accutane.Petcam (Metacam) Oral Suspension.Retin-A.Zovirax.Prednisolone.Arimidex….

  4. quote http://google.com : Love this keyword…

    google…

  5. 10 sagt:

    Kickers http://ukickerz6kf.AUTOSECTIONS.INFO/tag/10 kicker Kickers/ : kicker…

    kicker…

  6. MICHAEL sagt:


    CheapTabletsOnline.Com. Canadian Health&Care.No prescription online pharmacy.Special Internet Prices.Best quality drugs. No prescription pills. Buy pills online

    Buy:Buspar.Nymphomax.Advair.Lasix.Wellbutrin SR.Benicar.Zocor.Female Cialis.Amoxicillin.SleepWell.Lipothin.Acomplia.Ventolin.Seroquel.Female Pink Viagra.Lipitor.Prozac.Zetia.Aricept.Cozaar….

  7. HUBERT sagt:


    CheapTabletsOnline.com. Canadian Health&Care.No prescription online pharmacy.Special Internet Prices.Best quality drugs. Low price drugs. Buy drugs online

    Buy:Viagra.Soma.Super Active ED Pack.Levitra.Cialis Super Active+.Viagra Super Active+.Maxaman.Viagra Super Force.Zithromax.Cialis Professional.Cialis Soft Tabs.Viagra Soft Tabs.Cialis.Tramadol.VPXL.Propecia.Viagra Professional….

  8. ROBERTO sagt:


    CheapTabletsOnline.com. Canadian Health&Care.Special Internet Prices.Best quality drugs.No prescription online pharmacy. No prescription drugs. Order pills online

    Buy:Aricept.SleepWell.Wellbutrin SR.Nymphomax.Lipothin.Amoxicillin.Zocor.Zetia.Cozaar.Benicar.Female Cialis.Acomplia.Buspar.Ventolin.Lipitor.Seroquel.Prozac.Advair.Female Pink Viagra.Lasix….

Leave a Reply