Let’s Build A Framework – Day 2.5


Despite my best efforts we fell a little behind in the last 2 sessions.  So to catch us up to where I wanted to be on our final day we mae this Day 2.5 session post.  This post will cover a few key changes made after Day 2.   We will discuss these on Day 3 as well, but this post just covers the actual coding done.

I will keep this post as short and as sweet as possible.

What Has Changed Since Day 2

If you’ll remember on Day 2, we built a handy dandy function “waitForPageToLoad” that allows us to quickly check all required elements on a page and ensure that page is fully loaded.   However, the way we built it, was to add it directly to our EbayHome page object.  This means that only the EbayHome page could use it.  When what we want is for any page we create to be able to use waitForPageToLoad.

To do this we are going to create a Base Page Object and explore the concept of inheritance in javascript.  This will also let us clean up our code a little bit in other ways.

The other changes made were to create a couple new pages for us to play with, as up until now we’ve been doing everything on a single EbayHome page.  By the end of this post you should have 3 different pages and we can play with navigating between all of them and really start to see the power behind our framework.

Building a Base Page Object in WebDriver.io

As mentioned, our big goal for this session is to share methods between our page objects.  Now, there are plenty of options we could explore,  but, since we are already using classes and objects in our framework we should really take advantage of the features for them.

The biggest feature we’ll use is “inheritance”.  That is to say, allowing one class to be built on top of another class.  This means that the child class  would get all of the benefits and methods of the parent class while also being able to have its own methods.

Note: In computer science inheritance can be a controversial subject on when it should and should not be used.  If you are new to programming and want to learn more I recommend googling concepts such as “inheritance vs. composition”.   But for the purpose of our sessions we are going to stay away from these arguments and use inheritance in a very limited capacity.

Let’s Get To It

Our goal is to build is a new page object base class we’ll call “PageObject”.  This class will have a constructor just like our other page that saves our driver.  We will also use a little trick to have it load our locator file dynamically to save us some coding time.

But, most importantly we are going to put our “waitForPageToLoad” method there.  Doing this will allow any page object like EbayHome that inherits from PageObject to be able to call “waitForPageToLoad” with no extra code needed.

Building Our Base PageObject class

First step is we are going to make a very simple class, and only have it handle the driver.  This is going to look very similar to our existing EbayHome class.

Screen Shot 2016-12-08 at 12.54.03 PM.png
A very basic PageObject base class

So at this point with our EbayHome class inheriting our base class, all we’ve gained is it no longer has to manage its own driver.

Screen Shot 2016-12-08 at 12.55.58 PM.png
EbayHome inheriting our PageObject base class

First thing, let’s get rid of the need to constantly have to load the locator file in each page.   This is problematic because if we ever move our page object file, or change the locator name our tests will stop working.  Instead, we want our base class to be smart enough to say “Look for a locator file that has the same name as this class and load that”.

Luckily we can get the name of our EbayHome class even from inside our base class with

this.constructor.name

Calling that in our PageObject base class will return “EbayHome”.  So we can modify our PageObject constructor to automatically load our locator file for every page that inherits from it.

Screen Shot 2016-12-08 at 12.59.33 PM.png
Dynamically load the correct locator file based on the page objects name (EbayHome etc …)

Obviously now, we can delete the locator line from our EbayHome constructor.

Next up, we want to migrate our “waitForPageToLoad” method to our PageObject base class so for any new page object we create we can call this method.  This is fortunately very easy as we’ve already written the function.  We can just copy the waitForPageToLoad method directly to our PageObject class.

Screen Shot 2016-12-08 at 1.02.10 PM.png
waitForPageToLoad now in the base class

Note: the one thing we have to change is, its now a prototype of the PageObject class and not from the EbayHome class.

Now obviously this method relies on our helper method “findRequiredLocators” so we’ll have to move that over to our PageObject class as well.

Screen Shot 2016-12-08 at 1.03.59 PM.png
findRequiredLocators method now in PageObject class

Inheriting From Our PageObject Class

There are numerous ways to inherit in Node/JavaScript, in newer versions like ES6 its much more user friendly.  But because we want this post to work for everyone including people who might be on older infrastructure, we are going to use an older method of inheritance

I leave it to you the reader to make a modification yourself and use the new fancy methods of inheritance for future learning and practice.

For our method of inheritance we are going to use a helper method in the ‘util’ library called “inherits”.

util.inherits(EbayHome, PageObject);

That line will do most of the dirty work for us in linking EbayHome as a child of PageObject.

The only remaining thing is to use PageObject’s constructor.  So when we create a new page object in our tests we can pass a driver in to the page, but have that page pass it up the chain to its parents constructor.

Thankfully there is an easy solution for this.  We just call that driver directly from our parent class like so:

function EbayHome(passedInDriver) {
 PageObject.call(this, passedInDriver);
 locators = require('../locators/EbayHome');
};

Note that this is our EbayHome class, and inside we are referencing our new PageObject class and calling its constructor.

After these two changes are made, we have successfully made EbayHome a child of our PageObject base class in javascript.

screen-shot-2016-12-08-at-1-46-29-pm

And that’s it, nothing else needs to change.  You can still call waitForPageToLoad in your tests like before only now we’ve set it up so it will work for every new page we create as well.

on.ebayHome().waitForPageToLoad()

Speaking of new pages ..

Expanding our Page Object Collection

Now that we have a few commands, a PageObject base class and some helpful methods.  It’s probably time to create some new page objects so we can make bigger scripts.

For this session we are going to create a EbaySearchResults and EbayCart page, and make a test to tie it all together.

Steps To Create a New Page

Obviously in Day 1 and 2 we covered making a new page.  But now is a good time for a refresher.

  1.  Create a new PageObject class under the pages directory

    1. Make sure that class inherits from our PageObject base class
    2. We’ve created a “SamplePageObject” class for you.  If you are in a hurry you can just copy this class for new pages and change “SamplePageObject” to your new page name
Screen Shot 2016-12-08 at 1.10.17 PM.png
A sample new page object template

2 Create a new locator file with the same name as the page under the locators directory

  1. Just like with the page object, we’ve created a SamplePageObject.json file you can use as a template
Screen Shot 2016-12-08 at 1.12.09 PM.png
Sample page object locator file

3 Add an entry to our PageObjectCollection class

  1. Now that we have a page, and a locator file, the final step to wiring it up is to add an entry to our PageObjectCollection class which is located in the pages/page_object_collection.js file.
Screen Shot 2016-12-08 at 1.15.34 PM.png
New entry for a page object in the PageObjectCollection class

4.  Fill out the new page with locators and methods

  1. Now you can add locators to the locator file for elements that are on the page.  And you can add methods in the page to interact with those elements.
  2. Below are screenshots of new locators and methods for our EbaySearchResults, and EbayCart pages!
Screen Shot 2016-12-08 at 1.17.27 PM.png
Locators for new EbaySearchResult page
Screen Shot 2016-12-08 at 1.18.20 PM.png
Locator for new EbayCart page
Screen Shot 2016-12-08 at 1.19.13 PM.png
New EbaySearchResult page with a goToCart method
Screen Shot 2016-12-08 at 1.20.01 PM.png
New EbayCart page

Putting It All Together With a New Test

Now that we have our shiny new PageObject base class, and some new page objects.  Let’s write another test, this time navigating further into the site.

Screen Shot 2016-12-08 at 1.22.00 PM.png
New test using new page objects

Note how we can call waitForPageToLoad on any page we want.

Hopefully now, you’ll start to see how this framework while kind of a pain to build adds some real value.

  • At this point our tests are readable even for people who can’t code well.
  • We can quickly spin up new pages in a matter of minutes and incorporate them into our tests.
  • We can add new methods to all our pages at once with our base class.

And, believe it or not, we have only scratched the surface with what is possible with our framework.

What’s Coming Up?

For our final day of work, we’ve still got some fun features to add.

  1. We’re going to create a concept of a “Navigation Path” that will allow us to quickly get to any page we want.
  2. We’re going to create a smoke test, that takes advantage of everything we have and that can test every single page we have in one simple data driven test.
  3. We’re going to create some API infrastructure and tests.

 

So stay tuned dear reader because we’ve saved the best for last.

 

Let’s Build A Framework – Day 2 Recap


Thanks to everyone who came out for the 2nd day in our current series around building an automation framework.

This one is audio only due to a miss during the session, but the issue should be resolved for future sessions. In addition, we are going to try and update with visuals as well if possible.

Sorry for the delay in getting this posted…totally slipped through the cracks!

Let’s Build A Framework – Day 2


Fleshing Out Our UI Automation Framework

Hello again to all the West Denver Test Engineers, or any wayward internet traveller who stumbled across this page.  Today we are going to go over what we built in Day 2 as part of our great framework building experiment.   The good news, is this blog post should be much shorter than Day 1, which had to include a lot of ancillary explanation of the tools we were using.   The bad news? were nearing the end of our journey.

 

So let’s get to it shall we?

What Are We Going to Build Today?

Today we are going to expand our framework with some new killer features like automatic frame handling in our tests.  And introducing a way to make our tests even more readable with a page object collection.  Finally we will close with adding a great new feature that will allow us to validate any page we write is fully loaded without ever having to write new code.

A way to clean up our test readability

Before we get started let’s revisit what our last test looked like at the end of Day 1.

it('Should open ebay and search for orphans', function() {
   //I want to open a browser
   //I want to load google
   var ebayHome = new EbayHome(driver);
   return ebayHome.open()
   .then(function() {
     return ebayHome.searchFor('orphans');
   });

});

It’s a little cleaner, but if we imagine a test spanning numerous pages we’ll have to create each page object every time.

it('Should do lots of actions', function() {
  var ebayHome = new EbayHome(driver);
  var ebaySearchResults = new EbaySearchResults(driver);
  var ebayUserPage = new EbayUserPage(driver);
  // you get the idea
});

Not only is this not pretty, it exposes a potential maintenance problem.  Say at some point in the future, we decide we need to pass an additional argument to our page objects instead of just the driver.  In this case we would need to update every test and every instantiation of every page to support that.

A maintenance nightmare.

To solve this we will build out a PageObjectCollection object.   This will be a simple class that stores all our pages, so we can simply ask for which page we want.  Through some clever naming, this will also greatly improve the readability of our tests.

A way to handle frames

For those of you who have experience with older websites, or sites that use a lot of iframes you probably know that frames can be incredibly frustrating to deal with in UI automation.  The reason being that even though you can see everything on the browser webdriver treats each framew like its own window.  And you have to switch to that window to see the content.

The result is a lot of test code like this:

driver.frame('frameName')
.click('some locator')
.frame('back out of content')

Wherein we constantly have to switch into and out of frames in our tests.  And if someone forgets to switch back out tests might fail leaving a wake of very confused test engineers trying to debug.

We are going to expand our locator file to allow us to indicate if this element lives in a separate frame, and enhance our commands to automatically change into and out of a frame.  This will allow testers to write actions in peace without ever having to think of frames again.  Truly a marvelous future.

A way to automatically be able to validate any page has loaded correctly

Finally we are going to add our most powerful feature to date.  We are going to add a way through the locator files to “Tag” elements as being required for the page to be considered loaded.   Then we will write a new method that will be shared for all pages that automatically checks for every element thats required.

This gives us the opportunity to write easy smoke tests that checks every page of the application for missing elements.  It also allows us an elegant way in our test to wait for the page to load before proceeding, without resorting to ugly waits or polling functions polluting our pristine test waters.

Getting Our Hands Dirty

Now that we know what we want to do.  We can get down to the nitty gritty and build it out.  Let’s start with the page object collection.

Introducing the Page Object Collection

As mentioned above the goal for the page object collection is to give us a way to ask for any page we want and give us a fresh page object for it.   We can then include and initialize the page object collection in all of our tests.   And if we are clever we can give it a name like “on”.  This will result in our test code looking like this:

on.ebayHome().open()
.then(function() {
  return on.ebayHome().searchFor('orphans');
});

Much more readable.  The “on” makes it read like english, so even non programmers can get an idea of what the test is doing.

Creating the collection

We’re going to put our collection in the pages directory.  So to start we want to create a file called page_object_collection.js.   This is going to be a class, not a library, so it’s going to look a lot like our page object.

Screen Shot 2016-11-17 at 12.40.12 PM.png
Basic structure of page object collection
  • Note that we have to require all of our pages at the top of the file.
  • Just like a page we have a constructor that takes the driver in.  We save this driver so we can pass it to any page the user wants.
  • Finally we add a “prototype” function for every page.  In this case we made the function name camelCase to stick with javascript conventions

So if you had 10 pages you can add a method for each page.  Then in your test you can reference any page with the structure

on.<pageName>().<pageAction>()

Implementing the functions is easy as can be:

PageObjectCollection.prototype.ebayHome = function() {
   var self = this;
   var ebayHome = new EbayHome(self.driver);
   return ebayHome;
};
  • Here we use the same “self” convention just for good coding practices
  • We create the page object just like we would do in our test and then we return it.
  • If you are wondering, nothing being done here involves I/O so we don’t need to wrap anything in a promise.  We are simply instantiating a page, but that has no impact on the actual browser or WebDriver.io.

Our finished result (with a stubbed out function for another page we want to add looks like this:

Screen Shot 2016-11-17 at 12.46.49 PM.png
Page Object Collection Finished Product

Now that we have our collection, we should modify our test to take advantage.

Modifying the tests to use the collection

For now we’re going to stick with our “tests/better_testing.js” file.  But we don’t want to lose our old test, so we’re going to temporarily disable it, and create a new test underneath it.

You can disable a test in mocha by adding “.skip” after the it statement like so:

it.skip('Should open ebay and search for orphans', function() {

As mentioned in day 1, you can have multiple tests per describe block, so we can add a new test right underneath our first one.

Note:  be careful to ensure you are adding your new test after the ‘});’ that closes the it block.  A common bug is someone accidentally tries to add their test inside an existing test.

it('Should open ebay and search for orphans but better this time', function() {
  //Test will go here
});

Obviously before we can use our page object collection we have to define it somewhere, and because its a class we have to initialize it.  The first step here is require it:

var PageObjectCollection = require('../pages/page_object_collection');

Note again, because its a class and not a library we use Capital first letters to indicate to people.  This is a common Node code convention.

As we discussed, we want to store our collection in a variable named “on” for readability.  We can define on next to where we define our browser near the top of the test.

var driver;
var on;

Next we need to create a new instance of the collection and assign it to our “on” variable.  Since we need to pass the driver in on creating it, we should probably do this before every test.  (Since the driver is closed at the end of every test).

So near the bottom of our beforeEach we can do this:

  on = new PageObjectCollection(driver);

Now we are cooking with grease.  And we can re-write our previous test but this time using our collection.

 return on.ebayHome().open()
 .then(function(result) {
    return on.ebayHome().searchFor('orphans');
 });

Much more readable.

Our final result looks like this:

Screen Shot 2016-11-17 at 12.57.22 PM.png
Improved test using page object collection

Note: we shrunk some of the file to fit it all in the screenshot, don’t worry we still have our afterEach and first “it” test they are just minimized.

One goal down for the day 2 to go

Handling Frames Through the Locator File

Frames are a tricky thing, some engineers can go years without ever running across one while others must deal with them constantly.  Still building support for frames in your framework even if you don’t ever use a frame, could pay off down the line if you want to embed youtube or other site content suddenly. You’ll be able to support it with no effort.

To support frames we want to make it an optional field in our locator file.  Meaning if an element lives in a frame we want to add a field called “frame”:

 "topSearchBar": {
   "description": "Search bar at top of the page",
   "locator": "#gh-ac",
   "frame": "contentFrame",
   "groups": ["requiredForPage"]
 },

Thats it for the locator file.  Now we want to modify our custom commands, to check if a locator has a frame, and if so to switch into that frame before running the command.

We’ll start with our “click” method.

Here we’ll do some actual node coding.  To check if a field exists in an object we just do

if (locatorObject.frame) {
//locatorObject has a property or function called frame
}

Then we will take advantage of the WebDriver.io chaining ability and just add a method to switch to the frame before our click, and one after to switch back to the main frame.

 return resolve(driver.frame(locatorObject.frame)
 .click(locatorObject.locator)
 .frame(null));

note that we keep the entire chain inside the resolve statement to ensure our promise works.

Then, we handle the case if an element does not have a frame by adding a else statement. In which we call click as we did before.  The whole thing looks like:

Screen Shot 2016-11-17 at 1.50.19 PM.png
Updated click command with frames

And we can update setValue the same way

Screen Shot 2016-11-17 at 1.51.55 PM.png
Updated setValue command with frames

And that’s all there is to that.  Both methods will now handle switching into a frame for any element that requires it, and switches out when done.

Building Out the “waitForPageToLoad” Feature

Now we’ve come to our last new feature we want to add as part of Day 2.   The feature of waitForPageToLoad.  Building this we’ll get to learn some new concepts about promises, and programming through loops.

Adding a tagging system to our locator files

The first thing we want to do is to be able to tag elements in our locator file to indicate this element should be present before the page can be considered loaded.  To do this, we are going to add a new field called “groups”, this is going to be an array where we can put whatever group we want this element to be a part of.

Our group is going to be “requiredForPage”.

Why make it an array?  Because we might find other ways and reasons we want to group elements so in thinking ahead we want to support it right off the bat.

Since we only have 2 elements so far, and both should always be present on the EbayHome page we’re going to mark them both as required like so:

{
 "topSearchBar": {
 "description": "Search bar at top of the page",
 "locator": "#gh-ac",
 "frame": "contentFrame",
 "groups": ["requiredForPage"]
 },

 "topSearchButton": {
 "description": "Search button at top of page",
 "locator": "#gh-btn",
 "groups": ["requiredForPage"]
 }

}

Add a new custom command to wait for a single or group of elements to be visible

Our next step is to add a way to tell if an element is visible.  If we want to wait until all elements are loaded we’re going to need this.  As an added benefit these methods will be available for future uses as well.

We’ll build these by going off the existing “waitForVisible” command in WebDriver.io.  And we’ll add our own waitForVisible methods in our commands.js file.

Luckily the code is pretty much identical to the code for click, the difference being we change our console output and we call waitForVisible instead of click.

 

Screen Shot 2016-11-17 at 2.23.21 PM.png
New waitForVisible command

Note: because the code is so similar you can get away with copying and pasting, but I highly recommend you re-type it out.  First for that muscle memory learning, and second to encourage us to find ways to avoid duplicating code.   We don’t have time in this framework but we could build a simple helper that we just pass our method to that avoids all the duplicated code.

Now that we can wait for 1 element, next is we want to wait for a group of elements.  This will be a little more complicated.  We’re going to want to create a new command called
“waitForGroupToBeVisible”.

 waitForGroupToBeVisible: function(locatorGroup) {


 },

We’re going to assume someone has already compiled a group of elements into an array for us so we take a locatorGroup as an argument.

So we’ve done well with promises so far.  But in situations like this where we need to do multiple promises in a loop situation we need to use a special function our promise library has called “all”.

The “all” method in our library will take an array of promises, and run them all, and when it is finished it will return its own promise, with an array of results.  If any of the promises fail, it will fail as well.  The bonus is it runs through all these promises at the same time, which saves our program time as well.

var promises = []
promises.push(promiseFunction());
promises.push(promiseFunction2());

promises.all(promises)
.then(function(results) {
    //At this point we know all promises are done
});

Above is the basic form of using “all” for promises.

So we are going to use the same concept.  First we create an array to hold our promises

var promises = [];

Our next step is we want to loop through every locator in our locatorGroup and we’ll want to check each one if its visible.

locatorGroup.forEach(function(locator) {
    //Check if this locator is visible and push on promise array
});

This is an example of a “forEach” loop a very nice tool in Node/JavaScript.   It is a function that is called for each element of an array and for each element it will execute the function passed in.  Here it passes us a locator.

Our next step is to wait for it to load, which, lucky us, we just happened to write a function that does that!

locatorGroup.forEach(function(locator) {
    promises.push(module.exports.waitForVisible(locator));
});

So here were using a feature of arrays in javascript that we can add elements to an array with the “push” method.  We’re also using a feature that lets us call other functions  in the same library.  You can do this by appending module.exports.<functionName>.

So we basically go through each element call our waitForVisible method and store them all in an array of promises.  It’s important to note at this point in the code none of the promises have resolved they are all working at the same time.

So our final step is to wait until all promises are done.  Enter our “all” function.

return Promise.all(promises)
 .then(function(result) {
     return result;
 });

As we discussed in the last day, that “return” statement is critical, if left off the method will end before any promise has finished.

That’s it we can now wait for a single or group of elements!

screen-shot-2016-11-17-at-2-38-59-pm
New waitFor visibility elements

Write our waitForPageToLoad method

Now all thats left is to add a method to our page, that will find all the elements that are required and call our new custom command.

For now we are going to add it directly to our EbayHome page, but in a future post we’ll talk about how to make this method available to every page by default.

So we are going to edit pages/EbayHome.js and add a new internal function to findRequiredLocators.  And to add a new public method called waitForPageToLoad

var findRequiredLocators = function(locators) {

};

EbayHome.prototype.waitForPageToLoad = function() {

};

So what the hell is going on here, why do we have this new way of defining a function?  When we define a function through “var myFunction = function” we are limiting the scope of that function.  People using our Page Object in a test will not be able to access our findRequiredLocators function, but they will be able to call our waitForPageToLoad function.  Because we added waitForPageToLoad as a prototype of our class.

However waitForPageToLoad will be able to call findRequiredLocators because they are in the same scope.  It’s crazy but it will eventually make sense I promise.

Lets start with findRequiredElements.  In the page we already have all the locators stored in our “locators” variable.  But woe be unto us, the locators variable is not an array, its an object, with each property referencing a element.  Because of this, we cannot use forEach to loop through, because thats for arrays.

Instead we are going to use a helper library called “lodash”.  We store lodash in a variable called “_”.  Making sure to pull it in from a require statement.

var _ = require('lodash');=

LoDash has a very handy method called “forOwn” this will loop through all the properties of an object like a forEach loop.  It will give us two values (key and value).  The key is the name of the element and the value will be the locatorObject.

var returnArray = [];
_.forOwn(locators, function(locator, keyName) {

    //Now we can check if a locatorObject is part of the requiredForPage group
 });

To  check if a locator in our loop is part of the requiredForPage group is pretty simple

if (locator.groups) {
    if (locator.groups.indexOf("requiredForPage") !== -1 {
        //found a match
        returnArray.push(locator);
    }
}

So first we check if it even has the groups field, if it has no groups we know its not part of requiredForPage so we can do nothing.

Next we use a feature called “indexOf” this will return the index of an array that matches, if it can’t find a match it will return a -1.  You can think of this as saying “if locator.groups contains “requiredForPage””.

So we are saying if it doesn’t equal a -1 it means this locator does have this group.  In which case we push it onto our result array.

Finally when were done we just return our array, which now contains all elements that are part of the requiredForPage group.

screen-shot-2016-11-17-at-3-01-34-pm
New findRequiredLocators helper function

Once we have this method, our waitForPageToLoad method is trivial.  We just find our elements and pass it to our custom command.

Screen Shot 2016-11-17 at 3.03.38 PM.png
Our official waitForPageToLoad method

 

That’s it!  It took some work, but from now on anytime we want to check if a page is ready we can call this function, and any new page we can tag which elements are required with a few keystrokes.

For our final piece lets see how this looks at our test level.  We’ll go ahead and modify the new function we added earlier …

Screen Shot 2016-11-17 at 3.05.26 PM.png
Beautiful Isn’t It?

What’s Next?

So now hopefully we are starting to see some of the benefits of our framework.  We are going to do a special day 2.5 session next.  Which will exist outside of the meetups and only on this blog.   In that we are going to do one quick stop gap fix to create a base class that all of our page objects will sit on top of.

This is going to let us use that waitForPageToLoad method on all pages.

After thats added, for day 3, we will make some finishing touches on the UI framework.   And we will switch over and build a quick API Testing component to allow us to test APIs as well.

Truly we live in interesting times.  If you made it this far I commend you, and keep your ear to the ground for the next post which should come in a week or so.

 

 

Let’s Build A Framework – Day 1


 

Building Out the Bones of Our UI Automation Framework with WebDriver.io

Introduction

Hello to the West Denver Test Engineers, or to anyone out there who’s following along with our grand framework creation experiment.  This post, while very belated, will cover exactly what we did on Day 1.   We will talk about how you can check out Day 1 and see the end result.  Or you can check out Day 0 and follow along with the video posted earlier on this blog or you can follow along with this very blog post.

For this post we are going to assume you already read through the Day 0 Post and are set up and ready to create.  We will start with discussing the goals for the day, and go into how we build it.  Then, finally, we will discuss the purpose of what we built and potential uses for it for Day 2 and beyond!

The What: What We Want to Build Today

This section will cover what coding we actually did on day one, with pictures and more.

Ultimately we want to build a “Page Object Framework” which is a very common design pattern for UI Automation.

A Quick Understanding A Page Object Framework

The basic concept is we can divide any website or application up into individual pages.  We can sometimes further divide up that pages into smaller pages (think headers and footers).

Each page then has its own object associated with it.  This object stores the locators for all the elements on that page, and actions that you can do on the page.  This abstract breakdown of the application helps tremendously in writing easy to read and easy to maintain tests.

Think of a situation where you have 100 tests that all require a user to login.  Then one day a developer changes the login page.  You might find yourself in a situation where you have to update 100 tests.  Whereas if you stored all the details of a login page in a single object that the tests share.  You only need to update that one object and all your tests will magically work.

There are numerous components to build a successful page object.  Today we are going to focus just on this:

  1. Build a basic script with no framework to understand the basics of mocha, node and webdriver.io
  2. Create a locator file that stores information about what elements we want to interact with on a page.  (Stuff like buttons and text fields)
  3. Create a custom command library that can take on of our locators from our file and pass it through to WebDriver.io.
  4. Finally create a page object, which will be a class to represent a page in the application.  This will have easy to call methods representing actions you can perform on a page.  Actions like “login”, “searchForSomething” etc.

The How: Building It

Getting Set Up

Before we can start coding our framework we have a little foundational work to do to install, and set up our basic folder structure.

Please refer back to the Day 0 post for more specifics on everything you need to install.

Clone and enter our repo from git
git clone https://github.com/mustarddemon/westdenvermeetupfw.git
cd westdenvermeetupfw

Install and build everything
npm install
Start the selenium server (In a separate terminal)

In a separate terminal run the command for windows or mac, and leave it running.  When running tests for the remainder of this project we always want to make sure the server is running.

Windows

start_server_win.bat
Mac
./start_server.sh
Create our folder structure

The final set up piece will be to create a series of folders that we will use to divide our code up logically.  The structure is a main folder to hold our framework “mynewframework” and inside that folder create sub folders “lib”, “locators”, “pages” and “tests”.

Code below is for mac/linux but it assumed windows users can create their own folders

mkdir mynewframework
cd mynewframework
mkdir lib
mkdir locators
mkdir pages
mkdir tests

And that’s it, we’re ready to start building our framework!

Creating A Basic Test Without A Framework

The first thing we’ll want to do is just create a straightforward WebDriver.io test with no framework.  This is important to understand the basic structure, and also to serve as a reference to the advantages of our framework as we get further along.

Understanding Mocha

For our tests we are going to be using the mocha test runner.  As such were going to need to understand the basics of Mocha.  And how to set up a test file.

Mocha (for our purposes) is a behavior driven test framework.  It uses concepts such as “describe” to group a series of related tests together, and “it” to define a specific test.  This is so you can get test output like this:

Ebay Home Page – Should be able to search for an item

The way this looks in code form is like this:

screen-shot-2016-11-16-at-2-39-07-pm
Basic Mocha Test Structure
Understanding Basic Mocha

Looking at the above example you can see a pattern, where the first argument to a “describe” or “it” block is the description.  Each describe block can have multiple “it” blocks under it.  It can also have additional “describe” blocks to further group tests together.

The 2nd argument is whats called an anonymous function, this is a feature of the JavaScript language which Node is built on top of.   You can think of this function as the actual work that will be done.  Note the bottom two lines of the code above, the first closes out the “it” statement, and the 2nd closes out the “describe”.  The ‘}’ ends the anonymous function, and the ‘)’ ends the call to “it” or “describe”.

If you are coming to this having worked in a compiled language like Java or C# this can look a little strange.  But right now we can treat this as necessary “code  noise” over time it will make more sense.

Before and After Blocks

Mocha like most test runners also supports using Before and After blocks.  This allows to have some code that runs before the entire suite “before” or before each individual test “beforeEach”.  The way this looks in code is:

screen-shot-2016-11-16-at-2-46-48-pm
Mocha with a beforeEach method
The “done” function

The final aspect of mocha we need to be familiar with is the “done” function.  Node by its nature and mocha as an extension are asynchronous.  That means that whenever I/O is encountered (like reading a file, interacting with a browser, or calling an API) it is placed on a stack to be executed while control of the program continues on.

This asynchronous nature while making for very fast program execution, can be difficult in testing.  And since for UI testing almost everything done in the test is I/O the test can sometimes complete erroneously before the browser has even opened.

Mocha offers a couple solutions to this, one is that if a test is written using promises, it wont finish until the promise has resolved (this will be discussed in more detail below).  The other is a “done” function which serves as a “callback”.  What this means conceptually, is that a test is not considered completed until the “done” function is called.

The “done” function is passed in as an argument to any “it” or “before” or “after”
statement (which means any test).  Then inside the test the writer of the test can call “done” at a point when they know the test has completed.

In code this looks like:

screen-shot-2016-11-16-at-2-53-08-pm
Using done to ensure test completion

Note that done is passed in to our anonymous function, and called when we are sure the test or before actions are done.

You may be asking, who is passing a a “done” function in, and what is it doing inside that function.  The answer is that mocha is passing a function in.  That function determines test results and what to do next.  So when you call “done()” in your test, you are telling mocha to execute its end of test logic and move on.

Writing Our Basic Test File

Now that we have a basic understanding of mocha, we can write our first basic test file.  Our initial structure looks like this.  If you are following along at home, create a new file called “basic_scripting.js” under the “tests” folder.  And type this in.

Why Type?  You’ll notice that most code here is in an image format.  This is intentional to prevent copy/pasting.  By typing out the examples you will build muscle memory and it will immerse you in the learning experience.  Studies conducted by me, have shown people learn much faster when typing out the code initially.

Screen Shot 2016-11-16 at 2.57.53 PM.png
Initial structure for basic WebDriver.io test

Just like we discussed above, but we added one new thing a “require” statement.

Require Statements in Node

This is how we import libraries or classes in node.  Whether they are our libraries, or from a third party or build in libraries.  The behavior to pull one in varies slightly

Libraries Built By Us

//We need to pass the relative path from where we are currently
var myLibrary = require('./lib/myLibrary.js');

For our libraries we have to pass the path to the library.  This path is from the file we are currently in.  So in the above example if we were requiring this library from a file in the tests directory we’d have to change it to “../lib/myLibrary.js”  the “..” indicating we need to go up a directory.

Native or Third Party Libraries (Not Built By Us)

//We don't need to pass the path to the library just the name
var libraryName = require('libraryName');
Initializing WebDriver.io

We are now at a point where we can actually start a browser.   Below is the basic scripting test we will write.  We will break down whats happening below the image.

screen-shot-2016-11-16-at-3-18-32-pm
A basic vanilla WebDriver.io test

So what’s happening here?

  • First we define a variable object called “options”.  This object has a property called “desiredCapabilities” which itself is an object.  The “desiredCapabilities” object has a property called “browserName” which we define as firefox.  This is how we set the browser for our tests.  This options object is what WebDriver.io needs to get started
    • One of the advantages of Node/Javascript is the ease in which we can create new objects.  We can quickly create objects within objects, and can even give these objects functions!
  • Next we start by returning a command to webdriver.io.  If you’ll remember we pulled webdriverio in from our require statement at the top of the test.
    • We return as a way to stop the test from completing.  The test won’t complete until the entire return statement is finished.  In this case you can see we are “chaining” together multiple commands which finished at “end()”
  • The next command in our chain is “init()” this is where the browser is actually started.
  • The first command in our “chain” is “remote” this is telling webdriver to connect to the selenium server that we have running and use that to start our browser.  We pass in the “options” object, which tells it which browser we’d like to start.
  • The next command is “url(‘http://www.google.com&#8217;)” this is a WebDriver.io method that tells our browser to open that webpage.
  • Our final command is “end()” this tells the WebDriver.io and the selenium server that we are done and the browser can be closed.  This is also the end of our command chain so we terminate it with a “;”

That’s it we’ve created our first test.  You can explore all the different methods you can use with WebDriver.io here.  If you were so inclined you could start writing tests right away.  You know how to set up a test file and how to interact with webdriver.  You can call methods like “click” and “setValue” to type and click things on your web page.

Note: In truth you can get very far with just basic scripting.  The reasons for a framework are not immediately apparent.   Issues with basic scripting tend to happen months down the line after you’ve build your 100 tests and now you need to change something.  I encourage anyone to write a few fully scripted tests using this basic method.  It will not only help your understanding, it will help explain the features we are trying to give in our framework.

Wait?  How Do I Run the Test?

Ah, a key oversight!  To run the test use the following commands (after making sure the selenium server is running and you have run npm install).

Make sure you are in the mynewframework folder where we created our folder structure

mocha tests/basic_scripting.js

Creating a Locator File

It’s difficult to pick a starting point when building a new framework as many of the components tie in together.   That being said, a key feature of our framework is going to be storing a lot of knowledge about our pages in external language agnostic files.

This has numerous advantages which we’ll explore as we continue to build out the framework.

We are going to be storing our locators in JSON files.  This is because its easier to write than XML and its got native support in JavaScript/Node which will make parsing it in our code much easier.  But, in truth you could use any form of external storage for your locators.

Our basic layout is going to be an object, and in that object each property represents an element on the page.  For our example we’re going to use ebay.com.

First, we’ll create a new file called “EbayHome.json” and put it in our locators folder, then we’ll identify a few elements on the eBay home page we know we’ll want to interact with in our tests. In this case we’re going to use the search bar at the top of the page, and the corresponding search button.   Here’s what our file will look like initially.

Screen Shot 2016-11-17 at 9.39.47 AM.png
Basic locator file layout

You can see we give each element an easy to read name, and inside the object for the element we are going to store data on how to locate the element.  We are also going to include a “description” field.  This gives even more information about the element, and will allow us to make some very elegant test output.

In this experiment we are going to gloss over how to locate an element.  We are going to assume all elements are located through css.  But in later sessions we’ll discuss how to easily expand this to support xpath or any other locator method.

Here’s what our file looks like after we add information for our elements:

Screen Shot 2016-11-17 at 9.42.34 AM.png
Complete locator file

And that’s it.  While it may seem simple this locator file will allow us to add incredible features which we’ll discuss in future sessions.

Creating Our Own Custom Commands

Since we will be using our own locators pulled from our locator files.  We don’t want to use the straight WebDriver.io methods like click and setValue.  We instead want to make a wrapper method that takes our version of a locator and passes the correct locator information to the native WebDriver.io method.

We’re going to store all of our custom commands in a file called “commands.js” which we will put under the “lib” directory.  This file is going to be a library, that means its just going to be a collection of methods we can pull into any of our code with a “require” statement and call those methods.

To help make our code readable and understandable we’re going to use a NodeJs concept called “Promises”.  We’ll discuss further below what promises are and why we use them.  But our initial commands library will look like this:

Screen Shot 2016-11-17 at 9.49.26 AM.png
Basic custom commands library layout

There’s a lot happening here so lets break it down.

  • First we require “bluebird” this is a third party promise class that we will use.  Note that we store the required class in a variable called “Promise”.  The capitalization there is intentional, in Node the standard is when requiring a library that we use camel case, but when we require a class we use Uppercase.
  • Next we define a variable called “driver” this is going to hold the webdriver.  You can consider the driver to be essentially the browser, and it is the Native WebDriver.io code.
  • Next we create module.exports, this is how we tell Node which of our methods are public.  Anything inside module.exports you can reference when you require the library.
  • Inside module.exports we define a setDriver method.  This allows us to pass the driver in once and reuse it in all of our methods.  This will make our code more readable.  Notice that we take a passedInDriver, and assign it to our driver variable.  The nature of Node is that once something is “required” all subsequent “require” statements load the same library.  Meaning once we set the driver it will stay set even across different tests.
  • Finally we define some “stub” functions for click and setValue.  These both take a “locatorObject” in, this is going to be one of the elements from our locator file.  Now we can implement our commands.

How To Call A WebDriver.io Function

Before we can implement our custom function let’s look at how we would call it normally.

driver.click('locatorString');
driver.setValue('locatorString', 'text to type');

This is the base way to call a WebDriver.io method.   So we know our locatorObject has a locatorString property so we can modify this to be:

driver.click(locatorObject.locator);
//Our setValue function has a 2nd argument which is the text we want to input
driver.setValue(locatorObject.locator, textToType);

So far so good.  But lets take advantage of that description field we put in our locator object.   We can make it so every time our custom function is called it outputs a nice description so anyone running our tests can see in English what is happening.

click: function(locatorObject) {
 console.log('I am clicking ' + locatorObject.description);
 driver.click(locatorObject.locator);
 });

At this point our function will work, but using it will require tests to chain all methods together due to the nature of WebDriver.io.  We want to use promises to make our test code easy to write for anyone who might not have a lot of programming skills.

When using promises, we can wrap any non promise method in a promise and have it return that promise.  To do this we we immediately return a new Promise object.

return new Promise(function(resolve, reject) {
   //our method here
});

So what does this mean?  It means we immediately return the new Promise object, and we pass that object a new anonymous function.  That function takes itself 2 arguments resolve, and reject.  Both of these are also functions.  When we are sure our method is complete successfully we would call resolve, if an error occurred somewhere we would instead call reject.

This is how promises can enforce sequential behavior when dealing with asynchronous actions.

So we know we want to call “resolve” when our webdriver method is complete.  Luckily for us its as simple as:

return resolve(driver.click(locatorObject.locator));

That’s it.  Code using our promise wont move on to the next step until resolve is called, and resolve won’t be finished until the WebDriver.io click method is finished.

Putting it all together we get our finished commands file:

Screen Shot 2016-11-17 at 10.11.23 AM.png
Finished custom commands library

Now whenever we want we can expand our commands library to cover any WebDriver.io method.  Meaning any normal method you will call will now be able to have a nice output and use our locator objects from our locator file.

The advantages of this aside from the output are, that whenever we want to add a new feature to our locator object, we only need to modify these functions to support the new feature we don’t have to update anything else.

Some great features we’ll be adding later are:

  • Automatic handling of frames
  • Switching locator types between css and xpath
  • Grouping elements for automatic page load validation

Other features you could add

  • Alternate locators (great for mobile applications or applications where the locator changes between versions or users)
  • Automatic retry on failed actions
  • Checking for pop ups on failed actions (great for sites with ads)

Creating Our First Page Object With Locators

We’re so close now!  The final component of our framework is going to be a Page Object.  We are going to have a 1:1 ratio for page objects and locator file.  Meaning we need a page object called EbayHome.js to match our locator file EbayHome.json.  We’ll put this file in our pages folder.

This will allow us to automatically be able to reference all elements on a page.

The next thing we want our page objects to handle is what actions we are going to perform.  These actions are at a larger level then just click.  Think of actions like “logIn” or “searchForItem” or “waitForPageToLoad”.

Let’s start with a basic definition of our page.

Screen Shot 2016-11-17 at 10.19.53 AM.png
Basic page object class layout

So, again, a lot happening here let’s break it down.

  • First we require our handy Promise library like before
  • We also pull in our commands.js file we just made
  • And we define a “locators” variable.  This will store all the locators from our file.
  • Then we use the kind of funky way JavaScript defines classes.  It does so by defining a function with the class name.  This is the same as a “constructor” you would see in other languages.
    • Our constructor takes a driver in and assigns it to our driver variable.
    • It also loads the locator file and stores it in our locator object.
  • Then we define some “public” methods for our class to have.  to do this we use “prototype” syntax followed by the method name.  Here is where we will implement our actions.
  • Finally we set module.exports to our class.  This is what will allow us to create new pages.

Note: unlike libraries, classes in javascript need to be created with a “new” command, and doing so will create a fresh copy each time.  Meaning that each time we will have to pass a driver in and anything changed in the class will not be preserved across instances of that class.

Now for the fun part actually stringing together some actions to do something on the browser.

First we want an “open” method, this will load the url for the home page.  Unlike click and setValue we havent implemented a custom command for open yet. So we’ll just wrap it in a promise like before:

EbayHome.prototype.open = function() {
   var self = this;
   //open the ebay home page
   return new Promise(function(resolve, reject) {
      return resolve(self.driver.url('http://www.ebay.com'));
   });
};

So what’s the deal with the “self” variable?  JavaScript does some interesting thing with scoping, so its just a good practice to create a variable called self and assign it to “this”.  I won’t go into more detail you can just think of it as some necessary code noise.

The rest of the method is just like our custom commands, we just wrap the built in WebDriver.io method in a promise.

The next method “searchFor” we get to use our custom commands though:

EbayHome.prototype.searchFor = function(textToSearchFor) {
   // type something and search for it
   var self = this;
   return commands.setValue(self.locators.topSearchBar, textToSearchFor)
   .then(function() {
     return commands.click(self.locators.topSearchButton);
   });
};

So you can see we can call any of our custom commands just by using “commands.<method name>”.

Another nice feature here, is because we know our commands methods are already returning promises, we don’t need to wrap them in one, we can just return the method.

So what about this “then” business?  This is the key part of why we are using promises.  Anytime you are working with a function that returns a promise, you can call call “then” and pass a function to it.  That function passed will only be executed after the previous promise is resolved.  This means we can guarantee our actions happen sequentially.

This is called a “promise chain” meaning we can string together however many actions we want and have them execute in sequence.

//Typical Promise Chain Structure
return somePromiseFunction()
.then(function(resultFromFirstFunction) {
    return someOtherPromiseFunction();
})
.then(function(resultFromPreviousFunction) {
    //and so on and so forth
});

If you are new to Node this may seem strange, but you might still see the value of syntactical structure of the code.   “Do something THEN do something else THEN etc …”

Note:  The return statements are absolutely critical with promises.  Because of the nature of Node, if it sees a return statements it stops execution in that method until all promises are resolved.  If you left out a “return” Node would asynchronously run the promises and continue execution to the next command.  Meaning it would get to the end of the function and finish before the promises had finished.

Let’s look at our finished product:

Screen Shot 2016-11-17 at 10.38.00 AM.png
Finished page object class

Now we can create as many Pages as we want to map out the entire eBay site, and we can make as many actions on each page.  So that when it comes time to write tests all the hard work has been done for us!

Tying It All Together With A New Test

We’ve reached the promise land, time to write our first test using our framework.

Note: Be prepared to be underwhelmed, our new test will not be that much cleaner, but remember this is just day one.  In the coming days we will add more features to make our tests cleaner and easier to run.

We already have our “basic_scripting.js” file in our “tests” directory.  Let’s create a new file for our new framework style test called “better_scripting.js”.  We’ll give it a basic mocha structure:

Screen Shot 2016-11-17 at 10.41.32 AM.png
New test file layout

A couple things to point out before we go further.

We added a beforeEach and afterEach method.  We are going to use these to automatically start our browser and shut it down when the test is done.

We also added a “this.timeout(30000)” this is a feature in Mocha.  By default it times out a test after 2 seconds, so we are expanding it so it will kill our tests after 30 seconds instead.

Finally we added some new “require” statements we are pulling in our EbayHome class.  This is going to allow us to create a new version of the page and call our handy methods.  And we pulled in our custom commands, this is so we can set our driver in it at the start of our test once we’ve initialized it.

First though, lets move our initialize webdriver code into our beforeEach method.

 beforeEach(function(done) {
   var options = {
     desiredCapabilities: {
       browserName: 'firefox'
     }
   };

   driver = webdriverio.remote(options)
   .init();
   commands.setDriver(driver);
   return done();
 });

So this is essentially the same code as in our “basic_scripting.js” but we call the “done()” method when we are done to ensure we don’t start the test before the browser loads.

Our “afterEach” method is even simpler.

afterEach(function() {
   driver.end();
});

That’s it, it will close the browser after each test.

Now to the big moment.  We can write our new test using page objects:

First we want to create a new EbayHome page so we can use it.

var ebayHome = new EbayHome(driver);

Then we can call and chain any methods on the page together:

 return ebayHome.open()
 .then(function() {
    return ebayHome.searchFor('orphans');
 });

Now we only have 2 methods, but you can imagine if you had multiple page objects, and methods you could write a pretty impressive test.

Lets see the finished product:

Screen Shot 2016-11-17 at 10.56.47 AM.png
Finished test file

Wait?  How Do I Run the Test?

Ah, a key oversight!  To run the test use the following commands (after making sure the selenium server is running and you have run npm install).

Make sure you are in the mynewframework folder where we created our folder structure

mocha tests/better_scripting.js

 

It’s still not super pretty and easy to use.  But by the end of day 2 all of that will change!

So stay tuned, and watch this space!

img_2055

Let’s Build A Framework – Session 1 Recap


Great big thanks to everyone that came out and joined us for our kickoff session around building frameworks for automation. As mentioned, we were able to record the screencast of this session, and I wanted to get this posted for everyone to take a look at and view (or review).

GitHub Page

Meetup Page

img_2057

Let’s Build a Framework – Day 0


Building An Automated UI and API test framework

A big hello to anyone from the West Denver Test Engineering meetup who came to this page in preparation of attending or watching the 3 part discussion on building an Automated Testing framework for API and UI testing.  And to anyone who has just stumbled across this page a big hello to you as well.

For this blog post we will focus mainly on getting set up prior to the meetup or prior to watching the videos to build your own framework.  We will talk about what tools we will be using, and what you need to install.  In preparation for this I have created everything locally to ensure it works, but have done so on a Mac.  We will include information on how to install and run on a Windows machine as well, however these instructions have not been tested as of yet.  As we get feedback I will endeavor to keep this up to date with the most recent information on tools and installation for both Windows and Mac.

If you’re a Linux user, then you are probably used to trudging up the hard road so good luck to you.  Actually, in all seriousness the steps for the mac should be very similar for Linux users so try to follow those.

The Tools We Will Need

The framework we will be building is meant to be a hybrid framework to allow for testing of APIs and UI, and potentially mix the two together for some tests.  We will be using the following tools and languages as part of building, so please follow the instructions for each tool below to ensure you are set up.

If you are using a mac it is strongly encouraged to install homebrew which will allow you to install many of these tools through the command line with a simple command.  For Linux users similar installers such as yum and apt-get are recommended.

Continue reading “Let’s Build a Framework – Day 0”

Retesting Vs. Regression Testing | Software testing Blog.


A great article on the two different types of testing that people often get confused with each other.

How is re-testing different from regression testing? Is there a difference at all? Is regression testing a subset of re-testing? Quite a few times, testing teams use these two terms interchangeably. However, there is a vast difference between these two types of testing. Let us have a look – Regression Testing Re-testing Definition Regression testing…

Source: Retesting Vs. Regression Testing | Software testing Blog.

Testing vs QA


I wrote the article on Medium a while back, and forgot to link it here.

Turns out, it’s getting some traffic today…thought I should go ahead and get it posted. Be sure to check out the comments, as there is a good discussion happening there too.

Testing vs QA

Fostering Growth


One of the biggest frustrations I have run into as a member of an organization is how the leaders grow their employees. In my entire career, I have only had two leaders mentor me in such a way that I felt like I was growing as both an employee, as well as a person. Why there were not more people doing this, I will never understand. If you want to build an organization that is strong, it only makes sense to develop the next level of people below you in order to ensure that this happens consistently. This Harvard Business Review article says it best:

Regardless of what else you expect from your managers, facilitating employee learning and development should be a non-negotiable competency.

So how do you do this? How do you become a manager that people want to work for, and more importantly, how do you develop those people into the next wave of leaders in your organization? The first thing to realize is that there is no magic bullet. There is no secret recipe for success that is 100% repeatable. Instead, there are some key principles that you should keep in mind, and strive to work towards.

People vs Resources

I’m not talking about using resources other than people, but rather how you look at the people you have. Do you treat them like a resource to use as needed, or do you treat them as human beings, and use the individual/unique skills they bring to the table? Having the ability to recognize people for the unique individuals that they are is a lot tougher than it sounds, and takes deliberate and intentional effort. It is far easier to see them as a resource with skills that are defined by a job description, but that does not do anything to further the person, nor does it truly help further the organization. When you just throw resources at a problem, eventually you will run into a scaling problem.

Personal Interactions

When you connect with people on a personal level, they feel valued, and their desire for success, as well as their level engagement go up. In every position of authority I have ever been in, I have gotten the best results out of the people I was able to connect with on a personal level. This not a simple matter, and it is likely that you will have people on your team that you just can’t connect with. This is one of the key reasons why cultural fit is such an important part of the hiring process. When you spend as much time with your coworkers as you do your own family, you naturally want to enjoy that time (and conversely, your employees want the same thing). Having this feeling of camaraderie and friendship will lead the members of your team to want to do better by each other, and will result in a much higher level of efficiency.

Career Development

The resources on your team, regardless of where they are at in their career, need to be treated as a plant would be. They need fed and nurtured on a regular basis in order to keep them healthy and productive. One of the ways I like to do this is by sitting down with each person and outlining where they want to go in their career, and then take that and work with them to put together a list of goals for them to work towards. These goals should be S.M.A.R.T., should be a mixture of individual and teams goals, and should be measured on a quarterly basis at a minimum (I like to review during monthly 1-on–1’s). By including the employee in the process of creating the goals, you enable them to take ownership of their career, and thereby fostering better engagement on their part.


I know a lot of this seems pretty simple and basic on paper, but it is surprisingly difficult to accomplish in reality. The key is to make a deliberate choice with each and every employee to connect with them on their level, and be genuine in your conversations with them. You won’t win them all, but trust me, word will get around, and you’ll find that people are wanting to come to your team or organization. It’s not easy, and there are definitely some bumps along the way, but you will find it all that much more rewarding!

Building for the Future


One of the hardest things in a leadership position is figuring out how you want to build and structure your team. It makes sense then that your hiring process is an important part of this. Identifying talent inside of an organization is hard enough on it’s own, but trying to evaluate a complete stranger from nothing but a resume and a conversation is difficult at best, and usually far tougher than that. So, given that this is such a difficult process, what is the best way to find and identify those people that will move your organization forward?

If you’re me, you start the process by asking about their Tetris experience. I’ve been asking this question for years, and while I have often taken flak (the good-natured kind!), it has thus far proven to be a very effective barometer of a candidate’s critical thinking ability, as well as their ability to quickly problem-solve. From my perspective, these are the most important qualities a person can bring to the table, and are absolutely crucial if you want to build a nimble and agile team that is capable of functioning at a high level.

Another key characteristic that I look for, is their ability to fit in culturally. When I interview someone in person, I am most concerned with how well they connect with me, as well as the rest of the team. For us at HomeAdvisor, a candidates ability to fit in culturally is just as important as their technical abilities, and in some cases, even more important. We are in the midst of transitioning from a startup-type of environment to one where there are multiple delivery teams, and we need to have people that are capable of taking the QA direction and focus and integrate it within their teams.

Finally, the last key thing that I look for in a candidate is their passion and enthusiasm for QA. I want people on my team that are genuinely excited to deliver quality software. I want people that are engaged in the local meetups and communities in the area, and want to broaden their skill set. I want people that want a career in QA, not just a job.