✓ I'm available for hire! Check out my open source work on Github or drop me an email

Douglas F Shearer

Posts Tagged with testing

There are 3 matching posts.

Integrity Git post-receive Hook

I host a few of my repositories myself, rather than on GitHub. As a result I can’t take advantage of their marvelous post-commit hook support. Instead, when it comes to informing Integrity of new commits, I have to use a custom Git post-commit hook.

Use the following in /path/to/repo/.git/hooks/post-receive changing the login credentials, URL, and project name as necessary. Make sure the script is executable.

#!/bin/sh

# Username and password not needed if publicly accessible.
curl -d '' http://USERNAME:PASSWORD@example.com/PROJECT_NAME/builds

echo "\n\n=========="
echo "  Received push and alerted Integrity"
echo "==========\n\n"

Now whenever I push to the remote repo, Integrity is informed and grabs all the new commits to run the test suite against them. This could also work as a post-commit hook, if your Integrity CI server pulls from your local working repository.

 
 

Testing Custom Rails Validations with Shoulda

In this post, I’ll show how to write custom validations for Rails’ models, and how to test them with Shoulda, the ‘Makes tests easy on the fingers and the eyes’ testing plugin.

Rails’ ActiveRecord validations are great when you want to make sure attributes are the way you want them. But what about the use-cases where you need to write a custom one?

Creating the Validation

The validation we’ll write is called validates_positive_or_zero, which will return an error if a relevant integer attribute is negative.

Create the file RAILS_ROOT/lib/validations.rb with the following contents:

def validates_positive_or_zero(*attr_names)
  # Set the default error message.
  configuration = { :message => "Cannot be negative" }
  
  # Set a custom error message if there is one.
  configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
  
  # Check none of the object's attributes are negative.
  validates_each attr_names do |obj, atr, val| obj.errors.add(atr, configuration[:message]) if val < 0 end
end

Note: This particular validation is complementary to validates_numericality_of, you’ll get some odd failures if you don’t use it.

We need to require this file before we can use the new validation in our model:

class Badger < ActiveRecord::Base
  require 'validations'
  
  validates_numericality_of :age, :height, :weight
  validates_positive_or_zero :age, :height
  validates_positive_or_zero :weight, :message => 'no-one is that light'
end

The first validates_positive_or_zero validates two attributes at once, whereas the second validates only one attribute with a custom error message.

Testing the Validation

I feel I should give a little introduction to Shoulda, it’s one of those tools that leaves me wondering how I ever managed before. Despite the popularity of RSpec within the Ruby community, I’m not a fan, it’s just too verbose, which I find gets in the way (it doesn’t render views though, which makes functional testing a lot easier, this feature for standard Rails tests please!). Shoulda is the answer for those of us who want standard Rails tests, but with them being neater and tidier. I encourage you to check it out more fully, but for this example, I’ll stay on-subject.

For our custom validation we could test it in the regular fashion with a test_foo method, or we could write a custom method that we could use again and again without re-writing the same code. The latter is the approach we are going to take here, with the method being in the style of the other shoulda validation tests.

First up, install the Shoulda plugin:

./script/plugin install git://github.com/thoughtbot/shoulda.git

Next, create the file RAILS_ROOT/test/shoulda_macros/validations.rb with the following contents:

class Test::Unit::TestCase
  
  def self.should_only_allow_positive_or_zero_values_for(*attributes)
    configuration = { :message => "Cannot be negative" }
    configuration.update(attributes.pop) if attributes.last.is_a?(Hash)
    klass = model_class
    attributes.each do |attribute|
      attribute = attribute.to_sym
      should "only allow positive or zero values for #{attribute}" do
        assert_bad_value(klass, attribute, -1, configuration[:message])
      end
    end
  end
  
  private
  
  # Taken from the shoulda private methods
  def model_class
    self.name.gsub(/Test$/, '').constantize
  end
  
end

Now we set up our tests in RAILS_ROOT/test/units/badger_test.rb:

require 'test_helper'

class BadgerTest < Test::Unit::TestCase
  
  # This method is provided by Shoulda.
  should_only_allow_numeric_values_for :age, :height, :weight
  
  should_only_allow_positive_or_zero_values_for :age, :height 
  should_only_allow_positive_or_zero_values_for :weight, :message => 'no-one is that light'
  
end

And we’re done! I hope this was useful for you.

 
 

Mocking User_Agent In Rails Tests

Sometimes you may want to check the user agent of a request in your Rails controller, be this for checking for spam, or only allowing services such as Feedburner to access your RSS feeds. Something like this:


def feed
  if request.user_agent !~"Feedburner"
    # redirect to feedburner
  else
    # display feed
  end
end

So what happens when you try to test this using the standard Rails functional tests? You should see an error something like the following:


ActionView::TemplateError: undefined method `user_agent' for
 #<ActionController::TestRequest:0xb69d9b88>

Not so good. The solution is to add the following module to your app. I chose to add it in the same file as the appropriate controller, after the end statement for the class:


module ActionController
  class TestRequest < AbstractRequest
    attr_accessor :user_agent
  end
end

Now your tests should run fine, and you can even set the user agent as you wish in your tests:


def test_access_allowed_to_feedburner
  @request.user_agent = 'Feedburner'
  get :feed
  assert_response :success
end

Hope this helps you out.