Menu
Seligman Ventures Ltd
  • Home
  • About Us
  • Training
  • Blog
  • Privacy Policy
  • Contact Us
  • Home
  • About Us
  • Training
  • Blog
  • Privacy Policy
  • Contact Us

Test Automation - Page Object Model with Gherkin (Appium & Java centered)

12/13/2017

2 Comments

 
Having done both Development & Test Automation for over 10 years now, I realised the focus of this blog has been primarily on development.  Therefore, I thought it would be interesting to cover some Test Automation.  

Gherkin (the human readable coding language used by Cucumber) is becoming increasingly popular as more companies embrace Behaviour Driven Development (BDD).  The Page Object Model is an equally important tool in the test automator's arsenal and so I was keen to show how these two structures can work together to provide a well structured, modular & easily updatable test automation framework.  Please do leave any comments below, since I plan to update this framework approach as suggestions come in.

In summary, the purpose of this post is to provide an evolving best practice guidelines for structuring & writing automation frameworks, using Behaviour Driven Development (through cucumber) and good code structure (through Page Object Model pattern).

HIGH-LEVEL STRUCTURE:
Picture
  1. Feature files are requirements used to drive the tests. They are written in gherkin syntax (given, when, then).
  2. Step definitions allow the gherkin syntax to drive the lower level test automation code.
  3. Object Buckets are used to store/reuse data across test steps within the same scenario (e.g. instances of page objects created).
  4. Test Data Objects are logical groupings of test data (e.g. a test user class with an email address and password property).
  5. Step definitions communicate with Page Objects, which are representations of the pages/menus within the Application Under Test (AUT).
  6. App Driver class provides a wrapper for Selenium WebDriver allowing additional logging and any other interaction specific code required.

FEATURE FILES:
These represent the business requirements and are written in ‘business speak’ using Gherkin syntax
Picture
​Best Practice:

  • A separate feature file should be created for each feature/functional area within the app.
  • ‘Given’ sentences should be written using past tense, ‘Whens’ using present tense and ‘Thens’ using future tense
  • The ‘When’ section of a scenario will commonly be only one row long (making the purpose of test easily identifiable)
  • Scenario titles should not be too long. If more detail is needed add description row(s) underneath the title.
  • Use a ‘Given I was on the launch page’ to setup new instance of AppDriver and to place user on first screen of app. Use ‘Given I have navigated to XXXX page’ to get test pre-condition to start on a certain page. Both these statements can be used in the scenario Background.

​
STEP DEFINITIONS:
 
Step definitions are the interface between the ‘business speak’ gherkin and the technically coded Page Objects.  They are made up of methods which are called when the higher level Cucumber scenarios are run.

Picture
Best Practice:
 
  • Within the constructor, create/reuse any Object Bucket instances that are needed within that specific Step Definition file.  This can be done using Cucumber’s dependency injection.
  • Use instances of page objects and test data objects within the step definition file to drive your tests. 
  • The step definition files should contain your asserts.
  • You may choose to have 1 step definition class that is responsible for the creation/closure of the app driver class (if using web automation). This is the only step definition class that will contain a private instance of the web driver, since page objects will pass that instance between themselves.
 
Code Reuse:
 
  • Write your code for a step definition.  If that code is required by other step definitions within the same file, refactor that code into a private method. If different step definition files also require the same code, refactor it into a ‘CommonSteps’ step definition file. Here is an example:
Picture
​OBJECT BUCKETS:
 
These are used to persist data across Gherkin test steps as a Cucumber scenario runs. The data will be wiped at the end of each scenario.  Rather than creating new instances of pages manually at the start of each step definition method, this way means you don't have to expose the Driver instance on every Step definition page (meaning lazy use of e.g. driver.FindElementBy().Click() at the step definition level is not possible)
Picture
Best Practice:
  • Buckets will simply be ‘plain old’ classes with properties, allowing data to be stored only for the duration of a single test scenario. For example, a UserBucket might be used to gather user data during the ‘given’ and ‘when’ sections of a test run and then test that data as part of the ‘then’ section asserts (though usually these asserts will be carried out using data direct from the UI).
  • Instances of these buckets will be destroyed automatically by Cucumber at the end of each test scenario.
  • Most projects will have a PageBucket class to hold new page object instances as they are created during a test.

 
TEST DATA OBJECTS:
 
These objects are used to store logical groupings of test data information, for example a Test User with an email and password property.  They allow your test suite to pass around representations of real world objects as single entities, rather than as lots of individual variables (which can get confusing & cumbersome to maintain).
Picture
Best Practice:
  • Use these ‘plain old’ classes with properties to represent different Test Data that will be used by your tests. For example, a TestUser class might have a default username & password property set in its constructor. You could then pass an instance of testUser into a relevant method: loginPage.loginWithValidUser(testUser);
  • Updates to default values should be made in the Step definition files so the purpose of the test is obvious, e.g:
TestUser user1 = new TestUser();
user1.password = “invalid_password”;
loginPage.loginWithValidUser(user1);
  • User getters & setters for test data objects (so that controls can be added if needed at a later stage).
 
 

 
PAGE OBJECTS:
 
A separate class is created for each page or navigation menu of the Application Under Test (AUT). The methods on these classes will drive the AUT pages (e.g. Actions like: loginWithAValidUser) or return information about the state of the app (e.g.Queries like: getUsernameDisplayed).
Picture
Best Practice:
  • Pass the single instance of AppDriver into all page objects’ constructor method (see screenshot above)
  • Keep methods functional (e.g. loginWithValidUser) rather than too specific (e.g. enterEmailAddress). This will make future refactoring far quicker as the app evolves over time.
  • Any navigation methods (e.g. GotoLoginPage) should return an instance of the subsequent page object (e.g. LoginPage).  This will allow test writers to navigate through the test suites they are running more easily (since resulting pathway flows will be apparent from the code design). It can also help identify failing tests when, for example, a page object no longer links to a certain page.
  • Common navigation menus should form separate page object classes. Any page object (e.g. HomePage) that has the navigation menu should then have the navigation menu page object as a property of itself (using composition rather than inheritance).
  • Page Objects should not make assertions, except in the constructor to check the page is displayed. This can help make sure the correct page is correctly loaded before proceeding.
  • If a single flow in the application can lead to different pages being presented, then create a separate method for each journey. E.g: loginWithValidUser (returns welcome page) vs loginWithInvalidUser (returns error page).
  • When using NavigationControllers, a single page’s back button might return you to different pages. When this happens create multiple methods e.g.  'Back to homepage', 'Back to Account Page'.
  • For websites, if name and id are not available as properties of objects, use CSS if possible (faster & more consistent than xpath). For iOS apps xpath is fine instead of CSS.
  • Page Objects should not use getters & setters, since the page objects are encapsulating the UI and so will get and set any values using the UI (not internal class properties).


​APPDRIVER:
 
This is simply a wrapper class between our test automation code and the third party test automation framework (e.g. Selenium WebDriver).  

Picture
Best Practice:
  • The page objects should interact with AppDriver rather than directly with WebDriver.  This will allow far more control over test runs (e.g. logging), as well as providing the ability to switch in and out of different automation tools if required.
  • Environment variables (e.g. iOS version) should ideally not be hard coded within the constructor (contrary to the screenshot above), but instead set up as part of test run configuration.
  • The AppDriver should be the only class in the test automation framework that interacts with directly with Calabash / Appium / Selenium.
  • Set the implicit wait to be a low value (e.g. 5 or 10 seconds), and then wait for elements with a longer time out when required. This will help ensure tests are faster to run.

FOLDER STRUCTURE:
 
Below is an example of a folder structure you could use for implementing the aforementioned process:

Picture
DataObjects:
This folder can contain Test Data Objects and any other object representations you may need for your test suite.
 
Facades:
A façade class is one that provides a simplified gateway to more complex classes.  AppDriver is one example of a façade but others can be stored in this folder.
 
Utilities:
The Utilities folder will contain classes that use static methods to provide time saving actions, such as logging.
 
The remaining folder titles, in the screenshot above, have been covered earlier in this document.



ADDITIONS YOU COULD MAKE:
 
  • Adding Selenium’s Page Factory.
  • Agree a process for writing Gherkin.  Perhaps agree scenario titles & relative priorities as a group across Dev, Test & Business (to ensure nothing is missed), but then write individual steps as a tester (to ensure correct wording & ordering of steps is achieved).
2 Comments

    Author

    Seligman Ventures Ltd provide Software Testing & Development Services

    Archives

    March 2018
    December 2017
    February 2014
    January 2014

    Categories

    All

    RSS Feed

Powered by Create your own unique website with customizable templates.