1

enter image description here

I am contemplating on creating a public api for my team to use that will encapsulate the workings of webdriver and testng as it's main tools. Primary to the concern is re usability of code when possible to cater the many test scenarios.

My idea is to allow the qa team to define a set of parameters per scenario to test through excel worksheet, being 1 worksheet per scenario. Each scenario can involve multiple test classes created by the developer, these test classes may be testing a specific page or a set of pages together.

With webdriver in mind, I can solve for a way to mix pages on a single test class that initializes the necessary webdriver object used by the page objects.

My problem arises when trying to mix test classes together to form an orchestrated mix of test cases in a big scenario case, in a way like composing many fine grained level use cases in a single coarse level use case.

How should i pass webdriver objects and pages objects between the test classes using testng and webdriver to achieve this goal? Is this even a sound idea in the first place?

Btw the factory A and factory B are what i thought of as scenario A and scenario B. I got blocked by the mechanisms to pass test related object between test classes for the orchestration to work.

2

It looks like you're facing two problems. Let me address them separately.

Managing test scenarios

It sounds like some of your problems could be solved by adopting a BDD framework like Cucumber. It's possible to use with a variety of languages including Ruby, Python, PHP and a variety of .NET and JVM languages.

What it allows you to do is describe test scenarios in feature files composed of reusable steps that are basically granular pieces of code you can use to interact with the tested application. It's often used in conjunction with WebDriver in order to automate web-browsing scenarios.

The syntax of a feature file is pretty much plain text following a set of conventions. Each step can be matched (using a regular expression) to an implementation that you provide.

Here's a simple example

Feature: Subscribe to the service
   In order to receive updates on latest offers
   As a site visitor
   I want to be able to subscribe to XYZ's service

Scenario: Subscribe button displayed on the home page
   Given I am viewing the home page
   And I scroll to the bottom
   When I fill in my email in the subscription form
   And I click the Subscribe button
   Then I am redirected to a confirmation page

The first part, starting with Feature is a piece of background information that is not backed by any code. It's just used to create a readable test report.

A feature file can contain an arbitrary number of scenarios (in this case, just one) that are backed by actual code. These units of code are called steps. The code to be executed is usually chosen by a regex pattern match against what appears in your feature file.

Here's a simple example in Java:

@Given("^I am viewing the home page$")
public void iAmViewingTheHomePage() {
    // Write code here that turns the phrase above into concrete actions
    // obtain the web driver, visit a page
}

So far so good but this doesn't solve your problem yet. One step towards writing granular and reusable steps is the use of parameters.

Let's say you have a step that describes an interaction with a specific page.

Given I open the Subscriptions section of the site

Instead of matching the whole step like this:

@Given("^I open the Subscriptions section of the site$")
public void visitSubscriptions(){...}

You can pass parts of your step description as parameters

@Given("^I open the (.*) section of the site$")
public void visitSection(final String sectionName) {
   //use selenium to navigate to an arbitrary section using
   //WebDriver
}

Cucumber also comes with a cool set of features that allows you to pass data around the steps.

You can embed any number of placeholders in your regular expression and they're going to be bound to method parameters with corresponding indices. This is how it works in Selenium-JVM but other flavours support basically the same thing. Different syntax is used across languages but the general idea is the same.

This alone will allow you to manage your test steps much better but there's more.

You mentioned your testers using CSV files. Cucumber allows you to embed tables with test data into the feature files themselves. You can easily ask your testers to write up the data in this format or just write a script that converts CSV files into it. Here's what a Data Table looks like:

Scenario: Book a flight for multiple users
  Given the following contact information
    | name    | email   | nationalId   |
    | Alice   | a@a.com | AAA222       |
    | Bob     | b@b.com | BBB333       |
    | Charlie | c@c.com | CCC444       |
  When I fill in the passenger details form
  Then the booking should be recorded

You can then read the table in your step definition. There's a number of ways to do this. You can use the DataTable class, use a POJO that has a constructor matching the data, etc. This will be a bit different between languages but again, the principle remains the same.

You can find a broader range of examples in this blog post

Reuse of internal objects

When it comes to object reuse (WebDriver instances, etc.), Cucumber itself does not offer a solution. It is possible to call steps from within other steps but this is advised against by the community and not supported by some of the Cucumber versions (I know it can be done in Cucumber Ruby). See this SO answer for a little follow-up on the subject. That said, even if you decide to pass data around steps like this, it's not the way to manage internal objects in a sane way using this technique. WebDriver objects are implementation details that must not pollute your scenarios anyway.

What you can come up with will be specific to the language you're using. Judging by the fact that you mention TestNG, this is probably either Java or C#

The company I work for has developed a nice framework based on dependency injection (specifically, Google Guice was used) that allows us to provide this kind of objects in an easy, consistent way, as well as effortlessly compose page objects by simply @Inject-ing them. It's a proprietary piece of software so I'm afraid I cannot share more information but the whole idea should not be too complex to implement in a basic form. Whatever way you go, the management of WebDriver objects and other implementation details should never leak into the test cases themselves. You'll need a shared utility to be used by all page objects in a consistent manner.

There are some blog posts on the subject of using WebDriver with Spring but any CDI framework will greatly simplify your functional test codebase.

Please also mind that automated tests need not use the same programming language as the code itself. It's a boon if your developers can use a single language to write production code and tests but if you're working with polyglots, they might just find a different language more suitable for this purpose. From my experience, dynamically typed scripting languages like Ruby or Groovy tend to fit this role quite well.

  • thanks for the long post, it looks promising.. i'll try to read it and churn it over the weekend.. :D – johan.i.zahri Jun 26 '15 at 4:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.