Five automated acceptance test anti-patterns

Whilst being involved with lots of people writing automated acceptance tests using tools like SpecFlow and WebDriver I’ve seen some ‘anti-patterns’ emerge that can make these tests non-deterministic (flaky), very fragile to change and less efficient to run.

Here’s five ‘anti-patterns’ I’ve seen and what you can do instead.

Anti-pattern One: Not using page-objects

Page objects are just a design pattern to ensure automated UI tests use reusable, modular code. Not using them, eg, writing WebDriver code directly in step definitions, means any changes to your UI will require updates in lots of different places instead of the one ‘page’ class.

Bad

[When(@"I buy some '(.*)' tea")]
public void WhenIBuySomeTea(string typeOfTea)
{
Driver.FindElement(By.Id("tea-"+typeOfTea)).Click();
Driver.FindElement(By.Id("buy")).Click();
}

Better

[When(@"I buy some '(.*)' tea")]
public void WhenIBuySomeTea(string typeOfTea)
{
     MenuPage.BuyTea(typeOfTea);
}

Complicated set up scenarios within the tests themselves

Whilst there’s a place for automated end-to-end scenarios (I call these user journies), I prefer most acceptance tests to jump straight to the point.

Bad

Scenario: Accept Visa and Mastercard for Australia
 Given I am on the home page for Australia
 And I choose the tea menu
 And I select some 'green tea'
 And I add the tea to my basket
 And I choose to checkout
 Then I should see 'visa' is accepted
 And I should see 'mastercard' is accepted

Better

This usually requires adding some special functionality to your app, but the ability for testing to ‘jump’ to certain pages with data automatically set up makes automated tests much easier to read and maintain.

Scenario: Accept Visa and Mastercard for Australia
 Given I am the checkout page for Australia
 Then I should see 'visa' is accepted
 And I should see 'mastercard' is accepted

Using complicated x-path or CSS selectors

Using element identification selectors that have long chains from the DOM in them leads to fragile tests, as any change to that chain in the DOM will break your tests.

Bad

private static readonly By TeaTypeSelector =
            By.CssSelector(
                "#input-tea-type > div > div.TeaSearchRow > div.TeaSearchCell.no > div:nth-child(2) > label");

Better

Identify by ‘id’ (unique) or ‘class’. If there’s multiple elements in a group, create a parent container and iterate through them.

private static readonly By TeaTypeSelector = By.Id("teaType");

Directly executing JavaScript

Since WebDriver can directly execute any arbitrary JavaScript, it can be tempting to bypass DOM manipulation and just run the JavaScript.

Bad

public void RemoveTea(string teaType)
{
  (driver as IJavaScriptExecutor).ExecuteScript(string.Format("viewModel.tea.types.removeTeaType(\"{0}\");", teaType));
  }

Better

It is much better to let the WebDriver control the browser elements which should fire the correct JavaScript events and call the JavaScript, as that way you avoid having your ‘test’ JavaScript in sync to your ‘real’ JavaScript.

public void RemoveTea(string teaType)
{
  driver.FindElement(By.Id("remove-"+teaType)).Click();
}

Embedding implementation detail in your features/scenarios

Acceptance test scenarios are meant to convey intention over implementation. If you start seeing things like URLs in your test scenarios you’re focusing on implementation.

Bad


 Scenario: Social media links displayed on checkout page
   Given I am the checkout page for Australia
   Then I should see a link to 'http://twitter.com/beautifultea'
   And I should see a link to 'https://facebook.com/beautifultea'
 

Better

Hide implementation detail in the steps (or pages, or config) and make your scenarios about the test intention.


 Scenario: Social media links displayed on checkout page
   Given I am the checkout page for Australia
   Then I should see a link to the Beautiful Tea Twitter account
   And I should see a link to the Beautiful Tea Facebook page
 

I hope you’ve enjoyed these anti-patterns. Leave a comment below if you have any of your own.

An automated testing journey

I did a presentation this evening in Brisbane on an automated testing journey that one may embark on. The whole thing was centered around this tube map style diagram I came up with recently: (download in PDF)

Here’s a link to my prezi slides and it should appear below (if you have flash enabled that is).  You can also download them in very printable PDF if you so choose.

I feel the presentation was well received, but I really shouldn’t have tried to squeeze three days of thinking into 30 mins. Oh well.

As always, I welcome your feedback.

Rubular & RubyMine: makes Cucumber easier

I’ve spent the last couple of months establishing Acceptance Test Driven Development on a medium sized software delivery project using Watir & Cucumber.

Cucumber is premised on reading feature files and matching strings to determine what to do, which is done by using regular expressions in step files. This means constant use of ruby regular expressions, and in polishing up on my regular expression skills, I have found rubular incredidly useful. I love the simple layout and the ‘Regex Quick Reference’ at the bottom, just where you need it. It’s very well done.

Rubular: A Ruby regular expression editor and tester
Rubular: A Ruby regular expression editor and tester

The other tool I have found incredibly useful is RubyMine. Up until now, I’ve never really bothered with an IDE for Watir stuff. I’ve mainly stuck to text editors before, but since I have started using Cucumber, I have found the RubyMine tool almost critical, as its support for Cucumber feature files and step definitions is superb. It features click through linking for feature files so you know exactly what step you’re calling, and the debugger is awesome; no more puts statements for me :)

So, if you’re thinking about implementing Cucumber, or using Cucumber but are annoyed with the lack of efficiency in managing a large suite of step definitions, I would thoroughly recommend these two tools. Rubular is free, and I believe RubyMine is about $99, but less if you need multiple licenses. There’s also an Early Access Program where you can use RubyMine for free as long as you’re happy to test it along the way.

Three software testing links

Soap Opera Testing

A couple of years back I read about soap opera testing, a derivative of scenario testing that involves complicating a test scenario to the point of it resembling a soap opera plot. Most of the material on soap opera testing is now unavailable, but Eric Petersen wrote about a real life example of a Department Store accidently giving away $800 to $4000, and the unintended consequences including physical violence in the carpark.

Usability Testing

When conducting usablity testing, it is super critical to have non leading goals and tasks, otherwise the participant will simply do what you ask and won’t reveal any usability issues. I found this example about usability testing of the IKEA site the most useful to explain why.

Years ago, we helped with a study of Ikea.com, looking at how people found products on the site. When we got there, they’d already started the testing process and were using tasks like “Find a bookcase.” Interestingly, every participant did exactly the same thing: they went to the search box and typed “bookcase”.

Upon our suggestion, the team made a subtle change to the instructions they were giving their participants: “You have 200+ books in your fiction collection, currently in boxes strewn around your living room. Find a way to organize them.”

We instantly saw a change in how the participants behaved with the design. Most clicked through the various categories, looking for some sort of storage solution. Few used Search, typing in phrases like “Shelves” and “Storage Systems”. And, nobody searched on “bookcase”.

The way you design tasks could have a dramatic outcome on the results, without you even realizing it.

Acceptance Test Driven Development

I’ve seen acceptance test driven development (ATDD) frequently implemented incorrectly, especially with developers writing acceptance tests in FitNesse. I think it’s because the developers I have seen have a natural tendency to make things technical. This article, about the misuse of Cucumber, represents my thoughts correctly, it’s a design vs implementation problem, and it’s the fault of the ATDD tools as they encourage it.

You’re Cuking It Wrong

Opinions on cucumber seem to be divided in the Ruby community. Here at Elabs we’ve been using cucumber to fantastic success on all of our projects for more than a year. At the same time Steak and projects like it seem to be gaining traction; some people are seemingly frustrated and fed up with cucumber.

So where does this gulf of experiences come from, why is cucumber loved by some and hated by others. At the risk of over-generalisation and mischaracterisation I recently came up with a theory: the cucumber detractors are not using cuke the way it was intended.