ParkCalc automation – BDD style tests

In the comments on one of the previous blog entries in this series, Pekka Klärck pointed out that another great way to refactor a keyword-driven test to a data-driven is the usage of templates within Robot Framework. Before doing this, we will take a look at BDD style tests using given, when, and then. Following an ATDD approach does not make sense for the problem statement given, but I will at least scratch that topic during the reflection.

Some clean-up

Another feedback I got from Dale Emery suggests to extract the xpath entry to identify the costs in the keyword-driven test. So, we edit resource.txt in the data-driven tests to:


...
*** Variables ***
...
${COST_ITEM}     xpath=//tr[td/div[@class='SubHead'] = 'COST']/td/span/font/b

*** Keywords ***
...
Calculated Cost Should Be  [Arguments]  ${expectedCost}
    Click Button  Submit
    ${actualCost} =  Get Text  ${COST_ITEM}
...

Thereby we can override the cost item once the user interface changes with a single change of that variable, or even change the value from the command line via an option while the new user interface is still under development. In a recent talk, Uncle Bob Martin uses the term “extract method until you drop” for good code. I use a similar term for acceptance tests here, but it’s “extract variable until you drop”. Taking a closer look on the resource.txt file now reveals that nearly all the variables are in one tiny place together. Just the title of the Parking Calculator is inline in the keywords, so we extract that one, too.

I will leave the same steps for the resource.txt file in the keyword-driven tests as an exercise to the reader. The resulting repository tree can be found here.

BDD style

Basically the BDD style is similar to keyword-driven tests. Let’s start with an easy one using Valet Parking. First, we create the direct BDD, and edit the valet.txt, similar to the layout we used for keyword-driven tests.

Usually the given, when, and then sections of a BDD style tests reflect the setup, execute, and verify steps of a three-step test. given ensures the preconditions, when executes the system under tests, and then checks the postconditions. Here is the first test, parking for less than five hours, that I came up with:


Less Than Five Hours
    Given I want to use  Valet Parking
    When I park for less then five hours
    Then the calculated Cost Should Be  $ 12.00

Now, we need to evolve the keywords behind this. For the suite setup and teardown I used to open parkcalc and close the browser respectively as before. Now, we need to write the three keyword listed up in the first test together with these. I decide to put them directly into the resource.txt file, which I create for that purpose.



*** Settings ***

Documentation  A resource file containing the ParkCalc app specific keywords and variables for BDD-style tests that create our own domain specific language. Also SeleniumLibrary itself is imported here so that tests only need to import this resource file.

Library        SeleniumLibrary

*** Variables ***

${BROWSER}       firefox
${DELAY}         0
${PARKCALC URL}  http://adam.goucher.ca/parkcalc/
${COST_ITEM}     xpath=//tr[td/div[@class='SubHead'] = 'COST']/td/span/font/b
${PAGE_TITLE}    Parking Calculator

@{FOR_ONE_HOUR}      05/04/2010  12:00  AM  05/04/2010  01:00  AM

*** Keywords ***

Open ParkCalc
    Open Browser  ${PARKCALC URL}  ${BROWSER}
    Set Selenium Speed  ${DELAY}
    Title Should Be  ${PAGE_TITLE}

Given I want to use  [Arguments]  ${lot}
    Select From List  Lot  ${lot}

When I park for less then five hours
    Entry And Exit Dates  @{FOR_ONE_HOUR}

Entry And Exit Dates  [Arguments]  ${entryDate}  ${entryTime}  ${entryAmPm}  ${exitDate}  ${exitTime}  ${exitAmPm}
    Input Text  EntryTime  ${entryTime}
    Select Radio Button  EntryTimeAMPM  ${entryAmPm}
    Input Text  EntryDate  ${entryDate}
    Input Text  ExitTime  ${exitTime}
    Select Radio Button  ExitTimeAMPM  ${exitAmPm}
    Input Text  ExitDate  ${exitDate}
    Click Button  Submit

Then the calculated costs should be  [Arguments]  ${cost}
    ${actual} =  Get Text  ${COST_ITEM}
    Log  Actual costs: ${actual}
    Page Should Contain  ${cost}

Running the tests, I can see that they pass. Check-in time. Here is the source for that.

Now, you may have noticed that I reused the parking durations as defined in the data-driven tests together with a mixture inspired from the keyword-driven tests. That is quite natural for a BDD-style test.

Continuing as before, I create similar tests in the same manner, thereby developing first the valet parking tests. While doing so, I notice that I could add some parameters to the keywords with the when prefix thereby getting rid of the duplication completely. This couples the duration variables more to the tests, but I feel that I may reuse them in other tests later, so I leave the durations in the resource file. Here are the final valet parking test cases:


Less Than Five Hours
    Given I want to use  Valet Parking
    When I park  @{FOR_ONE_HOUR}
    Then the calculated costs should be  $ 12.00

Exactly Five Hours
    Given I want to use  Valet Parking
    When I park  @{FOR_FIVE_HOURS}
    Then the calculated costs should be  $ 12.00

More Than Five Hours
    Given I want to use  Valet Parking
    When I park  @{FOR_SIX_HOURS}
    Then the calculated costs should be  $ 18.00

Multiple Days
    Given I want to use  Valet Parking
    When I park  @{FOR_FOUR_DAYS}
    Then the calculated costs should be  $ 72.00

and this is the resulting resource.txt content


*** Variables ***
...

@{FOR_ONE_HOUR}      05/04/2010  12:00  AM  05/04/2010  01:00  AM
@{FOR_FIVE_HOURS}    05/04/2010  12:00  AM  05/04/2010  05:00  AM
@{FOR_SIX_HOURS}     05/04/2010  12:00  AM  05/04/2010  06:00  AM

@{FOR_FOUR_DAYS}     05/04/2010  12:00  AM  05/08/2010  12:00  AM

*** Keywords ***

Open ParkCalc
    Open Browser  ${PARKCALC URL}  ${BROWSER}
    Set Selenium Speed  ${DELAY}
    Title Should Be  ${PAGE_TITLE}

Given I want to use  [Arguments]  ${lot}
    Select From List  Lot  ${lot}

When I park  [Arguments]  ${entryDate}  ${entryTime}  ${entryAmPm}  ${exitDate}  ${exitTime}  ${exitAmPm}
    Input Text  EntryTime  ${entryTime}
    Select Radio Button  EntryTimeAMPM  ${entryAmPm}
    Input Text  EntryDate  ${entryDate}
    Input Text  ExitTime  ${exitTime}
    Select Radio Button  ExitTimeAMPM  ${exitAmPm}
    Input Text  ExitDate  ${exitDate}
    Click Button  Submit

Then the calculated costs should be  [Arguments]  ${cost}
    ${actual} =  Get Text  ${COST_ITEM}
    Log  Actual costs: ${actual}
    Page Should Contain  ${cost}

Running the tests, I can see that it’s time to check them in again. Here is the resulting tree.

Finally, I can continue to work on the other four parking lots in the same manner. This leads me further to this tree in the source repository.

  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Twitter
  • LinkedIn
  • Google Bookmarks

One thought on “ParkCalc automation – BDD style tests”

Leave a Reply

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