Agile Testing

by Stan Taylor

The evolution of cucumber UI test steps

by Stan on 2016/03/16, one comment

I’m currently the framework/lead developer of a UI testing framework using Selenium WebDriver and Cucumber (written in Javascript using the webdriver.io bindings).  In an ideal world, cucumber test steps have no reference to anything beyond what is visible to the user in the user interface:

And I enter Password1 in the Password field
And I click the Log In button

In the initial version of the test steps that I wrote, I made steps like this reusable by allowing the test creator to enter custom data in reusable steps:

And I enter "Password1" in the "Password" field
And I click the "Log In" button

Where the text in parentheses is a variable, allowing the same step to be used for any similar field:

And I enter "johndoe" in the "Username" field
And I enter "Password1" in the "Password" field

The Javascript code behind these cucumber steps made certain assumptions about how the UI text was associated with the UI objects that the user needed to interact with, but this was hidden from the author of the cucumber steps. In the examples above, the assumption was that the text associated with the input field was contained in an associated <label> tag, e.g.,

<label for="username">Username</label>
<input type="text" name="username>

Another example step:

And I click the "Submit" button

which corresponds to this DOM element:

 <input type="submit" value="Submit">

For our applications that are actively under development, we discussed the need for consistent UI conventions with our developers and they agreed to abide by a set of UI design patterns. Since the agreed upon patterns represented best practices in HTML UI development in addition to making automation easier, our developers were agreeable. Afterwards, if we started to automate a new UI screen and discovered that it did not conform to the agreed-upon patterns, we filed a design-for-testability bug and the UI would be changed.

In the next phase of our automation project, we began to  to automate some of our legacy applications, and we quickly discovered that the developers had not been nearly as consistent with the UI designs of these applications: the assumptions behind our existing cucumber steps did not always hold true. Since these applications will eventually be phased out, the company is carefully limiting the amount of development work that is put into them. Therefore, we could not request that the UIs be changed to enable them to conform to the design patterns we had agreed upon for our new UIs.

To accommodate automation of these applications, we had to deviate from the cucumber principle that the test writer doesn’t need to know any more about the UI than what they can see. We developed some steps for other common UI patterns, and our automated test developers had to look at the DOM of the elements they needed to interact with in order to decide which step to use, such as:

And I enter "johndoe" in the input text field with name "username"

which corresponds to the input text field:

<input type="text" name="username">

and:

And I click the button that contains the text "Submit"

which corresponds to:

<button...>Submit</button>

(In that step, the ‘contains’ is the part that requires the user to understand the DOM and which differentiates this step from other steps related to buttons).

To my pleasant surprise, even our manual testers who didn’t really have any significant experience with HTML or the DOM learned these UI patterns quickly and adapted to them.

For the most part, we discovered that the UIs of our legacy applications, while not as conducive to the spirit of cucumber, still used only a fairly small set of UI conventions. We coded some more reusable steps for those other conventions and covered probably 90% of the cases that we encountered.

Eventually, I had to add some steps for the more obtuse UI design cases, such as:

And I enter "johndoe" in the "input" field with attribute "custom_attribute_name" with value "x_username"

I’m the first to admit that that is an ugly, ugly step, but steps like this allow us to automate the other 10% of UI designs that lie outside the conventions outlined above, and we’ve only had to use these types of steps a few times.

It did not take us long to create a library of steps that accommodate all of our standard UI interactions. I don’t think I’ve added a general-purpose UI interaction step in a couple of months, which is awesome.

For the next phase in the evolution of our automation framework, I’m thinking of using the XPATH ‘or’ attribute to collapse multiple steps back into one, but that may end up being more confusing to our test writers, especially if I can collapse some similar steps but not all of the same type. We’ll see.

 

Travel Time to…

by Stan on 2016/02/09, no comments

travel_timeI had to take a different route to work this morning, down I-35 from Round Rock to downtown Austin. Every few miles along I-35 there are light-up signs that are sometimes used for Amber alerts and senior alerts. Most of the time, however, they report “Travel Time to” the next major crossroad. As I pass these signs, the QA engineer in me tries to answer the following questions:

  • What is the purpose of these signs?
  • What am I, a passing driver, supposed to do with this information?
  • How well do the signs serve their presumed purpose?

I assume that the purpose of these signs is to give drivers an idea of how congested the roadway is at the present time. As for what I can do with this information? The sign doesn’t give any recommendations, but I assume that if the travel time is short, I could choose to stay on the road, and if it’s longer, I could choose an alternate route or just say f**k it, I’m heading back home.

The most interesting question to me, though, is how well the signs serve their purpose. In order to make a driving decision based on the information on the sign, I would have to have some idea of the following:

  • Which crossroad does the sign refer to (I’ll come back to this one)?
  • What does the current number of minutes shown say about the expected traffic volume? Making this judgment means I would need to know some of the following:
    • How far is it to the crossroad?
    • What would be a ‘normal’ travel time?
    • By ‘normal,’ am I thinking of traveling the speed limit without congestion slowing me down, or what I might consider ‘normal’ for this day and time, morning rush hour in my case this morning?
    • How does the current estimated travel time compare to ‘normal’?

The first sign that I saw this morning, and the one that inspired me to write this blog post is installed around Pflugerville, just south of the Louis Henna/SH-45 intersection with I-35, I think. This morning, it read:

TRAVEL TIME TO
FM 734
7-9 MINS

I would argue that this particular sign fails its intended purpose by the simple fact that it refers to a road number that nobody in the Austin area uses. If you asked me which roadway in the Austin area is FM 734, I probably wouldn’t be able to tell you, but from the location of the sign and from having lived in north Austin for 20 years, I deduce/remember that FM 734 is the numerical designation for the roadway that EVERYONE in the Austin area knows as Parmer Ln.

But this brings up another question: who is the intended audience for these signs? I-35 is both a major local expressway and an important interstate highway. Since I am a local resident, my initial assumption is that the information is for me, and therefore, since I believe most Austin-area residents would not know that FM 734 is Parmer Ln, my conclusion is that the information is not very useful. If the sign is intended for someone just passing through Austin, then referring to the cross road as FM 734 is probably acceptable.

But assuming that I, the passing traveler, know the crossroad, then we come to the point where all of these signs fail their assumed purpose: in order to make use of the information provided, I have to have some way to gauge the estimated travel time against some known quantity. If you asked me, for instance, how far I thought Parmer Ln is from the sign mentioned above, I’d estimate ‘a few miles’ or how long to travel there at the speed limit, I’d estimate ‘a few minutes.’ Assuming my ability to estimate distances or travel times are average, then the estimated travel time is pretty useless.

Let’s assume that my estimate of ‘a few miles’ is somewhere between 3 and 7 miles. If it’s 3 miles, then traffic must be traveling at about 30 mph, but if the distance is actually toward the longer end of my estimate, then traffic must be traveling close to the speed limit. Considering that traffic was probably traveling at 40-50 mph–right in the middle of 30-60 mph–at the time I saw the sign, then my only conclusion is that traffic must be about the same or average for that time during morning rush hour.

Conclusion

Giving the estimated drive time to a point that is a few miles away seems to be of very limited usefulness and requires the person reading the sign to have fairly accurate information about distances or usual drive times in order to make use of the information. I guess if I drove this stretch of I-35 every day and noticed the signs regularly, then I could make comparative use of the data provided. But if I were unfamiliar with Austin, then without consulting a map, this information would be completely useless. If the estimated drive time this morning had been, say 15-17 minutes, I probably would have concluded that traffic was very heavy this morning, but considering the relatively short distance from my current location to FM 734, if congestion were that heavy, then I would probably already be traveling slowly, in which case, I don’t need a sign to tell me that traffic is slow today.

Alternatives

Since these signs apparently use some sort of real-time detection of traffic density or speed, it seems to me that a more useful to give an average traffic speed, such as:

AVG TRAFFIC SPD
NEXT 5 MI
40 MPH

Honestly, I would enjoy nothing more than having someone tell me that some of my assumptions above are wrong or to explain the process behind the decision to show average travel time.

If tests fail, eliminate them

by Stan on 2016/01/29, no comments

JSF Program Ditches Tests To Protect Schedule:

A major operational test series planned for the Lockheed Martin F-35 Joint Strike Fighter has been abandoned in an attempt to protect the schedule for delivering a fully operational aircraft, according to the just-released fiscal 2014 report on the program from the Pentagon’s Director of Operational Test & Evaluation (DOT&E).

As I understand it, the F-35 has suffered from increases in scope, schedule and cost. Quality sacrificed. Good thing there are no lives on the line. Oh wait…

Automating android cordova/phonegap applications with appium

by Stan on 2015/10/16, no comments

I am just putting this out there for others to find, because I had such a difficult time locating this crucial tidbit of information: if you select the Android WebView context in your hybrid mobile application, you can run your DOM-based Selenium tests against it using appium.

I am tasked with creating UI automation for an angularJS-based application that we are deploying as a web application and as a mobile application using cordova/phonegap. I wrote my Selenium-based tests for the web deployment and then wanted to use the same tests for the Android mobile application using appium. When I launched my mobile application in the Android emulator and then used Android’s UIAutomator to view the UI objects, all I saw was the Android-based objects, no DOM-based objects–even when I selected the WebView context. My heart sunk because I thought I would have to write separate automation for the web deployment and the Android app. After quite a bit of Googling, though, I found the nugget of information above (I can’t find the source now). So, I’m able to write my tests against the web deployment using Selenium and then run them against the Android app using appium.

Identifying form elements by the <label> tag contents

by Stan on 2015/10/16, one comment

In a previous post, I explained how I use the text associated with UI objects in my cucumber tests. My steps look something like this:

Given I go to the login page
And I enter "johndoe" in the field with id "username"
And I enter "password1" in the field with id "password"

If the application under test is using the <label> tag to identify form elements (and it should! The <label> tag was designed specifically for this purpose), then your application under test has UI objects that look something like this:

<label for="username">Username</label>
<input name="username" type="text"></input>

Writing a cucumber step to interact with the <input> field based on the text in the <label> tag consists of locating the label element and then using the value of its for= attribute to locate the input element. Using the webdriver.io Selenium bindings, my code looks like this:

  this.Given(/^I enter "([^"]*)" in the "([^"]*)" field$/, function (textToEnter, labelText, callback) {
    xpath = '//label[contains(.,"' + labelText + '")]';
    this.getAttribute(xpath, 'for').then(
      function (value) {
      // get the input tag with the name= {value} and enter the text
        xpath = '//input[@name="' + value + '"]';
        that.setValue(xpath, textToEnter).then(
          function () {
            callback();
          },
          function (err) {
            callback(err);
          }
        );
      },
      function (err) {
        callback(err);
      }
    );
  });

Words have meanings!

by Stan on 2015/10/10, no comments

I recently received the following message via LinkedIn:

Dear Stan, We are a young silicon-valley-like startup …
… developing disruptive products for sensing, cognition and communication for the Internet of Things (IoT) market;
… fully funded with an exclusive Fortune 200 customer already secured;
… who is working closely with us to specify the product and take it to market;
… led by a top-notch team of seasoned start-up engineers and executives with successful prior startup exits to multi-national corporations; and
… all right here in Austin.

We are currently looking for a top-notch automation expert and looking at your resume and background I thought you might be a good fit.    I hope you are interested in hearing more and would be glad to discuss this opportunity further via a call or f2f meeting. Thanks, [name redacted]

I was really curious to know what he meant by ‘silicon-valley-like,’ so I answered:

What does ‘silicon-valley-like’ denote? That could mean a lot of different things–both positive and negative.

His response:

Good point re: the silicon-valley reference – esp. being a long-time Austinite (by choice) I can understand why it could be considered negative! I was referring to the fact that we have an exciting mission in a hot industry area that can have a big impact with a top-notch team to work with. And the particular role I’d like to go over has some very interesting challenges – for example capturing, storing, analyzing, labeling and retrieving very large data sets.

And my answer again:

I’m pretty sure that “an exciting mission in a hot industry area that can have a big impact with a top-notch team to work with” isn’t a characteristic unique to the Bay Area. I understand that you probably can’t reveal many details, but the quote above doesn’t tell me anything more than “silicon-valley-like” So far, you’ve basically told me nothing at all about the opportunity.

If this ‘silicon-valley-like’ startup hired this guy to do their recruiting, I can only come to one of two conclusions:

  1. He doesn’t know the business well enough to give meaningful details, or
  2. He doesn’t understand recruiting well enough to get to a candidate’s concerns quickly and answer them.

Based on what I saw on LinkedIn (LI only let me see this guy’s name and title), however, I suspect that he is one of the founders or early employees. If that’s the case, then possible explanations above for his behavior incline me even less to treat his offer seriously. Do I want to work in a company where this person has a leading role? Hell no.

Writing Selenium test steps for cucumber tests

by Stan on 2015/10/03, 2 comments

In my current job, I’m responsible for developing a framework for performing UI testing of web and mobile applications with Selenium WebDriver/Appium, using the webdriver.io bindings for node.js Javascript. We have adopted cucumber as the format for defining the tests.

Conventional wisdom regarding UI testing holds that you should always strive to select UI objects by the attribute that is least likely to change. With web UIs, you’ll typically see a hierarchy of preferred selectors as the following:

  1. Element ID
  2. Element name
  3. CSS class(es) associated with the element
  4. Text associated with the element

If you used this strategy with cucumber, you would get tests that looked something like this:

Given I go to the login page
And I enter "johndoe" in the field with id "username"
And I enter "password1" in the field with id "password"
Then the input element with type "submit" should become enabled
And I click the input element with type "submit"

But such steps are counter to the principles of behavior-driven development. The primary purpose of cucumber is that it allows your business owner to write requirements that can also directly serve as tests, and identifiers such as element ID or name are artifacts of implementation details, not part of the basic requirements. Or more simply–your business owner should be able to describe interaction with the application using only what’s visible to them in the UI.

More typically, cucumber steps for the login scenario above would look something like this:

Given I go to the login page
And I enter "johndoe" in the "Username" field
And I enter "password1" in the "Password" field
The the "Log in" button should become enabled
And I click the "Log in" button

Note that the steps use the visible text associated with each element to select the element.

The argument against this approach is: “But whenever your UI text changes–and let’s face it, it often changes–you’ll have to go update every single test!” While this is true, my rebuttal is that it’s a simple global search and replace change, and more importantly, it’s not a change to the code behind the cucumber, only to the cucumber test definitions, which, in my opinion, is a lower risk change than an actual code change.

To be fair, as the number of tests grew, I saw the redundancy between tests as a maintenance risk, so I’ve abstracted out frequently used functions, such as login and navigation, into single steps. Steps like the examples above no longer exists in our codebase. Instead, we have single steps such as:

Given I log in as username "johndoe" and password "password1"

So, now, if the text on our login page changes, we only have to change it in one place.

In my next blog post, I’ll show some of the code behind these steps.

UPDATE: Here is the next blog post.

Underestimating myself

by Stan on 2015/07/23, no comments

I’m a self-taught programmer; I’ve never done it full-time. Most of the QA jobs that I have had over the years have included some amount of scripting and/or automated testing work, but it’s always been done alongside other QA tasks. When I was job hunting last year, I concluded that if I really wanted to remain competitive in my career, my next job needed to focus solely or primarily on writing test automation. Plus, I love to code, and I thought I would really enjoy such a job.

During my job hunt, my standard line about my coding skills was: I’m a decent coder, but because I’ve never done it full-time, I’m probably not qualified to fill a role where I’m the person primarily responsible for the development of an automation framework. When I interviewed here at Netspend for a senior automation developer job, I was told that they were seeking someone with a strong automation background but that they were less concerned whether the candidate knew the language being used, node.js/Javascript. Since node.js is a fairly new framework, and since Javascript is rarely used in automation, they (accurately, in my opinion) didn’t expect to find a candidate who had node.js/Javascript experience. Furthermore, they assumed that any qualified candidate could pick up the language.

It turned out that those were perfect expectations for me. During my interviews here, the interviewers were impressed with my extensive knowledge and experience with automation, and I passed their general programming tests. In regard to programming skills, they were more interested in my thought processes and logic than producing accurate code in the spur of the moment on a whiteboard. Plus, I did have a distant background with Javascript (not just in the browser; it was also the programming language of an automation tool that I used many years ago).

Now that I’ve been here at Netspend for about 8 months and developed a framework and automated tests for UI-testing, I’ve discovered that I misapprehended the skills that are necessary for building an automated testing framework. When I said I was probably not qualified to build an automation framework, I was thinking primarily of coding skills. I have learned the Javascript syntax and the node-specific knowledge necessary to build an automation framework, and I’ve built a robust framework and set of tests that adds value to our development process.

Last week, I worked with another senior QA engineer here at Netspend to define the desired skill sets of our different types of QA jobs: general QA, QA of our back-end systems, QA for our user-facing applications, and automated test developer (I’ll do another blog post about the results of this work). Here is the list of skills that we feel are necessary for an automated test developer in our organization:

  • Source Control Management (we use git)
    • How and Why
  • Continuous Integration (we use Bamboo)
  • Programming Basics, e.g.,
    • Conditionals
    • Data Types
    • Program flow
  • Advanced Programming, e.g.,
    • Development Patterns / Architecture
    • Abstractions / Refactoring
    • Contributing to Framework development
  • X-Path / DOM manipulation (for UI testing)
  • Automation Test Concepts, e.g.,
    • How to Validate what
    • Types of automation
    • Reducing to minimum set of tests
    • Cost / Benefit analysis
  • Database basics
  • Linux basics

As it turns out (and as the people who hired me here–one of whom was the guy I worked with to create this list–astutely realized), being an expert coder of the language of choice doesn’t even make the list. I’ve been successful with the development of an automated testing framework here due to my knowledge of and experience with all of these areas.