Hackernoon logoThree steps to click a button by@fkem

Three steps to click a button

image
Michael Borisov Hacker Noon profile picture

@fkemMichael Borisov

I’ve been helping with test automation for a couple of projects. Every time we start fresh and have all good intentions to keep our regression suite clean. Every time we end up tossing things around and spending the time to adjust our scripts in order to avoid big changes with every little new UI change. Is there an option to reduce the overhead? I know my specs are a representation of original requirements. I also noticed that there is something usability engineers could benefit.

I’ve spent some time analyzing what levels of abstraction we have during automating specifications. I looked at what type of language we use on each of these levels and this is what I found:

  1. A level of use cases. Where business processes and actors are defined;
  2. A level of screens and scenarios. Where use cases translated into screens and scenarios;
  3. A level of controls and actions. Where screens and scenarios translated into low-level UI specific controls and actions.

Let’s take a look on every level with some more or less practical examples.

The level of use cases

I assume you know about behavior driven development, Gherkin language and tools like SpecFlow. Using Gherkin language on this level makes a lot of sense. This level is very much about the business meaning of our product thus it’s valuable if business people can understand this kind of tests. So, let our Gherkin scenarios speak the language Product Owner could understand and use as his own:

Feature: Shopping
Scenario: I want to buy a present for Christmas and I don't have any clue what to buy
Given I know my budget
And I know whom I buy a present
When I ask for help to choose a present
And I tell about the person I buy a present
And I tell my budget
Then I'm offered with relevant options

I bet my Product Owner can read the script above and may also find mistakes without any noticeable effort. I even hope he could create scenarios for me so we could help each other and have a point for collaboration.

The level of screens and scenarios

At this level, I’ll refer to a page object pattern explained by Martin Fowler. The page object pattern helps to separate low-level clicks and objects from more meaningful screens and page blocks that make our product. These screens and blocks are specific to the product. Some teams even create a catalog out of those blocks and reuse them through the product. These blocks usually are tightly coupled with work that usability engineers are doing, and this probably would be a topic for another article — still nothing like an input, button or label. To show an example, I use NOpenPage library- a lightweight implementation for the page object pattern that extends Selenium. The example shows SpecFlow steps:

[Binding]
public class MySteps
{
[When(@"I ask for help to choose a present")]
public void When_I_ask_for_help_to_choose_a_present()
{
Browser.Do(TheShopPage.Navigate);
Browser.On<TheShopPage>().AskForHelpToChooseAPresent();
}
    [Then(@"I'm offered with relevant options")]
public void Then_Im_offered_with_relevant_options()
{
Browser.On<TheShopPage>().AssertRelevantOptionsOffered();
}
}

This level needs some effort from a person with development skills although the language could be clear for a usability engineer as we speak about pages, blocks on those pages and scenarios. Let’s assume asking for help is something like a wizard. Then method AskForHelpToChooseAPresent could look like this:

public class TheShopPage : Page
{
public TheShopPage(IPageContext context) : base(context)
{
}
    public static void Navigate(IWebDriver driver)
{
driver.Navigate().GoToUrl("https://theshop.it");
}
    public void AskForHelpToChooseAPresent(string gender, int age)
{
Control<Gender>().Choose(gender);
Control<Age>().Choose(age);
}
    public void AssertRelevantOptionsOffered()
{
Control<Offers>().AssertRelevantOptionsOffered();
}
}

Level of controls and actions

So, now this should be clear. We went to the bottom. Buttons, labels, and inputs live here. We put here all Selenium related code inside page objects implemented with NOpenPage:

public class Gender : PageControl
{
public Gender(IPageControlContext context) : base(By.ClassName("gender"), context)
{
}
    public void Choose(string gender)
{
var input = Element.FindElement(By.Id(gender));
input.Click();
}
}

By following these three levels of abstraction:

  • I have clean specifications that business people and usability engineers can understand;
  • I can easily extend my specs. Because I know on what level I need to introduce a change.

Examples here are very abstract although I only want to show the idea of using business language on top, usability language in the middle and keep low-level technical details at the bottom. This approach helps a lot writing clean code for my automated tests.

Happy coding,
Michael Borisov

Originally published at corker.github.io on March 4, 2017.

Tags

Join Hacker Noon

Create your free account to unlock your custom reading experience.