Tuesday, May 20, 2014

Automation in Behavior Driven Testing (tips and tricks to enhance code reuse)



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

  1. Organization creation
  2. 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.

3 comments:

  1. You need to reevaluate your test cases, you are suppose to test user and organization creation, it has nothing to do with how the left and top menu is rendered in a page. Menu rendering should be different test cases all together. How does it sound to you if user creation failed because the menu is not rendered correctly, sound's weired?

    ReplyDelete
    Replies
    1. @KaziManzurRashid bhai: Thanks for your comment. You are right that they don't fit in a single scenario. Actually the post was getting bigger. So to reduce space I combined them in a single scenario. I wanted to put emphasis on how to reduces code writing effort. However, I should have mentioned that as readers might get confused. Will keep this in mind in my future posts. And thanks for the suggestion for me and the readers. This makes sense :)

      Delete
  2. For readers, when writing scenarios in BDT, please ensure you keep the scenarios separated. If you combine everything in one scenario then once the test fails, it would be difficult to understand where exactly it went wrong. Moreover, it will be difficult to manage. Therefore, keep them separated. For example, this post is influenced by a real life project. I have following scenarios in “create user.feature” file

    Scenario: Generic verifications
    Scenario: Check required field validations
    Scenario: Successfully create user
    Scenario: Verify duplicate email check

    ReplyDelete