21 August 2012

Cucumber Variables in Tests and using "Examples"

Back in my posts long ago, I had mentioned something about GEB tests using the Where clause.  The where clause added a table of data in the test, that the test would iterate through.

Similarly in Cucumber, it's called Examples, and it's invoked using a Scenario Outline.  A basic Cucumber test has a Feature, which has a Scenario, which has steps. 

In a case where you want to run different values, you would use a Scenario Outline.  This works like this:

Feature: Cross Browser use
     Scenario Outline: Users hit the same site in multiple browsers
          Given a user goes to www.whatsmybrowser.com in "<browser>"
          When they click the check my browser button
          Then the output on the screen should be "<output>"

     Examples:
          | browser | output  |
          | ff           | firefox  |
          | ie           | IE         |
          |chrome   | Chrome|

By doing this, we allow the BDD test itself to select the variables for browser and output.  This way several iterations of the test could be run against one test. 

Video of Cucumber Test Running



20 August 2012

Test Cleanliness - GEB vs Cucumber

Look how clean the BDD portion of the cucumber tests are, compared to something like GEB:

Cucumber:
Feature: User searches for book on Amazon.com
  Scenario: User searches for the book Cucumber
    Given a user goes to Amazon.com
    When they input the title Cucumber in the Amazon search field
    And they click submit
    Then  they should see a results list with Cucumber in the title

   Scenario: Amazon user adds The Cucumber Book to their shopping cart
     Given an Amazon user who has selected the Cucumber book
     When they click add to cart
     Then the book is added to their shopping cart

GEB:
 given: "a newly registered user"
            user = newUser(GENDER, USER_DETAILS, [country: cy, postalCode: postalC])
            def locales = [us: "US", aa: "Austrailia", gb: "England", ca: "Cananda", gr: "Germany"]
            getBrowser().reportGroup(getBrowser().reportGroup + "/" + locales[cy] + "/" + pMethod)

        when: "he attempts to purchase product #1"
            login()
            productAd.click()
            sleep 500
            $("input#prod_price").click(ProdPage)
            $("input.agree-accept").click(BillingPage)
            submitBillingInfo(paymentMethod)
                    .confirmPurchase()
                    .completeProductFlow()

...man, that's a lot of ubly BDD code, lets just stop there.  Each of those calls goes to a class or page, that has all the core functions.  So you're looking at lots of code and ugly BDD tests with GEB.

While GEB is readable, it's messy.  Consider Cucumber and how clean it is.  In Cucumber all the real code is in the step_definitions.  It makes the BDD tests so nice to see and read. 

15 August 2012

Cucumber set up and sample test

Compared to the time I spent getting GEB up and running and getting tests working... Cucumber is so much easier.

Here's how I set up Cucumber
First, I edited the Gemfile for a project and added this group:

group :test, :development do
  gem 'cucumber-rails'
  gem 'database_cleaner'
  gem 'rspec'
  gem 'spork'
  gem 'watir-webdriver'
end

Once done, I run at the project root:
bundle install

It pulls down the gems needed - in this case, I'm mainly using cucumber-rails and watir-webdriver.

After the install, I run a rails generator call to set up cucumber from the project root:
rails generate cucumber:install

This will create a features folder... it's layout will be like this:
features
  |
  |--step_definitions
  |--support

At the root of the features folder, I put my BDD test.  This is where you define the goals... you can think of it as the high level "Given When Thens."  What's cool about Cucumber, is that the NO code goes in this file, it's simple.  In GEB, or groovy frameworks, simple code goes in the BDD tests.  But in Cucumber, NOTHING but the BDD goes there. 

The BDD Test

In my test, I wrote the following in a ruby file at the root here:
Feature: User searches for book on Amazon.com
  Scenario: User searches for the book Cucumber
    Given a user goes to Amazon.com
    When they input the title Cucumber in the Amazon search field
    And they click submit
    Then  they should see a resuls list with Cucumber in the title

So the directory looks like:
features
  |
  |--step_definitions
  |--support
  amazon_test.rb

If you were to run the command "cucumber" now, it would return back a statement that there are no step definitions.  Which is true, there aren't.  The step definitions is the code that makes this test work.  Right now, it just has the BDD language, but no code.

The Step Definitions
So lets create the amazon_test.rb ruby file... in there I use Watir-webdriver to power the browser... and I use Cucumber to write the Given When Thens'.  Here's my file's contents:
Given /^a user goes to Amazon.com$/ do
  @browser = Watir::Browser.new(:ff)
  @browser.goto "http://www.amazon.com"
  @browser.title
end

When /^they input the title Cucumber in the Amazon search field$/ do
  @browser.text_field(:name => "field-keywords").set "Cucumber"
end

And /^they click submit$/ do
  @browser.button(:class => "nav-submit-input").click
end

Then /^they should see a resuls list with Cucumber in the title$/ do
  @browser.h1(:id => "breadCrumb") == "Cucumber"
  @browser.close
end

Now if we run "cucumber" - it will execute each scenario in the test and each part of the test.  If it fails to get a value for any of the steps, it will return the error in the console.  If you have a ANSI color coded terminal you'll get results in a nice color coding.

Breaking the Code Down
First line defines the browser I'm using. In this case it's Firefox.

After that I tell it where to go, in this case www.amazon.com

Next I'm finding the main search field on Amazon ("field-keywords") - I'm searching for the name on the field.  It would be better to search by ID, but I'm going for a field name search.  In the same line, I'm passing the value of "cucumber" into the field.

Next I find the submit button and click it.

Then I find the breadcrumb on the page, and verify the value is "Cucumber"

Finally I close the browser to end the test.

Rails Webapp: WoW Lookup

I've been busy with a family situation.  But in my downtime, late at night, I've been learning and writing code.  I came up with a web application that I created in Rails.

Below I'll provide a summary of what the webapp does, and then a step through of the program.

The program itself is housed at:
https://github.com/wbwarnerb/wowlookup

You can see this in action at my Heroku publish point:

What it does:
I wrote a web application to test some items I learned. The application ties to a public available API from World of Warcraft.  The API I'm talking to is a Quest API.  It's a simple REST call, that needs a ID appended to the URL.  World of Warcraft responds with JSON.  I convert the JSON into a hash, and then finally output specific elements of the HASH to a results view.

Step Through:
I modified the routes file to point the app to search#index.
From search#index, a view is presented with a very simple form.  The form has only one text field, and a submit button.
When a number is input into the field and a user submits, the number is added as a parameter to the URL being called to World of Warcraft:
This is the WoW URL:
http://us.battle.net/api/wow/quest/
Adding a number to the end, will call the WoW database for quest info for that quest id.

I make this call, and associate it to a instanced variable in the controller, like this:
@output = JSON.parse(open("http://us.battle.net/api/wow/quest/"+params[:qid]).read)

The instanced variable is @output.  The code: JSON.parse is going to parse the results of the URL we're calling.  Next the code opens a URL, and I'm passing the ID the user input in the text field with: +params[:qid].  the .read at the end, is just the return of the value.

The data that returns, has some useful info and some not so useful.  I take the hash that's returned from World of Warcraft (it looks like this:
{"id":9877,"title":"A Restorative Draught","reqLevel":17,"suggestedPartyMembers":0,"category":"Ghostlands","level":20})
and I create a results view.  In the results view I added:
<%= @output['title'] %>
<%= @output['level'] %>
<%= @output['suggestedPartyMembers'] %>
<%= @output['category'] %> 

At the bottom of the results view, I added a link to go back to the search page:
<%= link_to("Go back to Search", { :controller => "search", :action => "index" }) %>

 The code to go back is simple enough. It's just saying Link this text "Go back to Search" with a link to the controller (search) and action (index) - which looks like "/search#index"
 
 

11 August 2012

git fetch vs. git pull

When wanting to overwrite local files, I found using git fetch is the answer.

It has to be followed by:
git reset --hard origin/master


09 August 2012

First Webapp

During my lunch break today, I opened up Ruby on Rails Tutorial and walked through setting up another first time app.

So this is my 2nd app i'm working on.  I wanted to actually do something... so I decided to get something simple going and publish via Heroku.

So what's Heroku?
Heroku is this awesome cloud service, that's free, if  you're just testing your apps.  you go to heroku.com and set up an account... then you run a rails gem like: gem install heroku
and that will install it.

The idea is this:
1. you write some code
2. you commit the code locally with git commit
3. you push the commit to a remote git repo (i.e. github.com)
4. you make a call to Heroku to pick up the git repo and publish it.

I hit a few snags from the book though.  The book didn't tell me I had to change the gem sqlite3.  Heroku doesn't like it. The solution was to go into the Rails Gemfile and do something like this:
group :development, :test do
   gem "sqlite3"
end

If you don't set up a dev group like that, then it tries to compile sqlite3 on Heroku and since it has it's own db structure it will fail and error out (the error would be "an error occurred while installing sqlite3...."

So here's my webapp:
http://peaceful-castle-5270.herokuapp.com/users

Heroku makes a random name for your webapp.  That /users is the code I comitted and published. it allows users to be created based on their email address.

So how did I do it?

Well I cheated somewhat.  I used scaffolding.  In Rails there's a scaffolding option.  It will build out a structure for your application.  All I had to do, was call a Users model with the scaffolding and it built it out...
rails generate scaffold User name:string email:string

That one command did all of this.  It created the User model and set up a name and email variable as a string the user inputs.  It added in all the good stuff.

Once done, you run a rake migrate, like:
bundle exec rake db:migrate

Add this to Git: git add .
Commit with git: git commit -m "something"
Push to github (should have defined this already): git push
If you have created the Heroku space, you run:
heroku create
Publish with Heroku: git push heroku master

You're done.  Go to the url