How Stop Autotest From Running After Each Failed Test Was Fixed

Autotest until recently only had one flaw: it could not be used for large test suites, since after each red-green cycle I had to wait x minutes for all tests to pass, which made autotest really frustrating.

So grep autotest (the ‘without ZenTest version’) from github and enjoy “autotest -c” (also works with auospec).

And remember kids: always run autospec with script/spec_server and its twice the fun ๐Ÿ˜‰

Cucumber vs ActiveRecord 2.3 — Attempt to call private method (NoMethodError)

All of the sudden some columns began to misbehave in cucumber tests, claiming that “Attempt to call private method (NoMethodError)” on normal column attributes!

A simple fix for this, essentially saying that a method is not private when its a column:

#features/support/ar_private_fix.rb required from env.rb
unless ActiveRecord::Base.methods.include?('private_method_defined_with_fix?')
  class ActiveRecord::Base
    class << self
      def private_method_defined_with_fix?(method)
        return false if columns_hash.keys.include?(method.to_s)
        private_method_defined_without_fix?(method)
      end
      alias_method_chain :private_method_defined?, :fix
    end
  end
end

More Cucumber Common Steps and Love

You just have to love this “syntax” ๐Ÿ˜€
Story

#features/discussion.feature
Scenario: I add to an discussion
    Given I am logged in
    And a "Discussion" exists for "Festival" "1"
    And I am on "Festival" "1"
    When I fill in "Text" with "Halloo"
    And I press "Send"
    Then I should be on "Festival" "1"
    And I should see "Halloo"

Steps

#features/step_definitions/common_steps.rb 
# On page/record
Given /^I am on "([^"]*)"$/ do |path|
  visit path
end

Then /^I should be on "([^"]*)"$/ do |path|
  current_path.should == path
end

Given /^I am on "([^"]*)" "([^"]*)"$/ do |model,number|
  visit polymorphic_path(record_from_strings(model,number))
end

Then /^I should be on "([^"]*)" "([^"]*)"$/ do |model,number|
   current_path.should == polymorphic_path(record_from_strings(model,number))
end

# Existing
Given /^a "([^"]*)" exists for "([^"]*)" "([^"]*)"$/ do |associated,model,number|
  record = record_from_strings(model,number)
  record.send(associated.underscore+'=',valid(associated))
  record.save!
end


# Login
Then /^I should be logged in$/ do
  should be_logged_in
end

Given /^I am logged in$/ do
  visit 'login'
  fill_in 'email', :with=>'quentin@example.com'
  fill_in 'password', :with=>'test'
  click_button 'Login'
end


# Support
def current_path
  response.request.request_uri
end

def record_from_strings(model,number)
  model.constantize.find(:first,:offset=>number.to_i-1)
end

env.rb

#features/support/env.rb
#load all fixtures
include AuthenticatedTestHelper #restful_authentification
include ValidAttributes #http://github.com/grosser/valid_attributes

Getting Started with Cucumber on Ubuntu

I finally found some time to mess with cucumber, its pretty nice but has some edges and quircks… but for now i like it ๐Ÿ™‚

Install
This was rather hard… (these libraries and frex should not be necessary for mac)

sudo apt-get install libxslt1-dev libxml2-dev racc
sudo gem install aaronp-frex brynary-webrat
sudo gem install cucumber
./script/generate cucumber
rake features

First story

#features/signup.feature
Feature: Signup
  Scenario: A new user comes to the page and wants to register.
    Given I am on "/"
    When I click "register"
    And I fill in "user[name]" with "Michael G"
    And I fill in "Email" with "test@test.de"
    And I fill in "Password" with "test"
    And I fill in "Password confirmation" with "test"
    And I press "Register for the free basic account"
    Then I should be on "/"
    And I should be logged in
    And I should see a flash about "activation"

Environment setup

#append to features/support/env.rb
#load all fixtures -- https://pragmatig.wordpress.com/2008/12/25/load-all-fixtures-when-not-in-test/
include AuthenticatedTestHelper # restful authentification
include RspecResponseEnhancer # https://pragmatig.wordpress.com/2008/04/20/rspec-responseshould-information-enhancers/

Common steps
There is a nice collection of steps already available in steps/webrat_steps, but some basics where missing….

#features/step_definitions/common_steps.rb
When /^I click "(.*)"$/ do |link|
  click_link(link)
end

When /^I am on "(.*)"$/ do |path|
  header('Accept-Language','EN-en')
  visit path
end

Then /^I should be on "(.*)"$/ do |path|
  response.request.request_uri.should == path
end

Then /^I should see a flash about "(.*)"/ do |message|
  doc.search('div.flash_notice').inner_html.include?(message).should be_true
end

Then /^I should be logged in$/ do
  should be_logged_in
end

def doc
  Hpricot(response.body)
end

Output

 rake features
Feature: Signup  # features/signup.feature
  Scenario: A new user comes to the page and wants to register.  # features/signup.feature:2
    Given I am on "/"                                            # features/step_definitions/common_steps.rb:6
    When I click register                                        # features/step_definitions/common_steps.rb:1
    And I fill in "user[name]" with "Michael G"            # features/step_definitions/webrat_steps.rb:12
    And I fill in "Email" with "test@test.de"                    # features/step_definitions/webrat_steps.rb:12
    And I fill in "Password" with "test"                         # features/step_definitions/webrat_steps.rb:12
    And I fill in "Password confirmation" with "test"            # features/step_definitions/webrat_steps.rb:12
    And I press "Register for the free basic account"            # features/step_definitions/webrat_steps.rb:4
    Then I should be on "/"                                      # features/step_definitions/common_steps.rb:11
    And I should be logged in                                    # features/step_definitions/common_steps.rb:19
    And I should see a flash about "activation"                  # features/step_definitions/common_steps.rb:15

10 steps passed

Feels great to write stories again, sadly takes more time then unit tests, but the readability is superb! IMO a very nice way of doing integration tests…

The Black White Tree Testing Method

snow tree by plain ethos

TDD often is well understood, but seldom put to good use. Spikes grow larger, hard to test aspects are skipped and sooner or later your test coverage looks like this.

.

Therefore i want to show you the Black-White-Tree testing method, which is easy to adopt and results in full C1(path) coverage with easy to maintain, independent tests.

.

.

ice tree by serendipitypeace2007

ice tree by serendipitypeace2007

The principle is simple:

When designing a new method build Black-Box tests for it, often 2-3 are sufficient if they exersice all paths within this method(not necessarily its sub-methods), represented by the trunk and the black branches.

describe :price do
  it "sums prices and applies discounts" do
    Order.new(:items=>items,:discount=>20).price.should == 22.5
  end
  it "costs nothing if it is free" do
    Order.new(:items=>items,:free=>true,:discount=>10).price.should == 0
  end
end

Then write White Box tests, for the public method, mocking everything out with forged return values to verify that every method is called and the call-results are used logically.

describe :price do
  ...
  it "uses sum_price and apply_discount" do
    order = Order.new(:items=>items,:discount=>10)
    order.expects(:sum_prices).returns 100
    order.expects(:apply_discount).with(10,100).returns 20
    order.price.should == 20
  end
end

Then build the method, making all White Box and some of the Black Box tests pass.
Repeat for every sub-method.