A day in the life of an acceptance tester

I am a tester on the Extremely Cheezy team. Our team is building a revolutionary new online bookstore application called depot. It is Friday afternoon and our new Iteration begins on Monday. The user-facing portion of the application is nearly finished. All that remains is the checkout page. This is my story.

Starting the Feature

I walk over and sit down beside the product owner to discuss the checkout page. There is no need to schedule a meeting since we are all sitting in an open space collaborating continuously. She begins the conversation.

PO: I’ve been working with Kimberly (the UX girl) on the screen mockup. Here it is.

Me: Very nice. Let’s take a look at the story you have started.

Feature: Checking out after you complete your order

  As an online book buyer
  I need to provide my personal information
  so that the website can process my order

Me: This is a good start. What can you tell me about the details of this page?
PO: Well, all of the fields must be filled in before we can process the order.
Me: Okay. So all fields are required. What should happen if the user leaves one of the fields blank?
PO: Well I guess they should get a message informing them that the field cannot be blank.
Me: Good. What are the possible values for the Pay with field?
PO: We only handle Checks, Credit cards, and Purchase orders.
Me: That’s good to know. What should happen when the user completes all of the fields and places the order?
PO: The user should get a message thanking them for their order.
Me: Is there anything else I should know about this page?
PO: Not that I can think of right now.
Me: I think we have enough to get started. Let’s start writing the first version of the acceptance tests.

With my PO still watching, I open RubyMine and create a new feature file. I type the story info and a few notes to myself.

Feature: Checking out after you complete your order

  As an online book buyer
  I need to provide my personal information
  so that the website can process my order

All fields are required.
Should display error message when fields are left blank.
Pay with should include Check, Credit card, and Purchase order.
Should display thank you message when order is complete.

The Scenarios Please?

We really need to capture some of the details about the story in the form of Scenarios so the developer will know what to deliver when they pick up the story on Monday.

Me: Let’s write the scenario that describes what should happen when they fill in all of the fields on this page.
PO: OK. Remember it should display a thank-you message.

I write the following Scenario:

Scenario: filling in all fields
  Given I am on the depot site
  When I purchase a book
  And I complete the order with:
    | name      | address         | email           | pay_type    |
    | Sam Smith | 123 Main Street | sam@example.com | Credit card |
  Then I should see "Thank you for your order"

Me: What do you think of this?
PO: It’s good. I think the message is fine but I might want to change it once I talk to Jared. You know he always has an opinion on those things.
Me: That’s no problem. We can easily change them later. Now let me take a shot at writing the Scenarios for the required fields.

I start by writing the first Scenario for the required fields and show it to the product owner. She says this is exactly what she expected:

Scenario: Name is required
  Given I am on the depot site
  When I purchase a book
  And I complete the order leaving the "Name" field blank
  Then I should see an error message with "Name can't be blank"

So I continue to write Scenarios for the other required fields on the page. While I write these Scenarios I see some duplication in my steps. At first I pull the first two steps out of the Scenarios and place them in a Background but I soon realize that this takes away from the expressiveness of the Scenarios. I settle on just moving the first step to the Background.

I look back at my notes I placed in the Feature and realize that all that remains is to define what belongs in the Pay with field. I write one final Scenario.

Scenario: Options for Pay with
  When I purchase a book
  And go to the checkout page
  Then the Pay with dropdown should contain "Check"
  And the Pay with dropdown should contain "Credit card"
  And the Pay with dropdown should contain "Purchase order"

The product owner and I feel good about the acceptance tests. I spend the remainder of the day performing exploratory testing on a story from the current iteration.

Monday comes around

First thing Monday morning we have our Show-and-Tell. The product owner feels good about the progress we are making on the site and she heaps praise on the team. Next comes the Iteration Close, Retrospective, and Iteration Open. All of these meetings take about an hour so I am ready for my next coffee when they are over.

At the coffee pot I run into Joseph. He lets me know he intends to pick up the Checkout story when he gets back to his desk and wonders if I have time to perform one final review of the Scenarios. I tell him I do. Back at the team space a conversation begins.

Me: Let’s read over the Scenarios together one final time before we begin coding.

After reading all of the Scenarios together, Joseph has no questions and is ready to get started. If he would have come up with other Scenarios they would have been added now. Joseph starts coding and it is time for me to begin automating the Scenarios, but first of all I place the tags at the top of the Feature file and check in everything I have so far.

Here is my completed Feature:

@NR @I_4
Feature: Checking out after you complete your order
  As an online book buyer
  I need to provide my personal information
  so that the website can process my order

  Background:
    Given I am on the depot site

  Scenario: Filling in all fields
    When I purchase a book
    And I complete the order with:
    | name      | address          | email           | pay_type    |
    | Sam Smith | 1213 Main Street | sam@example.com | Credit card |
    Then I should see "Thank you for your order"

  Scenario: Name is required
    When I purchase a book
    And I complete the order leaving the "Name" field blank
    Then I should see an error message with "Name can't be blank"

  Scenario: Address is required
    When I purchase a book
    And I complete the order leaving the "Address" field blank
    Then I should see an error message with "Address can't be blank"

  Scenario: Email is required
    When I purchase a book
    And I complete the order leaving the "Email" field blank
    Then I should see an error message with "Email can't be blank"

  Scenario: Options for Pay with
    When I purchase a book
    And go to the checkout page
    Then the Pay with dropdown should contain "Check"
    And the Pay with dropdown should contain "Credit card"
    And the Pay with dropdown should contain "Purchase order"

Let’s create the page object

Since I have the screen mockup from Kimberly I can create the initial page object fairly quickly. All I need to do is create a new class, identify the elements on the screen with WatirHelper, and create my initialize method so I can pass the @browser variable. I write the following in about five minutes:

class CheckoutPage
  include WatirHelper

  text_field(:name, :id => 'order_name')
  text_field(:address, :id => 'order_address')
  text_field(:email, :id => 'order_email')
  select_list(:pay_type, :id => 'order_pay_type')
  button(:place_order, :value => 'Place Order')

  def initialize(browser)
    @browser = browser
  end
end

This is good enough for right now. I’ll enhance the class when I really know what my step definitions need.

Writing the Step Definitions

I let RubyMine generate the shell for the step definitions for me. Since I have been working at this for a while I only have to implement six methods. I go ahead and write the steps as I think they should be implemented. This forces me to add a complete_order method to my page helper. Here are the step definitions:

Given /^I am on the depot site$/ do
  @catalog = CatalogPage.new(@browser)
  @catalog.visit
end

When /^I complete the order with:$/ do |table|
  @checkout_page = @shopping_cart.goto_checkout_page
  @checkout_page.complete_order(table.hashes.first)
end

When /^I complete the order leaving the "([^\"]*)" field blank$/ do |field|
  @checkout_page = @shopping_cart.goto_checkout_page
  @checkout_page.complete_order(field.downcase => "")
end

Then /^I should see an error message with "([^\"]*)"$/ do |message|
  @checkout_page.content.should include message
end

When /^go to the checkout page$/ do
  @checkout_page = @shopping_cart.goto_checkout_page
end

Then /^the Pay with dropdown should contain "([^\"]*)"$/ do |value|
  @checkout_page.pay_type_select_list.options.should include value
end

Completing the page object

Now that I have my step definitions complete it is time to round out the checkout page object. The first thing I do is add some default data.

With this in place I am able to add my complete_order method. This method takes an empty hash as a default parameter so it can be called without passing anything. Then it merges the hash parameter with the default data. Finally it sets the values on the page. Here is the complete source:

class CheckoutPage
  include WatirHelper

  DEFAULT_DATA = {
    'name' => 'Cheezy',
    'address' => '123 Main Street',
    'email' => 'cheezy@example.com',
    'pay_type' => 'Check'
  }

  text_field(:name, :id => 'order_name')
  text_field(:address, :id => 'order_address')
  text_field(:email, :id => 'order_email')
  select_list(:pay_type, :id => 'order_pay_type')
  button(:place_order, :value => 'Place Order')

  def initialize(browser)
    @browser = browser
  end

  def complete_order(data={})
    data = DEFAULT_DATA.merge(data)
    self.name = data['name']
    self.address = data['address']
    self.email = data['email']
    self.pay_type = data['pay_type']
    place_order
  end
end

When I am finished I check everything into source control and let Joseph the developer know all of the automation is complete.

Finishing the story

Joseph runs the acceptance tests periodically while developing the application. When he believes he is finished he calls me over.

Dev: The story is finally finished.
Me: Great. Let’s run the cucumber feature then.

Joseph runs cucumber on his computer and I see all of the acceptance tests run successfully. I then tell him it is Okay to remove the @NR tag in the feature file and check it in at the same time he checks in his last code. This triggers these tests to run as part of the continuous build.

At this time the story is considered functionally complete.

8 thoughts on “A day in the life of an acceptance tester

  1. Pingback: Tweets that mention New blog post - A day in the life of an acceptance tester - -- Topsy.com

  2. Pingback: Acceptance Test Driven Development for Windows « Stephan Schwab

  3. Having a good chunk of syntax to crib helped tremendously as I wrote my first (realistic) cucumber tests today.

    Hopefully I can convince the team lead to switch out of java/selenium into cucumber/page object/selenium.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>