Category Archives: rails

On working with Capybara

I’ve been writing Ruby since 2009 and while TDD as a process has long been clear to me, the morass of testing terminology has not. For a recent project I made pretty significant use of Capybara, and through it, Selenium. While it solved some problems I am not sure I could have solved any other way, it created others and on the way shed some light on some murky terminology.

I think mine was a pretty common pathway to working with Capybara, finding it via Rails and Rspec and an need to do an integration test.

The Rspec equivalent of an integration test is the Request Spec, and its often pointed out that its intended use is API testing, which wasn’t what I was doing. What’s held up as the user focused compliment to request specs are feature specs using Capybara.

The sudden appearance of “the feature” as the focus of these specs, and the brief description of “Acceptance test framework for web applications” at the top of the Capybara Github page should be our first signs that things have shifted a little.

This shift in terminology has implications technically, which are not immediately obvious. The intent of Acceptance testing “is to guarantee that a customers requirements have been met and the system is acceptable“. Importantly, since “Acceptance tests are black box system tests”, this means testing the system from the outside via the UI.

Its this “via the UI” part that should stand out, since its a far cry from the other kinds of tests of tests common with Rails. Uncle Bob has said that testing via the UI “is always a bad idea” and I got a taste of why pretty much right away. Lets take a feature spec like this as an example:

    it "asks for user email" do
      visit '/'
      fill_in "user_email", with: "foo@example.com"
      click_button "user_submit"
      expect(page).to have_content "Thanks for your email!"
    end

Notice that suddenly I am stating expectations about the HTML page contents and looking for and manipulating page elements like forms and buttons.
The code for the user_submit button above would typically look like this in most Rails apps:

<%= f.submit "Submit", :class => "btn snazzy" %>

In Rails 3.0.19 that code would use the User class and the input type to create the id attribute automatically. Our click_button 'user_submit' from above finds the element by id and our test passes:

<input class="btn snazzy" id="user_submit" name="commit" type="submit" value="Submit">

In Rails 3.1.12, the same code outputs this:

<input class="btn snazzy" name="commit" type="submit" value="Submit">

There are patterns like page objects that can reduce the brittleness but testing the UI is something that only really makes sense when the system under test is a black box.

Contrary to the black box assumption of Acceptance tests, Rails integration tests access system internals like cookies, session and the assigns hash as well as asserting specific templates have been rendered. All of that is done via HTTP requests without reliance on clicking UI elements to move between the controllers under test.

Another problem comes from the use of Selenium. By default Capybara uses rack-test as its driver, but adding js: true switches to the javascript driver which defaults to Selenium:

    it "asks for user email", js: true do
      visit '/'
      fill_in "user_email", with: "foo@example.com"
      click_button "user_submit"
      expect(page).to have_content "Thanks for your email!"
    end

The unexpected consequences of this seemingly innocuous option come a month or two later when I try to run my test suite:

     Failure/Error: visit '/'
     Selenium::WebDriver::Error::WebDriverError:
       unable to obtain stable firefox connection in 60 seconds (127.0.0.1:7055)

What happened? Well, my package manager has updated my Firefox version to 26.0, and the selenium-webdriver version specified in my Gemfile.lock is 2.35.1.

Yes, with “js: true” I have made that test dependent on a particular version of Firefox, which is living outside of my version control and gets auto-updated by my package manager every six weeks.

While workarounds like bundle update selenium-webdriver or simply skipping tests tagged with js:true using rspec -t ~js:true are available your default rspec command will always run all the tests. The need to use special options to avoid breakage is unlikely to be remembered/known by future selves/developers, so the solution seems to be keeping some sort of strict separation between your regular test suite and, minimally any test that uses js, or ideally all Acceptance tests. I’m not sure that that might look like yet, but I’m thinking about it.

Acceptance testing differs far more that I initially appreciated from other types of testing, and like most things, when used as intended its pretty fabulous. The unsettling thing in all this was how easy it was to drift into Acceptance testing without explicitly meaning to. Including the Capybara DSL in integration tests certainly blurs the boundaries between two things that are already pretty easily confused. In most other places Capybara’s ostensible raison d’etre seems to be largely glossed over. Matthew Robbins otherwise great book “Application Testing with Capybara“, is not only conspicuously not called “Acceptance testing with Capybara”, it only mentions the words “Acceptance testing” twice.

Cabybara is certainly nice to work with, and being able to translate a clients “when I click here it breaks” almost verbatim into a test is amazing. I feel like I now have a better idea of how to enjoy that upside without the downside.

Factory not registered

I have been working on adding tests to an existing Rails app for one of my clients. The app was written by some well intentioned person who included tonnes of testing libraries but just never got around to writing tests.

group :development, :test do
  gem 'capybara'
  gem 'cucumber'
  gem 'cucumber-rails', :require => false
  gem 'database_cleaner'
  gem 'factory_girl'
  gem 'factory_girl_rails'
  gem 'rspec-core'
  gem 'rspec-expectations'
  gem 'rspec-mocks'
  gem 'rspec'
  gem 'rspec-rails'
  gem 'ZenTest'
end

As I started adding specs I needed to create factories, and when I started to do that I started to get errors. First “Factory already registered” errors and then “Factory not registered” errors. Very annoying.
The root of the problem seems to be that factory_girl_rails and factory_girl both look for factories when loaded. The solution for me was to remove factory_girl and let factory_girl_rails do the right thing.
This triggered a major purge of unneeded gems which left me with a Gemfile that looks like this:

group :development, :test do
  gem 'factory_girl_rails'
  gem 'rspec-rails'
  gem 'capybara'
end

It also left me with passing tests and no further errors.

I think the take away for me here is to let bundler/rubygems dependency management system do the right thing. Over-specifying stuff is a recipe for trouble. Over-specifying stuff in the Gemfile might look like explicitly including factory_girl when it will obviously be a dependency of factory_girl_rails. I’ve also seen problems arise from habitually including version numbers in the Gemfile, which makes things so specific that Bundler no longer has the latitude to figure out something that works.

In any case its a good reminder that less is more.

Another look at creating Rails users in Postgres

Three years (!) has passed since I first wrote about setting up users for your Postgres development database. This does not come up often for me, but every time I see my own list of instructions I shudder and think there must be a better way. This morning I figured it out.

Here is what I have in my config/database.yml:

development:
adapter: postgresql
encoding: unicode
database: myapp_development
pool: 5

Omitting the username and password from the database.yml means that postgres will try to log using your operating system username using the peer method. Since I am logged in as “mike” that is the username that will be used to authenticate. With this in mind I am just going to create a database user with that name.

mike@sleepycat:~/projects/myapp$ sudo -u postgres createuser mike
Shall the new role be a superuser? (y/n) y

Notice that used sudo -u to switch to the existing “postgres” user (created by default) and created a superuser that matched my operating system account username.
After that, everything works. Even rake commands.

mike@sleepycat:~/projects/myapp$ rake db:create
mike@sleepycat:~/projects/myapp$ rake db:migrate
==  CreateWidgets: migrating ============================================
...
mike@sleepycat:~/projects/myapp$ rails dbconsole
psql (9.1.9)
Type "help" for help.

myapp_development=# 

Now that is far more civilized.

Including helper methods in javascript

I’m working on an app and found myself needing set an initial position for a map.
The most reasonable thing seems to be to geocode the IP in the controller and use it in my javascript.
So in my controller I tried creating a method that did what I needed. I figured declaring it as a helper_method and adding a .erb to the file name so it would be preprocessed would be all I would need to do.
For some reason it was not so simple…

If you call in your javascript file you get a decendent of Sprockets::Context. For reasons I don’t understand, Rails helper menthods don’t seem to be included in it.
My need was just to pass in my geocoded lat/long values, and using a gem felt like a little much so created a JsVars module that behaves like a hash and included it in the context class with an initializer:

config/initializers/sprockets_helpers.rb 

Rails.application.assets.context_class.class_eval do
  include AssetMethods
end

My little hash module looks like this:

module AssetMethods
  module JsVars
    @vars = {}

    def self.[]=(k, v)
      @vars[k]=v
    end

    def self.[](k)
      @vars[k].to_json
    end
  end
end

And that lets me do this in my whatever.js.erb:

var test = ;

which comes out as:
var test = {“fizz”:”buzz”};

I think I would have to take a hard look at json escaping if/when I start using that for user supplied data, but for now it fits the bill nicely. While I am happy to have figured out a workable solution, I have a suspicion there was a much easier way to have done it.
For the moment… onwards!

Ruby Redo’s: Sinatra

Sinatra is described as “a DSL for quickly creating web applications” and since I have been playing with DSLs lately I thought I would try my hand at making something like it. You can see in Sinatra’s famous three line “Hello World” that they are calling get directly on the top-level object called main:

require 'sinatra'

get '/hi' do
  "Hello World!"
end

So first thing we know is that we need a Rack compatible class. Why do we know that? Because Rack deals with the webserver/HTTP stuff as long as we follow their interface spec which saves us a lot of fussing with servers. The spec is simple:

A Rack application is a Ruby object (not a class) that responds to call. It takes exactly one argument, the environment and returns an Array of exactly three values: The status, the headers, and the body.

So that actually tells us a fair bit about the class we need to write. As the saying goes, “There are only two hard things in Computer Science: cache invalidation and naming things”, I think I will name this thing HTTP. So here is the minimum to conform with the Rack spec:

class HTTP
  def call env
    [200, {}, ""]
  end
end

If you are curious about what kind of stuff is going to end up in that env variable here is an example:

{
 "SERVER_SOFTWARE"=>"thin 1.5.0 codename Knife",
 "SERVER_NAME"=>"localhost",
 "rack.input"=> StringIO.new(),
 "rack.version"=>[1, 0],
 "errors"=>STDERR,
 "rack.multithread"=>false,
 "rack.multiprocess"=>false,
 "rack.run_once"=>false,
 "REQUEST_METHOD"=>"GET",
 "REQUEST_PATH"=>"/test",
 "PATH_INFO" => "/test",
 "REQUEST_URI"=>"/test",
 "HTTP_VERSION"=>"HTTP/1.1",
 "HTTP_USER_AGENT"=>"curl/7.27.0",
 "HTTP_HOST"=>"localhost:8080",
 "HTTP_ACCEPT"=>"*/*",
 "GATEWTERFACE"=>"CGI/1.2",
 "SERVER_PORT"=>"8080",
 "QUERY_STRING"=>"",
 "SERVER_PROTOCOL"=>"HTTP/1.1",
 "rack.url_scheme"=>"http",
 "SCRIPT_NAME"=>"",
 "REMOTE_ADDR" => "127.0.0.1"
}

Rack actually has a bunch of helpful classes that we are going to use to get thing working, lets add them in:

require 'rack'

class HTTP

  def call env
    request = Rack::Request.new env
    response = Rack::Response.new
    response.write "Hello Whirled"
    response.finish
  end

end

at_exit do
  Rack::Handler.default.run HTTP.new
end

You can see that we now have request (that wraps the environment hash that you can see us passing in) and a response object. Notice that response.finish is the last line of the call method now. This is because it returns the array of status, headers and body that Rack needs. The other thing to notice is that we are using Kernel#at_exit to run whatever Rack decides is the default webserver when the script exits. This actually gives us a working application that you can run like this:

mike@sleepycat:~/play/http$ ruby http.rb
>> Thin web server (v1.5.0 codename Knife)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:8080, CTRL+C to stop

Lets take another step and get that response.write out of there and put it in a Proc. Next, we use instance_eval to evaluate the Proc (which is being turned from a proc object back into a block with the & operator) in the context of the current object. Since the block is being evaluated in the context of the current object and not the context of the current method we need to make request and response instance variables and add some attr_accessor methods. You can see also that we are now storing the routes in a hash of hashes that is held in a class variable so that when we call new, our instance can still see the routes.

require 'rack'

class HTTP

  attr_accessor :request, :response

  @@routes = { get: {"/" => Proc.new {response.write "Hello Whirled"}} }

  def call env
    @request = Rack::Request.new env
    @response = Rack::Response.new
    the_proc = @@routes[:get]["/"]
    instance_eval &the_proc
    response.finish
  end

end

at_exit do
  Rack::Handler.default.run HTTP.new
end

Our next step is creating some way to add methods to that @@routes hash. For that we will create a class method called save_route. We’ll also add some other methods to the hash as well and make sure that if there is no block found for a url that we send back a 404:

require 'rack'

class HTTP

  attr_accessor :response, :request

  @@routes = { get: {}, put: {}, post: {}, delete: {}, patch: {}, head: {} }

  def self.save_route *args
    method, route, block = *args
    @@routes[method.downcase.to_sym][route] = block
  end

  def call env
    puts "Handling request for: #{env["PATH_INFO"]}"
    @request = Rack::Request.new env
    @response = Rack::Response.new
    block = @@routes[request.request_method.downcase.to_sym][request.path_info]
    # if no block is stored for that path; 404!
    block ? instance_eval(&block) : throw_404
    response.finish
  end

  private

  def throw_404
    @response.status = 404
    @response.write "<html>Page Not Found</html>"
  end

end

at_exit do
  Rack::Handler.default.run HTTP.new
end

Now that we can add routes to our class, we need to turn our attention to adding methods to the main object. The methods we want to add are the usual HTTP methods, get, put and whatnot.
We want to define an method for each of them like this:

def get *args, &block
  HTTP.save_route(:get, args.first, block)
end

But since that is kind of repetitive we are going to write some code that writes that code. Often you would use Module#define_method for this but the main object is weird and does not have that method. So I am going to use eval:

require 'rack'

class HTTP
  #... all the HTTP code ...
end

def http_methods
  %w(get put post delete head patch).each do |method_name|
     eval <<-EOMETH
     def #{method_name} *args, &block
       HTTP.save_route(:#{method_name}, args.first, block)
     end
     EOMETH
   end
end

at_exit do
  # ... rack stuff ...
end

Then we need to open the eigenclass of main and attach the methods to that. This is so the methods are available as instance methods of the main object. We can do that with Ruby’s somewhat bizarre syntax:

require 'rack'

class HTTP
  #... all the HTTP code ...
end

def http_methods
  #... all the HTTP code ...
end

class << self
  http_methods
end

at_exit do
  # ... rack stuff ...
end

With that we now have a working toy version of Sinatra. We can use it like this:

require_relative 'http'

get "/" do
  response.status = 200
  response["HTTP-Referrer"] = "Mike"
  response.write "<html>Hello Whirled</html>"
end

When you are working in Rails you often hear about Rack but its not usually something you interact directly with. Playing with this has really made me appreciate Sinatra for the intelligent, concise DSL that it is (which is easy to forget somehow). While playing with DSLs is fun, taking some time to get to know Rack has also really helped my understanding of Rails.

Duck typing in Ruby: thoughts on checking argument types.

It doesn’t take much time in the Ruby world to hear the term duck typing. It wasn’t until I was writing a method for a recent project that was to accept either one or many ids that I actually stopped and actually investigated it. I knew what most people know about it: “If it walks like a duck and quacks like a duck, then it’s a duck” and that in actual practice this means you call call respond_to? to see if a method exists.

But as I was working on the code I found I kept wanting to type object.kind_of?(Array) but since this seemed to clash with the idea of duck typing I thought it was time to investigate a little bit.

The reason the type of an object using #kind_of? is not that useful is that Ruby supports multiple inheritance via the inclusion of modules. Since an object’s methods may have come from either a parent class or an included module, knowing the objects class doesn’t provide much information. If Tiger.new.kind_of?(Felidae) just returned true, is it safe to call the #domesticated? method? Calling #kind_of? just doesn’t help you make that decision.

module Wild
  def domesticated?
    false
  end
end

class Felidae
  def claws?
    true
  end
end

class Tiger < Felidae
  include Wild
end

It seems that there are two schools of thought on duck typing. First, “soft” duck typing. Paraphrasing an example from Dave Thomas’ pickaxe book shows the standard approach:

def some_method param
  if param.respond_to? :<<
    # must be something we can write to!
    param << "a string to be added"
  end
end

The difficulty here is that respond_to? famously fails when you are using method_missing to catch and respond to method calls. The only way to be sure that respond_to? is not deceiving you is to go ahead and call the method. It is this approach that people call “hard” duck typing:

def some_method param
  param << "a string to be added"
end

As Dave explains:

“You don’t need to check the type of the arguments. If they support << (in the case of result) or title and artist (in the case of song), everything will just work. If they don’t, your method will throw an exception anyway (just as it would have done if you’d checked the types). But without the check, your method is suddenly a lot more flexible: you could pass it an array, a string, a file, or any other object that appends using <<, and it would just work.”
— Programming Ruby second edition pg 355 – Dave Thomas

The interesting thing to me here, is the rationale for just calling the method instead of doing something like this:

def some_method param
  begin
    param << "a string to be added"
  rescue NoMethodError => e
    raise ArgumentError, "Needs to support the << method"
  end
end

Constantly wrapping method calls in begin/rescue/end is pretty heinous from any angle; aesthetics, readability or performance. While hard duck-typing might come off as a little cavalier, it’s pretty much assumed in the Ruby community you have a test suite to make sure none of these NoMethod exceptions end up in production.

Another interesting take on the issue is the approach taken by Jeremy Kemper, the top commiter to the Rails framework. With commit 609c1988d2e274b he added the #acts_like? method to Object:

class Object
  # A duck-type assistant method. For example, Active Support extends Date
  # to define an acts_like_date? method, and extends Time to define
  # acts_like_time?. As a result, we can do "x.acts_like?(:time)" and
  # "x.acts_like?(:date)" to do duck-type-safe comparisons, since classes that
  # we want to act like Time simply need to define an acts_like_time? method.
  def acts_like?(duck)
    respond_to? :"acts_like_#{duck}?"
  end
end

and then to each of the core classes in the standard library he added an acts_like_x? method. Here is what the one for Date looks like:

class Date
  # Duck-types as a Date-like class. See Object#acts_like?.
  def acts_like_date?
    true
  end
end

These were added to ActiveSupport back in 2009 but for some reason they don’t seem to be widely used in the codebase. This surprises me because this approach seems to avoid NoMethodErrors without cluttering your code with rescue statements. On top of that it has none of the problems inherent in respond_to?.

I hope that helps people out a little. I know it has helped clarify my thoughts. Just one more reason to go and read the source.

Ruby redo’s: The Rails router

One of the things that Ruby is famous for is the ease with which you can build Domain Specific Languages (DSLs). The routing DSL in Rails is one of the more recognizable features of the framework and a good example of a Ruby DSL. If you’ve worked with Rails at all you have seen this in config/routes.rb:

MyApp::Application.routes.draw do
  match "/foo", to: "foo#bar"
end

I’ve worked with Rails a fair bit and had a pretty good understanding of how to use the DSL but there is always more to be learned by implementing it (or something like it) yourself. So what are we implementing? We want something that behaves like the ActionDispatch Routeset:

[27] pry(main)> Rails.application.routes
=> #<ActionDispatch::Routing::RouteSet:0x0000000232c588>
[28] pry(main)> Rails.application.routes.draw do
[28] pry(main)*   match "/foo", to: "bar#baz", via: :get
[28] pry(main)* end
=> nil

So we can see that it has a draw method that accepts a block. That block contains a call to the method “match” and accepts a string and a hash of arguments. We called the match method in our code block above and passed that block to the draw methods. When match is evaluated it adds the given route to the set of routes for the application. Which means that if we dig into the routes we should find our path we specified (/foo). Sure enough:

[29] pry(main)> Rails.application.routes.router.routes.each{|r| puts r.path.spec};nil;
/assets
/foo(.:format)
/rails/info/properties(.:format)

As with most things in Ruby, its actually surprisingly little code to get such a thing working:

class RouteSet

  def initialize(routes = {})
    @routes = routes
  end

  def match(path, options)
    @routes[path]= options
  end

  def draw(&block)
    instance_eval &block
  end

  def to_s
    puts @routes.inspect
  end

end

We can play with it in Pry:

mike@sleepycat:~/projects/play$ pry -I.
[1] pry(main)> load 'routes.rb'
=> true
[2] pry(main)> routeset = RouteSet.new
{}
=> #<RouteSet:0x1561598>
[3] pry(main)> routeset.draw do
[3] pry(main)*   match "/foo", to: "bar#baz", via: :get
[3] pry(main)* end
=> {:to=>"bar#baz", :via=>:get}
[4] pry(main)> routeset.to_s
{"/foo"=>{:to=>"bar#baz", :via=>:get}}
=> nil

The secret DSL sauce is all in the draw method. Notice the ampersand in front of the block parameter:

  def draw(&block)
    instance_eval &block
  end

That ampersand operator wraps an incoming block in a Proc and then binds it to a local variable named block. The same operator is used to reverse that process, turning the contents of the block variable from a Proc back into a block. That block is then fed into instance_eval which evaluates the block in the context of the current object. The net effect is the same as if you had just written this:

  def draw
    match "/foo", to: "bar#baz", via: :get
  end

This process of taking a block of code defined somewhere and evaluating it in some other context is the key to DSLs in Ruby. Understanding the ampersand operator and its conversion between blocks and Procs is really important since this is really common in Ruby code. While is may be common, its not cheap. All that “binding to variables” stuff can be slow so in those moments where you care about speed you will want to use this instead:

  def draw
    instance_eval &Proc.new
  end

Playing with this stuff has really helped my understanding of both Ruby and Rails. I hope it helps you too.

Ruby redo’s: IRB

I have come to the realization that the best thing you can do to advance your Rails knowledge is to get better at Ruby. Rails development tends to keep you in one particular corner of the language. To see the other parts you really need to step off Rails’ golden path and try writing something from scratch yourself.

To push myself into some interesting territory I have taken to creating toy implementations of some of the programs I use but have never really understood the internals of. Every time I do this I find I learn something new… sometimes something big, sometimes something small.

One of the small ones actually started with switching from IRB to Pry, and seeing the mind blowing simplicity of Josh Cheek’s example Read Evaluate Print Loop (REPL):

loop do
  puts eval gets
end

When he showed that I nearly fell out of my chair. I’ve been using the Rails console for years now and had never really stopped to consider how it actually did what it does. Obviously IRB is a bit more more involved than a one-liner and a gemspec but this is one of those magic code examples that gets the concept across with searing clarity.

A learning opportunity is not far off either since its not long before you will get the urge to improve it after fat-fingering something and the having it exit. If you don’t know about Ruby’s Exception hierarchy, or like me needed a reminder because you have spent to much time with Rails, try adding some error handling catching the Exception class:

loop do
  begin
    puts eval gets
  rescue Exception => e #Not a good idea!
    puts e.message
  end
end

Of course you will soon realize that you can’t end the program since it turns out that Kernel#abort just calls Kernel#exit and that actually exits the program by raising a SystemExit Error… which we just caught. Oops.
After discovering the joy of Kernel#exit! and doing some reading about the Exception hierarchy (Ahhaa StandardError!) I have to say that redoing even seven lines of IRB taught me a lot.

Sqlite: Failed to build gem native extension

I just stumbled across this error in mid-yak-shave for one of my projects. While trying to get my app up and running to test something I get the usual native extensions whining:

Installing sqlite-ruby (2.2.3) with native extensions
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

/home/mike/.rvm/rubies/ruby-1.9.2-p290/bin/ruby extconf.rb
checking for main() in -lsqlite… no
checking for sqlite.h… no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details. You may need configuration options.

After a you see this sort of thing a few times you pretty instinctively bang out the command:

sudo apt-get install libsqlite3-dev

I was pretty takenaback to get the same error after installing the dev libraries. It turns out that I was installing the gem “sqlite-ruby” when I needed “sqlite3” is what you need if you are using Ruby 1.9.2.

Do or do not. There is no try. Wait, yes there is.

Cruising through Stackoverflow I noticed some syntax that I had never seen before:

@blog.user.try(:username)

Interested, I looked it up. As far as I can tell, it seems that one of the clever folks behind Github posted it as a helpful snippet on his blog.
From there it seems to have made its way into the Rails ActiveSupport library and then into Ruby 1.9 itself. Basically its the same as send except it swallows errors and just returns nil.
An example from the docs:

@person ? @person.name : nil

could be replaced with:

@person.try(:name)

Coolness! I know this will be making its way into my own code shortly. Check out Scott Harvey’s excellent explanation of the try method and also take a look at the documentation here.