Disable / Enable Nagios Notifications From Command Line

Your a lazy devops, you want to deploy your application in one click BUT you don’t want Nagios to send alerts while you’re deploying. Solution: disable Nagios notifications while deploying.

Disable Nagios Notifications: curl -d "cmd_mod=2&cmd;_typ=11" "http://NAGIOS_HOST/cgi-bin/nagios3/cmd.cgi" -u "USERNAME:PASSWORD"

Re-Enable Nagios Notifications: curl -d "cmd_mod=2&cmd;_typ=12" "http://NAGIOS_HOST/cgi-bin/nagios3/cmd.cgi" -u "USERNAME:PASSWORD"

(My) Cucumber Best Practices and Tips

After (My) RSpec best practices and tips, I’m happy to share my Cucumber best practices and tips!

This article will help you organize, clarify and reduce the size of your cucumber scenarios.

1. Organize your garden

Keep your feature files organized by grouping them by business object, then action and context if any. I put all the feature files in the same directory. For instance:

1
2
3
4
5
bank_account_add.feature
bank_account_delete.feature
user_signup.feature
user_signup_when_invited.feature
user_login.feature

The steps specific to the application should be organized by business object as well (bank_account_steps.rb, user_steps.rb…). Keep the file organized grouping the steps by Given / When / Then.

Do not overload the files generated by Cucumber like step_definitions/web_steps.rb and support/env.rb with your own steps, helpers or setup code. These files are likely to get overwritten when you update Cucumber so store your stuff in your own files.

2. Custom steps make your scenario DRY and accessible

Scenarios should have the same lifecyle as your code: Red, Green, Refactor to make them DRY and easy to read.

Group multiple steps together. For instance:

1
2
3
4
5
6
  Given I follow "Send money"
  When I fill in "Email" with "mukmuk@example.com"
  And I fill in "Amount" with "10"
  And I select "Bank account" from "Source"
  And I press "Send"
  Then I should see "You've sent $10 to mukmuk@example.com"

… could be refactored to:

1
  Given I send "$10" to "mukmuk@example.com" from my "Bank account"

This step definition is the following:

1
2
3
4
5
6
7
8
  Given %{I send "$amount" to "$email" from my "$source"} do |amount, email, source|
    Given %{I follow "Send money"}
    When %{I fill in "Email" with "#{email}"}
    And %{I fill in "Amount" with "#{amount.delete('$')}"}
    And %{I select "#{source}" from "Source"}
    And %{I press "Send"}
    Then %{I should see "You've sent $#{amount} to #{email}"}
  end

This step can then be easily reused in other scenario keeping your features DRY. It also decouples the scenario from the UI so that you won’t have to change dozens of feature files when the UX guru changes translations or user flows.

3. Background: setup the DRY way

Make the feature focus on one business object/action/context and the background will get longer than the scenarios.

1
2
3
4
5
6
7
8
9
10
11
12
13
  Feature: A user can cancel a transaction unless it's claimed by the recipient

    Background:
      Given I am logged in
      And I send "$10" to "mukmuk@example.com" from my "Bank account"

    Scenario: I can cancel as long as the payment is not claimed
      When I cancel my latest transaction
      Then I should see a cancellation confirmation

    Scenario: I can't cancel once the payment is claimed
      Given "Mukmuk" claimed the latest transaction
      Then I can't cancel my latest transaction

4. Scenario outlines: scenario with variables!

A scenario outline contains variables allowing you to test multiple context using a truth table. For instance I use them to make sure that validation errors are displayed properly:

1
2
3
4
5
6
7
8
9
10
11
  Scenario Outline: Add invalid bank account displays inline errors
    Given I follow "Add Bank Account"
    When I fill in "<field>" with "<value>"
    And I press "Add Bank Account"
    And I should see the inline error "<error>" for "<field>"

    Examples:
      | field   | value         | error                    |
      | Account |               | Can't be blank           |
      | Account | Sixty five    | Should be 1 to 12 digits |
      | Account | 1234567890123 | Should be 1 to 12 digits |

5. Multi-line step arguments: give your step a table for lunch!

A step can take a multi-line table as an argument. This is a great way to load up a bunch of data or to test the rendering of lists and tables. For instance:

1
2
3
4
5
6
  Given I sent "$25" to "mukmuk@example.com" from my "Bank account"
  Then I should see the following transaction history:
    | create     | complete    |
    | deposit    | in_progress |
    | transfer   | pending     |
    | withdrawal | pending     |

The step definition looks like the following:

1
2
3
4
5
  Then "I should see the following transaction history:" do |table|
    table.raw.each do |event, state|
      page.should have_css("tr.#{event}.#{state}")
    end
  end

I hope that these tips will help you growing healthy cucumber features!

Want more? Check out the Cucumber wiki, 15 Expert Tips for Using Cucumber by Dave Astels, You’re Cuking It Wrong by Elabs and You’re almost cuking it… by Antony Marcano. You could also like (My) RSpec best practices and tips. :)

Happy BDD!

Thanks to Jean-Michel Garnier for reviewing this article.

Get Integrity to Play Well With Rails 3 and Bundler 1.0

The latest “stable” version of Integrity (v22) doesn’t play well with Rails 3 (or any other application using bundler 1.0). Basically the Integrity’s Gemfile is used in place of the application’s Gemfile when running the tests.

With a Rails 3 application you are likely to get:

no such file to load -- rails/all

Integrity fails to run with Rails 3 and Bundler 1.0

A patched version of integrity v22 for bundler 1.0 is available on http://github.com/pcreux/integrity/tree/v22-bundler-1.0.0.rc.

You also need to force your Rails application to use its Gemfile. To do so, update the file /config/boot.rb with the following:

1
2
3
4
5
6
7
8
9
require 'rubygems'
# Set up gems listed in the Gemfile.
GEMFILE_PATH = File.expand_path('../../Gemfile', __FILE__)
if File.exist?(GEMFILE_PATH)
  # Force the rails 3 application to use its Gemfile
  ENV['BUNDLE_GEMFILE'] = GEMFILE_PATH
  require 'bundler'
  Bundler.setup
end

That should make the trick!

Patched Integrity and custom boot.rb makes integrity working with Rails 3

Speed Up RSpec With Set()

I enjoy using the let() method as it makes my specs easier to read and maintain than setting up instance variables in before(:each) blocks. The let() method can be used like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
describe Account do
  let(:account) { Factory(:account) }

  subject { account }

  it { should be_enabled }

  context "when #disable!" do
    before do
      account.disable!
    end

    it { should be_disabled }
  end
end

My main concern was that the block gets evaluated everytime the method is called. In the example above, Factory(:account) will run and create a new record for every single spec.

To increase our specs performances let’s refactor this and setup the account in a before(:all) block.

1
2
3
4
5
6
7
8
describe Account do
  before(:all) do
    @account = Factory(:account)
  end

  let(:account) { @account.reload }
  #...
end

The account is now setup once before the specs get run. Each spec will be run in a separate transaction to prevent side effects. The account will be rolled back to its initial state before each spec then. Since ActiveRecord is not aware of the rollback we reload the account object from the database every time it’s called.

Specs are now faster but I want them to be as pretty as they were. Let’s make a little helper called set().

Sweeeet! You can now write the following:

1
2
3
4
5
describe Account do
  set(:account) { Factory(:account) }

  #...
end

The records created by set() will remain in your database. You can use DatabaseCleaner with the :truncation strategy to clean up your database. So far in RSpec 2.0, before(:all) runs before all describe/context/it while after(:all) runs after every single describe/context/it. Just make sure that you call DatabaseCleaner.clean in a before(:all) or after(:suite) blocks then. :)

I hope you’ll enjoy using this little helper. It’s very young and it has been tested with RSpec 2 only, so fill free to fill up the comments with enhancements and bug reports!

rspec-set is now available as a gem

Get Script/runner Back in Rails 3

EngineYard’s chef recipe for DelayedJob requires script/runner. To use this recipe with Rails 3 I’ve just made script/runner for Rails 3. Here is the code:

Edit: Fix for rails 3.0

(My) RSpec Best Practices and Tips

After a year using RSpec, I’m happy to share “(My) RSpec Best Practices and Tips”. Let’s make your specs easier to maintain, less verbose, more structured and covering more cases!

Use shortcuts specify {}, it {} and subject {}

You think RSpec is verbose? In case your code doesn’t need any description, use a specify block!

1
2
3
it "should be valid" do
  @user.should be_valid
end

can be replaced with

1
specify { @user.should be_valid }

RSpec will generate a nice description text for you when running this expectation. Even better, you can use the it block!

1
2
3
4
describe User do
  it { should validate_presence_of :name }
  it { should have_one :address }
end

In case the subject is the not the class described, just set it with the subject method:

1
2
subject { @user.address }
it { should be_valid }

Start context with ‘when’/‘with’ and methods description with ‘#’

Have you ever get a failed test with an incomprehensible error message like:

1
User non confirmed confirm email wrong token should not be valid

Start your contexts with when and get nice messages like:

1
User when non confirmed when #confirm_email with wrong token should not be valid

Use RSpec matchers to get meaningful messages

In case of failure

1
specify { user.valid?.should == true }

displays:

1
2
3
'User should == true' FAILED
  expected: true,
  got: false (using ==)

While

1
specify { user.should be_valid }

displays:

1
2
'User should be valid' FAILED
  expected valid? to return true, got false

Nice eh?

Only one expectation per it block

I often see specs where it blocks contain several expectations. This makes your tests harder to read and maintain.

So instead of that…

1
2
3
4
5
6
7
8
describe DemoMan do
  it "should have expected attributes" do
    demo_man = DemoMan.new
    demo_man.should respond_to :name
    demo_man.should respond_to :gender
    demo_man.should respond_to :age
  end
end

… do this:

1
2
3
4
5
6
7
8
9
10
11
describe DemoMan do
  before(:all) do
    @demo_man = DemoMan.new
  end

  subject { @demo_man }

  it { should respond_to :name   }
  it { should respond_to :gender }
  it { should respond_to :age    }
end

(Over)use describe and context

Big specs can be a joy to play with as long as they are ordered and DRY. Use nested describe and context blocks as much as you can, each level adding its own specificity in the before block. To check your specs are well organized, run them in ‘nested’ mode (spec spec/my_spec.rb -cf nested). Using before(:each) in each context and describe blocks will help you set up the environment without repeating yourself. It also enables you to use it {} blocks.

Bad:

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
describe User do

  it "should save when name is not empty" do
    User.new(:name => 'Alex').save.should == true
  end

  it "should not save when name is empty" do
    User.new.save.should == false
  end

  it "should not be valid when name is empty" do
    User.new.should_not be_valid
  end

  it "should be valid when name is not empty" do
    User.new(:name => 'Alex').should be_valid
  end

  it "should give the user a flower when gender is W" do
    User.new(:gender => 'W').present.should be_a Flower
  end

  it "should give the user a iMac when gender is M" do
    User.new(:gender => 'M').present.should be_an IMac
  end
end

Good:

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
describe User do
  before { @user = User.new }

  subject { @user }

  context "when name empty" do
    it { should not be_valid }
    specify { @user.save.should == false }
  end

  context "when name not empty" do
    before { @user.name = 'Sam' }

    it { should be_valid }
    specify { @user.save.should == true }
  end

  describe :present do
    subject { @user.present }

    context "when user is a W" do
      before { @user.gender = 'W' }

      it { should be_a Flower }
    end

    context "when user is a M" do
      before { @user.gender = 'M' }

      it { should be_an IMac }
    end
  end
end

Test Valid, Edge and Invalid cases

This is called Boundary value analysis, it’s simple and it will help you to cover the most important cases. Just split-up method’s input or object’s attributes into valid and invalid partitions and test both of them and there boundaries. A method specification might look like that:

1
2
3
4
5
6
7
8
9
10
describe "#month_in_english(month_id)" do
  context "when valid" do
    it "should return 'January' for 1" # lower boundary
    it "should return 'March' for 3"
    it "should return 'December' for 12" # upper boundary
  context "when invalid" do
    it "should return nil for 0"
    it "should return nil for 13"
  end
end

I hope this will help you improve your specs. Let me know if I missed anything! :)

You could also be interested in (My) Cucumber best practices and tips or rspec-set a little gem that helps you speeding up your model specs.

Migrate Rubygems to Ruby Enterprise Edition (REE)

If you have a server running the default Ruby interpreter (“Matz’s Ruby Interpreter” or “Ruby MRI”) and you want to switch to Ruby Enterprise Edition (REE) the following script will help you migrating the gems.

Once you have installed Ruby Enterprise Edition run this script so that REE installs the gems installed on your default ruby environment.

That’s all folks!

Move Your Ubuntu System to Another Computer in 3 Simple Steps

You just got a brand new machine but you won’t like to spend hours tuning it to get the same configuration as the one you have used for years?

Let’s transfer your Ubuntu configuration and applications to your new computer in three simple steps.

This method is cross-architecture. I moved successfully my configuration and applications from an Ubuntu 9.04 32bit to a 64bit one.

Prerequisites:

The same version of Ubuntu is installed on both machines. The architecture (32/64 bit) can be different.

Step 1: Store the list of installed packages

Run the following command on the source machine to store the installed packages names in ~/pkglist: sudo dpkg --get-selections | sed "s/.*deinstall//" | sed "s/install$//g" > ~/pkglist

Step 2: Transfer your config

Use scp or rsync or even a flash drive to transfer your home directory (~/*, ~/.*), the source list (/etc/apt/sources.list) and any other files you customized or installed (like apache config under /etc or softwares on /opt) from the source machine to the target one.

Step 3: Install packages

On the target machine run the following command in a failsafe terminal session to install your packages:

sudo aptitude update && cat pkglist | xargs sudo aptitude install -y

That’s all folks!

Log into your new machine and keep working as if you were using the previous one.

A freshly transfered Ubuntu install

Jabber-SH — SH Console via XMPP/Jabber (GTalk)

Screenshot-Jabber-SH on GTalk

I’ve just posted the code of Jabber-SH on GitHub. Jabber-SH is a ruby hack that allows you to administrate a remote computer via a command line through a Jabber client. It’s like SSH via GoogleTalk! :)

I coded it nine month ago then I planned to add some specs, to store the configuration in a yaml file, to make a gem out of it but… I didn’t and I won’t get a chance to do that. So here are the 25 lines of code… hackish eh?!

Top-down and Bottom-up Programming Illustrated by Mac OS X and Windows

Bottom-up programming starts by developing the data model before designing the user interface. Windows Start/Programs menu illustrates this approach. Since programs shortcuts are stored in the directory Programs the menu displays the content of this directory.

Windows XP Start menu

Top-down programming starts by designing the user interface before developing the data model. Mac OS X dock illustrates this approach. As it should be easy for a user to launch an application the dock displays big icons accessible in one click.

Mac OS X Dock