This post relates to my short talk at the Agile Testing Days in Potsdam, Germany 2012.
Earlier this year I tweeted this (there’s another blog post about this as well):
Automating tests/checks, seems more valuable than having automated tests—like planning being more valuable than having the plan.
In my case the automating certainly led to other interesting results — and that’s the topic of this post.
Some context
Let’s assume we’re using Cucumber to automate tests for some application and follow the typical Cucumber setup: A folder features containing the feature files and inside of that another folder (step_definitions) containing, well, the step definitions. A support folder inside the feature directory keeps supporting files, such as environment configuration(s) etc.
Keeping it clean
The way I started to work is to start simple: At first I put everything inside the step definitions. Pretty soon though, I extract code chunks into methods of their own. And then move those method definitions into their own class (or module) – an in fact a file of their own.
That way, I end up with two more levels of abstraction below the feature descriptions and the step definitions: Classes (or modules) containing method definitions (see picture).

Here I follow Uncle Bob Martin‘s advice of “Extract till you drop” (see his book ‘Clean Code‘, and episode 3 (Functions) of the video series at cleancoders.com): Extract methods until there’s nothing left to extract (and extract that code into the right place).
A first result: A high level interface to the system
One of the results of doing this, is a really high level and clean API to the system at hand. In addition to that I find that step definitions are much easier to understand, since they (mostly) contain a business level description of how the system is used and accompanying assertions to check whether the system behaves as it should.
Enter Pry
Pry is a command line tool for Ruby, like the interactive ruby shell irb that comes with Ruby. However, Pry is a lot more powerful and offers to display method definitions (even those defined in the C sources of internal Ruby classes) and a whole lot more. For a good introduction see the Pry Screencast by Josh Cheek on vimeo.
A trivial and contrived example
Let’s assume we’re trying to find stuff on the web (I’m on a Mac; there are hints about how to achieve this on Windows in the code comments):
require 'safariwatir' # Windows: require 'watir'
class GoogleSearch
def initialize
@browser = Watir::Safari.new # Win: Watir::Browser.new
end
def search_for search_term
@browser.goto 'http://wellknown-search-engine.example.com/'
@browser.text_field( :name, 'q' ).set search_term
@browser.button( :id, 'gbqfb' ).click
@browser.ol( :id, 'rso' ).links.map(&:text)
end
end
Given that interface and Ppy, the creation of a console app borders on being trivial (yet, it took me a long while to get to this point):
require_relative 'google_search'
require 'pry'
GoogleSearch.new.pry
Think about this for a moment: Take Pry and your API and in 3 lines of code you get a console app for your system. The console can be used like this:
[10] stephan@nibur … #ruby google_search_console.rb
[1] pry(#<GoogleSearch>):1> search_for 'pry video josh'
=> ['Pry Screencast on Vimeo',
# ...
As mentioned above, you can even display the method definition (including lines of code, file name etc.)
[8] pry(<GoogleSearch>)> show-method search_for
From: /Users/stephan/…/google_search.rb @ line 8:
Number of lines: 6
Owner: GoogleSearch
Visibility: public
def search_for search_term
@browser.goto 'http://google.de/'
@browser.text_field( :name, 'q' ).set search_term
@browser.button( :id, 'gbqfb' ).click
@browser.ol( :id, 'rso' ).links.map(&amp;amp;:text)
end
[9] pry(#&amp;lt;GoogleSearch&amp;gt;)&amp;gt;…
Leaving thoughts
It seems that doing something can be more valuable that having the result. Notwithstanding, we still need to produce something of value for our business.
I came to realise that clean code matters more than ‘only’ providing a code base that’s easy to understand and change: Without the high level API, I might not even have noticed the possibility to create a ‘business level console’.
Having a console app like this allows to prepare starting points for exploratory testing (that might be ‘automation assisted exploring). Or short: I think a clean and high-level interface plus Pry is a cool tool for exploration.
Like this:
Like Loading...