In this post i will demonstrate, how to make our Test Automation framework more maintainable using SpecFlow with Page Object Model. A good way to help pipe your mind is to imagine your SpecFlow feature files as interface to your testing application. i.e. like the User Interface (UI) . Here are some characteristics of a Good UI.

It is Clear, Concise, Familiar, Consistent, Attractive, Efficient, Forgiving.
All these characteristic are self Explanatory.
This is what I Expect our SpecFlow Feature Files and bindings to be. As we have already discussed, our target end users of the feature files do not include just technical people. Non technical audiences including business users and stake holders will also use the feature files. This means, Nothing too Crazy Gets done with SpecFlow.

To achieve the above i will employ an already discussed technique. Possibly the most famous pattern used in Test automation. The Page object model POM. I have already discussed this in detail in my previous post. Nothing changes in how it is implemented with SpecFlow. In-fact, if you have followed my previous tutorial on page objects, you will notice that we can technically just add our SpecFlow feature files and bindings project as another layer. This is because the test code is separated from  the script.

Agenda:

  • Page Object Project
  • SpecFlow Scenario Outline
  • Scenario Outline Implementation

Pre-requisite and Tools:

 

 

Page Object Project

In the previous post, we looked at  the successful login scenario with a single test case. We will be looking at another scenario, unsuccessful login. It will have four different test cases.

Successful Login Scenario steps using the Page Object Model.

Get the Complete Solution from the previous post.

  • First thing we will do is to add a .Net class library project into our solution. we will call it TatAuto.Pages

  • Add the required libraries via nugget package manager 'Selenium.Support' this should also install 'Selenium.Webdriver'.
  • The first step implementation we will convert is the 'When Step Definition'.

Here is where we want to get to.

LoginPObject loginPage = new LoginPObject(_driver);
loginPage.LoginAs(username, password);
  • We will call the class that represents the page and exposes the user actions as LoginPObject.

login page

DashboardPObject dashboardPage = new DashboardPObject(_driver);
Assert.IsTrue(dashboardPage.GetUser().Contains(expectedUser));
  • Secondly, in the 'Then Step Definition' will be asserting a text which will be retrieved via a public method from the DashboardPObject  class.
  • The DashboardPObject  class represents the page we will get to, after a successful login.
  • And then of course we will perform our assertion on this step.

Dashboard page

Now that we know the destination. lets create the two page objects required.

  • Create 2 classes in the Pages project and make them public.
  • LoginPObject.cs and DashboardPObject.cs.
  • In the LoginPObject.cs class, add the following properties and methods
  • In the DashboardPObject add the following properties and methods.
  • Ensure you add reference to the 'TatAuto.Pages' in your 'TatAuto.Bindings' project.
  • Finally, we can modify our step definitions as follow.
  • Do a build and ensure you have started the AUT. Instant wordpress.
  • Re-run the test and you should get a pass.

 

Specflow Scenarios Outline

We will be looking at another scenario. Unsuccessful login with 4 different Test cases. We can do this with peace of mind because all the steps for the four test cases are exactly the same. The only difference is the data being passed in, and the data being retrieved. 

  • The Keyword 'Scenario Outline:' is used instead of 'Scenario'.
  • It is used with 'Example Tables' which in a sense, holds the parameterized values on different rows.
  • A parameter is delimited using two angle brackets '<placeholder>'  syntax.
  • Scenario outline helps reduce the boring job of having to copy paste scenarios to satisfy different test cases.

Unit test method names that gets displayed for example in the test explorer are derived from the scenario outline title and first column of the examples table.

For better trace-ability, i have place a labeling column called 'name' to describe what is being tested.

The Scenario will execute once for each row in the example table.

It will use the relevant data under the matching place holder.e.g.

For the first test Case: Blank Username in the background it will be something like;

As you can see we have Built in Data Driving capability just by using SpecFlow, without writing any code.

Scenario Outline Implementation

A good tip when writing steps for a new scenario is to first check if you have an existing step that can satisfy your need immediately. The Login step from previous scenario uses a  method from the LoginPObject that returns the Dashboard page object.

loginPage.LoginAs(username, password)

Notice we have 4 test cases. which in total requires 12 steps. The beauty is that only 2 steps need to be implemented. SpecFlow helps us reuse them in other test cases with different data.

We do not expect to reach the dashboard with invalid login details. Unsuccessful login will either return an error page or a modified version of the current page. i.e. the login page with errors.

In this instance, we need to implement 2 new steps.  The 'When' and 'Then' Steps.

 [When(@"I Unsucessfully Login with Username '(.*)' and Password '(.*)' on the Login Page")]
 public void WhenIUnsucessfullyLoginWithUsernamePasswordOnTheLoginPage(string username, string password)
 {
            LoginPObject loginPage = new LoginPObject(_driver);
            loginPage.LoginUnsuccessfullyAs(username, password);
 }
 
  [Then(@"I Should See Error Message '(.*)' on the Login Page")]
  public void ThenIShouldSeeErrorMessageOnTheLoginPage(string errorMessage)
  {
            LoginPObject loginPage = new LoginPObject(_driver);
            loginPage.GetErrorMessage();
  }
  • Now the two methods we need to implement in our page objects are:
  • LoginUnsuccessfullyAs(username, password) which returns the current login page ;
  • GetErrorMessage() which returns a string.
  • Your login page should now look as shown.
  • Do a build and make sure your AUT is running.
  • In your Test Explorer you should now have 5 tests.
  • Run the test and you should get greens...

A note: Both the successful and Unsuccessful login methods can return void. You will notice in the case of a successful login, even though we are returning instances of the Dashboard page, we don't get to use it in method chaining context. We will however, ignore that for now.

Conclusion

We have used page objects to separate the code that interacts with the page elements from actual Test Scripts.

Our Feature file is very simple to read and can be understood by basically anyone that understands simple English. (or any other language used in the feature file supported)

We have enjoyed the Data driving capability built into SpecFlow in the form of Scenario outlines with Example tables.

We  have also gained re-usability from both the SpecFlow side in terms of reusing steps in different scenarios. Also, from the implementation side where in our page objects we encapsulated the actual login actions.

This Setup is very Maintainable.  We have the elements of the web page we interacting with all in the same place, defined once. If it ever changes, we just need to edit the locator. The step definition file will not be touched, neither do we need to touch the feature files. On the other hand, if the data input/Output requirement  changes e.g. error message that gets displayed changes, all we need to update is a simple string in the Example table in the feature file.

If we do not update the error message, the test will fail. Once this update is completed it will pass, the changes gets version controlled. this means we have a living documentation.

Completed Files:

Click Here to Download the Complete Working Solution.

References:

Specflow Documentation.

Any thoughts, questions, comments, addition, or anything you don’t like, do not hesitate to leave a comment or contact me. Thank you!

Leave a Reply

Your e-mail address will not be published. Required fields are marked *

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

Show Buttons
Hide Buttons