The idea of BDD is pretty simple. Write spec in a particular way and then write step definitions that follows the spec. I use Cucumber-JVM for this purpose. My first
reaction to this was, I’m writing too many codes. And it’s time consuming. And as a QA I should be spending more time on
investigating the software and identify
more and more test cases rather than automating few of them. But running automation
test was also an invincible necessity to avoid unwanted surprises. Therefore, I
started writing spec in a way so that I have to code as little as possible. Till
now it’s working pretty well for me. Here is an example of how I do it.
Suppose, I have two similar pages
- Organization creation
- User creation
These 2 pages have similar layout. They have a left menu,
breadcrumb, 2 action buttons and few elements to take input.
Suppose we write spec for create organization page in the
following way:
Feature: Create
organization test
Scenario: Successfully
create organization
Given I go to
create organization page
Then I verify left menu of
create organization page
|item|
|Left Menu 1|
|Left Menu 1.1|
|Left Menu 1.2|
|Left Menu 2|
|Left Menu 2.1|
|Left Menu 2.2|
And I verify breadcrumb of
create organization page
|item|
|Link A|
|Link B|
|Create Organization|
And I give “Random” organization
name
And I select “Financial” as
organization type
And I select “Active” as
organization status
And I click on public checkbox
And I click Save button to save
the organization
And I verify Save successful
message is shown
Now my second step is to write step definitions for those
steps. For example step definition for “Then I verify left menu of create organization page”
will look something similar to the following
Similarly we would have to write step definitions for other steps.
For example, step definition of “And I give organization
name” will
look something similar to the following:
So, the spec contains 9 steps. And I have to write 9 step
definitions for that.
Spec for “Create User” page will look something similar to
the following:
Feature: Create
user test
Scenario: Successfully
create user
Given I go to
create user page
Then I verify left menu of
create organization page
|item|
|Left Menu 1|
|Left Menu 1.1|
|Left Menu 1.2|
|Left Menu 2|
|Left Menu 2.1|
|Left Menu 2.2|
And I verify breadcrumb of
create organization page
|item|
|Link A|
|Link B|
|Create user|
And I give “Hanks” as last name
And I give “Tom”
as first name
And I give “h.t@test.com”
as email
And I give “p123”
as password
And I select “Primary” as user
type
And I click Save button to save
the user
And I verify Save successful
message is shown
Now again I have to write step definitions for the above
steps.
To avoid this, we can modify the above in the following way
Feature: Create
organization test
Scenario: Successfully
create organization
Given I go to page:
“create organization”
Then I verify left menu from xml
|file name|leftmenu.xml|
|parent node|createOrganization|
|child node|element|
And I verify breadcrumb
|item|
|Link A|
|Link B|
|Create Organization|
And I provide input data
|label|element
type|data|
|Organization Name|textbox|Random|
|Type|select|Financial|
|Status|select|Active|
|Public|checkbox|yes|
And I click action button with
title as “Save”
And I verify Save successful
message is shown
Feature: Create
user test
Scenario: Successfully
create user
Given I go to page:
“create user”
Then I verify left menu from xml
|file name|leftmenu.xml|
|parent node|createOrganization|
|child node|element|
And I verify breadcrumb
|item|
|Link A|
|Link B|
|Create user|
And I provide input data
|label|element
type|data|
|Last Name|textbox|Hanks|
|First Name| textbox|Tom|
|Email|textbox|h.t@test.com|
|User Type|select|Primary|
And I click action button with
title as “Save”
And I verify Save successful
message is shown
Here we will have to write 6 step definitions for “Create
Organization” page and 0 step definitions for “Create User” page or any other similar pages as you can
notice that the steps are similar. Here are the tricks:
1. We will maintain a list of URL in XML. This can
look like the following
<url>
<page
name=”create organization”>test.com/createorg</page>
<page
name=”create user”>test.com/createuser</page>
</url>
2. Write a function that can fetch xml data,
provided xml file name and associated nodes.
3. Use the function to navigate to a page, provided their name. So
we can use a single step definition for
a.
Given I go to page:
“create organization”
b.
Given I go to page:
“create user”
The step definition will look
something similar to the following
4. Menu items remain same for similar pages. So it’s
not wise to write them again and again. Therefore, maintain a list of menu
items in xml file and use the function mentioned in step 2 (or a better
function) to fetch menu items data from xml and verify it. So you can use a
single step definition to verify menu items of all pages.
5. Breadcrumbs usually remain in same structure for
all the pages (or most of the pages). Therefore, use a single function to fetch
breadcrumb items and verify it with the provided data table. Suppose breadcrumb appears in HTML in the
following way
You can easily find the elements of the
breadcrumb by
xpath = "//ul[@class='testbreadcrumb']//li"
Then you can write a function that extracts
the text of the elements and verifies it with a data tabe.
Here breadcrumb is just an example. There could
be lots of similar elements that share common structure (id, class, xpath etc.).
You can use this technique.
6. Usually we refer to an element by its locator.
But in most cases all applications follow a similar HTML pattern. If you investigate
then you will notice that you can identify an element by its corresponding
label. For example suppose following is the HTML structure of 'Organization Name' input box
If you notice, you can easily refer to the
input item with id=’Name’ by its corresponding label which is ‘Organization Name’.
We see this label from front end. All you have to do is to find the element by xpath= //label[normalize-space(text())='Organization Name']
The function can look like the following:
So do the followings
a. Write a function that can refer to an element by
its label
b. Write functions for every possible input items
that can send data to the element
c. Write function that takes label, element type
and input data as parameter and send data to the corresponding element.
d. Use the same function to provide data to most of
the create pages. It works for 90% of the input pages. If HTML structure does
not fit for some input elements then write another function for that.
One caution here is that, there could be
more that one element by same label in a single page. In that case you can
further specify the index of the label in parameter of the function.
7. Finally write a function that can identify
buttons by their property. The benefit is you don’t have to look for the locator
and secondly you can use the same function to refer to any buttons. Suppose
HTML structure of action buttons are as follows
So you can easily refer to the <a>
element by text()=’Save’.
Here again the caution is, there could be
more than one action button with same property. So you will have to modify code
so that you can refer to the index along with text.
Finally, it’s not that a single solution fits every problem.
But it’s worth trying something new and being innovative.