Creating test data with Calabash

On returning to my old iOS team after a brief stint working on our services team, I wanted to implement what I had learned there and improved the stability of our Calabash scenarios. I wanted to shift away from our dependence on test data stored in config files and databases and create test data at the same time as executing our Calabash scenarios.

The whole process was surprisingly simple and straightforward. We used the “Rest-Client” gem and then called some simple data manager classes by using cucumber’s built-in hooks.

Below is a simple example (based on what we did on our team) of how you can create new accounts/customers by using the “Rest-Client” gem, cucumber hooks, a data manager class and a factory module.

AccountDataManager.rb

require 'rest-client'

require_relative '../factory/account'

class AccountDataManager

  include Account

  def create
    current_time = Time.now.to_i
    username = 'test_acc_' + current_time.to_s
    password = 'password1'
    url = 'http://yourURLhere.com/account/new'

    request_body = manufacture_account(username, password)

    response = RestClient.post url, request_body.to_json, {:content_type => 'application/json', :accept => 'application/json'}

    if response.code != 200
      fail(msg ="POST failed. Response status code was: '#{response.code}'")
    end

    response_body = JSON.parse(response)

    clientId = response_body['Account']['ClientId']

    # return a hash of account details
    account_details = {
        username: username,
        password: password,
        clientId: clientId
    }
  end
end

Account.rb

The below factory manufactures the request’s body.

If you’re concerned about re-using the same test over and over you could use something like Faker to populate your each request payload with unique data.

module Account

  def manufacture_account(username, password)
    payload = {
        address:{
            :Address1 => '2 Main St',
            :Address2 => '',
            :Suburb => 'Sydney',
            :CountryCode => 8,
        },
        personal:{
           :Title => 'Mr',
           :Firstname => 'John',
           :Surname => 'Doe',
           :UserName => "#{username}",
           :Password => "#{password}",
           :Mobile => '0123456789',
           :Email => "#{username}@yopmail.com",
           :DOB => '1990-12-31 00:00:00',
        }
    }
  end
end

Hook.rb

Now you will need to create a hook file (this details what endpoints to call and when to call them). You should add your hook.rb file to a shared directory and then add a reference to it into your env.rb file (we added our hook file to the “/features/support” directory). Cucumber runs everything in the env.rb file first before it starts executing the Calabash scenarios.

As part of our calabash framework, we realised we needed 3 different types of hooks. One to run before any calabash scenarios are executed i.e. an initialization/setup hook, another to run before specifically tagged scenarios and a final a hook to run once all your scenarios finish executing.

require_relative '../data_manager/data_manager_account'

Before() do
  $first_time_setup ||= false

  unless $first_time_setup
    $first_time_setup = true
    
    # call the data managers needed to create test data before
    # any of your calabash scenarios start
  end
end

Before('@login') do
  # declare global variable that can be accessed by step_definition files
  $account_details = AccountDataManager.new.create
end

at_exit do
  # call the data managers to clean up test data
end

Login_steps.rb

The final piece of the jigsaw is to get your calabash scenarios to consume the test data you’ve just generated. To solve this problem we declared a global variable in our hook.rb file and referenced it in our step_definition file.

Given(/^I log in with newly created customer$/) do
  @current_page = @current_page.touch_login_button

  unless @current_page.is_a?(LoginPage)
    raise "Expected Login page, but found #{@current_page}"
  end

  # use global variable declared in hook.rb
  @current_page = @current_page.login($account_details)

  unless @current_page.is_a?(HomePage)
    raise "Expected Home page, but found #{@current_page}"
  end
end
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.