Book Review: The Way of the Web Tester

As any regular reader of this blog will know, this year I’ve been reading and reviewing one testing-related book a month. Well, I’m cheating a bit this month! I’m currently reading a very long book that I knew would take me two months to read (Want to know what it is? Check back in with me in four weeks!), so this month I’m reviewing a book that I read a couple of years ago: “The Way of the Web Tester” by Jonathan Rasmusson.

“The Way of the Web Tester” is the book I recommend for manual testers who want to learn the basics of automated testing. It’s a friendly, accessible book that gives readers both the “big picture” about automated web testing and the details about how to implement it well.

The book is organized in two parts: Part I describes the basics of how automated testing works, and Part II is devoted to helping people who are new to programming understand good coding techniques.

In Part I, the author begins by explaining the automation test pyramid, and then describes each level of the pyramid from top to bottom. He begins with the top level of the pyramid because that’s the most accessible to manual testers, and this idea makes a lot of sense; when you’ve been testing a system by going to the web page and clicking buttons, it’s easy to transition to automation that goes to the web page and clicks buttons!

The author then moves to integration tests, explaining how HTTP and REST requests work, and then to unit tests. Finally, he gives examples of how the all the tests can work together to test an entire system. I really like how he emphasizes that developers and testers should be working together to create test automation, so that work isn’t duplicated.

My favorite part of Part II is the Programming 101 chapter, where important practices such as choosing good variable names, spacing code, and using the DRY (Don’t Repeat Yourself) principle are discussed. These are so valuable to people who are new to coding.

Another thing I love about the book is the use of two cartoon characters. They are “Tim the Tester” and “Diane the Developer”, and they pop up throughout the book, asking questions that the reader might be wondering, such as “How do I know if I’ve written enough tests?”

If you are new to automated testing, or if you’ve struggled with it in the past, “The Way of the Web Tester” is definitely a book you will want to read. But it’s not just for beginners! I learned a number of things from the book as well, such as how mocking works and how to write unit tests that test UI elements. It’s a great, easy-to-understand book for anyone who’d like to make their test automation more robust.

Using DevTools Search to Locate WebElements

Recently, I took this great course on Locating Web Elements from Andrew Knight, through Test Automation University. In addition to learning helpful syntaxes for accessing elements, I also learned about yet another way we can use DevTools to help us!

One of the most annoying things about UI test automation is trying to figure out how to locate an element on a page if it doesn’t have an automation id. You are probably aware that if you open the Developer Tools in Chrome, you can right-click on an element on a Web page, select “Inspect” and the element will be highlighted in the DOM. This is useful, but there’s something even more useful hidden here: there’s a search bar that allows you to see if the locator you are planning to use in your test will work as you are expecting. Let’s walk through an example of how to use this valuable tool.

Let’s navigate to this page, which is part of Dave Haeffner’s “Welcome to the Internet” site, where you can practice finding web elements. On the Challenging DOM page, there’s a table with hard-to-find elements. We’re going to try locating the table element with the text “Iuvaret4”.

First, we’ll open DevTools. The easiest way to do this is to right-click on one of the elements on the page and choose “Inspect”. The Dev Tools will open either on the right or bottom of the page, and the Elements section will be displaying the DOM.

Now, we’ll open the search bar. Click somewhere in the Elements section, then click Ctrl-F. The search bar will open below the elements section, and the search bar will say “Find by string, selector, or XPath”.

We’ll use this tool to find the “Iuvaret4” element with css. Right-click on the “Iuvaret4” element in the table, and choose “Inspect”. The element will be highlighted in the DOM. Looking at the DOM, we can see that this is a <td> (table data) element, which is part of a <tr> (table row) element. So let’s see what happens if we put tr in the search bar and click Enter. It returns 13 elements. You can click the up and down arrows at the side of the search bar to highlight each element found. The first “tr” the search returns is just part of the word “demonstrates”. The next “tr” is part of the table head. The following “tr”s are part of the table body, and this is where our element is. So let’s put tbody tr in the search bar and click Enter. Now we’ve narrowed our search down to 10 results, which are the rows of the table body.

We know that we want the 5th row in the table body, so now let’s search for tbody tr:nth-child(5). This search narrows things down to the row we want. Now we can look for the <td> element we want. It’s the first element in the row, so if we search for tbody tr:nth-child(5) td:nth-child(1) we will narrow the search down to the exactly the element we want.

This is a pretty good CSS selector, but let’s see if we can make it shorter! Try removing the “tbody” from the search. It turns out the element can be located just fine by simply using tr:nth-child(5) td:nth-child(1).

Now we have a good way to find the element we want with CSS, but what happens if a new row is added to the table, or if the rows are in random order? As soon as the rows change we will be locating the wrong element. It would be better if we could search for a specific text. CSS doesn’t let us do this, so let’s try to find our element with XPath.

Remove the items in the search bar and let’s start by searching on the table body. Put //tbody in the search field and click Enter. You can see when you hover over the highlighted section in the DOM that the entire table body is highlighted on the page.

Inside the table body is the row with the element we want, so we’ll now search for //tbody/tr. This gives us ten results; the ten rows of the table body.

We know that we want to select a particular <td> element in the table body: the element that contains “Iuvaret4”. So we’ll try searching for this: //tbody/tr/td[contains(text(), “Iuavaret4”)]. We get the exact result we want, so we’ve got an XPath expression we can use.

But as with our CSS selector, it might be possible to make it shorter. Try removing the “tbody” and “tr” from the selection. It looks like all we need for our XPath is //td[contains(text(), “Iuvaret4”)].

Without this helpful search tool, we would be trying different CSS and XPath combinations in our test code and running our tests over and over again to see what worked. This Dev Tools feature lets us experiment with different locator strategies and get instant results!

Adventures in Node: Default Parameters

As you have read in my previous posts, I’ve been taking this amazing course on Node.js. I have found that deeply learning a coding language has really helped me in my testing. In previous years I had learned just enough of a language to get by; now I see the value of really understanding a language!

One of the fun things I’ve learned in this Node.js course is the concept of default parameters. When we create a function, we usually include whatever parameters need to be passed into the function, like this:
const greeting = (name, hometown) => {
console.log(‘Hello, ‘ + name + ‘! How is the weather in ‘ + hometown + ‘ today?’)

Then when we call the function, we need to include arguments for those parameters in order for the function to run:
greeting(‘Kristin’, ‘Boston’)
and we’ll get this response:
Hello, Kristin! How is the weather in Boston today?

But what if you’re going to use this function a lot, and most of the time you’ll be passing in the same arguments? Won’t you get tired of typing in those arguments every time?
This is where default parameters come in!

When we create our function, we can set one or more parameters to have a default argument, like this:
const greeting = (name = ‘Kristin’, hometown = ‘Boston’) => {
console.log(‘Hello, ‘ + name + ‘! How is the weather in ‘ + hometown + ‘ today?’)

Now we can call the greeting function without passing in any parameters:
And we’ll get this response:
Hello, Kristin! How is the weather in Boston today?

If we want to set the first argument to something different, we can call
And we’ll get this response:
Hello, Joe! How is the weather in Boston today?

If instead we want to set the second argument to something different, we can call
greeting(undefined, ‘Seattle’)
And we’ll get this response:
Hello, Kristin! How is the weather in Seattle today?

Or we can decide to replace both arguments, by calling
greeting(‘Joe’, ‘Seattle’)
And we’ll get this response:
Hello, Joe! How is the weather in Seattle today?

It’s really very simple once you see how it works. Think about how many times you’ve gotten tired of typing the same thing over and over in your code, and how many times you’ve accidentally missed a single quote or a comma. Typing () without having to fill in any arguments can really save time over the long run!

Dealing With Change

Anyone who works in the Software Industry knows that at some point they will need to cope with change. Consider the move from desktop computers to laptops, or from BlackBerry devices to iPhones. We all want advancements in software, but sometimes that means that we will need to change what we do. Have any of the following stories happened to you?

  • You are the sole QA Engineer on a software team, responsible for testing everything the developers create and writing test automation. Now your manager is telling you that the whole team should own quality, and that the developers will be testing each other’s work and writing automation. Your job is to the be the Quality Coach.
  • You have written UI automation for years, and your product has hundreds of UI tests. But there is a new policy that says you can only run a single end-to-end UI test, and the rest of the tests should be unit, integration or API-based.
  • You are a Selenium champion; you know how to locate even the trickiest elements. But your company has decided to support Cypress instead. You have always written your tests in Java, and you don’t have any experience with JavaScript.

It’s hard for everyone to deal with change! In this post, I’ll outline seven steps for dealing with the inevitable changes you’ll encounter working on a software team.

Step One: Don’t panic
This step is good advice for practically everything. While it may seem that the changes on your team are cataclysmic, and you won’t possibly be able to adapt, remember that changes usually don’t happen overnight. You will have time to learn whatever new strategies you need to deal with the change.

Step Two: Have a (very short) pity party
Often the changes that are thrust upon us are not changes that we agree with. We may think that our company is going in a terrible direction, but our warnings have gone unheeded. Whenever a change happens that I’m not happy with, I take 30 minutes to an hour to pout about it. I feel really sorry for myself. Then I tell myself that there’s nothing I can do about the change, and that I need to begin to move on and adapt. Taking some time to mourn can give you the emotional energy to move forward.

Step Three: Set an achievable goal
One thing that can really help us cope with change is to set a goal to work towards. It gives us a feeling of control and something that we can look forward to. In the case of the third example above, a person who is a Selenium expert can set a goal to take a course on JavaScript or Cypress in the next month. As you gradually learn something new, you’ll feel more like you can cope with the change.

Step Four: Do a little at a time
Remember that change doesn’t happen overnight. Moreover, you’ll still likely have your usual work responsibilities while your organization begins to change. Set a goal for yourself to work just a few minutes a day on learning a new skill, adapting an existing test, or trying a new strategy. Little changes each day can add up to big results.

Step Five: Use the magic of the Internet
When I was first learning test automation, there were very few resources out there to help me learn. Things are SO different today! Whatever you need to learn, I guarantee that there is a course out there that can help you learn it. And if you don’t like the course you’ve found, you can find a new one that works better for your learning style. Consider using Pluralsight, LinkedIn Learning, Udemy, W3 Schools, or Test Automation University, to name just a few great learning sites.

Step Six: Ask for help
Sometimes people in technology feel that they need to be seen as knowing everything. This is so dangerous! The best coders and testers I’ve known are the ones who ask lots of questions, and who aren’t afraid of looking silly for not knowing something. When I ask a question in a technical meeting, nine times out of ten I find that most of the other people in the meeting were wondering what the answer was themselves, and they were just too timid to ask.

One caveat to this step, however, is that you should always try answering questions and solving problems yourself before asking for help. Don’t be that person who gives up and says they can’t do it on the first try! If you work on a problem on your own for a while, you may find that you can arrive at the answer yourself, which is a great confidence-builder.

Step Seven: Buddy up
No one works in a vacuum! We are part of software teams so that we can help each other. If you learn best by learning with a group, assemble a group of people who need to learn the same thing that you do and work together. This is especially helpful when you are learning a new coding language. People can share the problems they’ve solved so that no one has to “reinvent the wheel”.

The one thing that’s constant in life is change. By applying these seven steps, you’ll be able to cope with any change your company or team presents you with.

Book Review: Accelerate

As you know, I’ve been reading one technology book a month and reviewing it in this blog. For the month of September I read “Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations” by Nicole Forsgren, Jez Humble, and Gene Kim.

You may have heard of this book, because it has become an industry standard in the discussion of how teams can deliver quality software more quickly. After reading the book, I see why it is so well accepted.

Part I of Accelerate consists of the findings of the authors based on a worldwide survey they conducted of software teams. They performed statistical analyses on the results and arrived at the following conclusions:

  • High-performing software teams have:
    – more frequent code deployments
    – faster lead time from commit to deploy
    – faster mean time to recover from downtime
    – a lower change failure rate
  • There is no tradeoff between improving performance and achieving higher levels of stability and quality- you can do all three!
  • Teams can improve their performance, stability, and quality by:
    – creating comprehensive test and deployment automation
    – setting up continuous integration
    – shifting left on security (meaning, testing security while features are being developed)
    – managing test data
    – using loosely coupled architectures
    – working independently (able to deploy without being dependent on other teams)
    – using version control on everything, including build scripts

Part I is really the meat of the book. You can read this part and get what you need to know about creating a high-performing software team.

In Part II, the authors dive into the details of the research they did, from choosing the questions, to finding the people to survey, to using statistical methods to analyze the results. I think you can safely skip this chapter unless you are doubtful of the validity of the results in Part I.

Part III contains a chapter with two guest authors who are lean IT practitioners. They describe what a banking institution’s software development team looked like after they had adopted the strategies in Part I. I was a bit confused by the jargon they used and put off by some of the irrelevant details (for example, what the office space looked like- not particularly important in 2020 when so many teams are working remotely!).

Finally there are three appendices. Appendix A consists of a summary of Part I, which is really helpful if you want quick access to all the ideas. Appendices B and C discuss the statistics and statistical methods used in analyzing the survey data. You can safely skip these sections unless you are a statistician.

Accelerate is a great book for anyone who wants to help their organization deliver quality software quickly. If you are trying to make changes to your team in order to implement CI/CD practices and your manager is resistant, I highly recommend giving them this book. It’s clear from the survey results that the strategies outlined here will help teams become high-performing.

How to Use Breakpoints in Dev Tools- Part II

Last week, we started to take a look at the different kinds of breakpoints we can use in Dev Tools to debug JavaScript applications. We tried out some breakpoints- Line of Code, Conditional Line of Code, and DOM- using Dev Tools and a simple counter application. This week we’ll continue the adventure with three more breakpoints! If you’d like to follow along, go to last week’s post and follow the setup steps.

XHR Breakpoint

XHR stands for “XMLHttpRequest”. It’s a way to request data from a server without having to reload the webpage. You can create a breakpoint that will pause the code whenever an XHR request is made. To set this up, look in the right panel of the Dev Tools (making sure that you’re already on the Sources tab), and open the section called “XHR/fetch Breakpoints”. Click the plus (+) button in the section, and check the box that says “Any XHR or fetch”. (If you don’t see the checkbox and instead see an empty text box, click out of the box, and the checkbox should appear.)

We now have a breakpoint set up that will be executed whenever any call is made to the server. To trigger this in the Counter App, click the trash can icon for every counter so they are all deleted. Then click the blue recycle button. A server call will be initiated, and you’ll see the code pause on the breakpoint.
Don’t forget to click the Resume button and remove the breakpoint before the next section!

Event Listener Breakpoint

As you might imagine, the Event Listener breakpoint listens for a particular event, such as an animation, a keyboard entry, a mouse movement, and so on. We’ll set up a breakpoint to stop on a mouse click. In the rightmost panel of Dev Tools, open up the Event Listener Breakpoints section, and click on the arrow next to “Mouse” to open that section. Check the “click” checkbox. Now when you click on one of the buttons, you’ll see the application stop on the breakpoint.
Don’t forget to remove the breakpoint and click the Resume button before the next section!

Exception Breakpoint

This breakpoint can be set to stop whenever the code encounters an exception, and you can specify whether you want to pause on all exceptions, including caught exceptions, or just uncaught exceptions. To set this breakpoint, simply click on the blue pause button in the upper right corner of Dev Tools. Let’s also click the “Pause on caught exceptions” checkbox. To trigger an exception in the Counter app, click the trash can icon for all the counters, then click the blue recycle button. This triggers an exception on my Safari browser which pauses the code; looking at the code it seems to me that the exception is browser-specific, so your results may vary.
Don’t forget to remove the breakpoint and click the Resume button before the next section!

Stepping Through the Application

Breakpoints are great for pausing an application so you can see what state it’s in, and they are also good for stepping through the code. To learn how to step through the code, let’s go back and use a simple Line of Code breakpoint like we learned how to do in last week’s post. So make sure the “Sources” tab is selected at the top of the Dev Tools pane, find the src folder in the left section of Dev Tools, then open it up and click on the App.js file. Find line 16 in the file and click on it to add a breakpoint.

Click one of the plus (+) buttons in the application, and the breakpoint should stop on line 16. This time instead of clicking on the Resume button, click on the button next to it. This is the Step Over button, and it will send the code execution to the next line of code in App.js. Open up the Scope section and you can see the value of all the variables at this particular place in the code. As you continue to click on the Step Over button, you’ll be able to see the counter value change. Look in the counters: Array(4) section, and you’ll see that the specific counter you are using will go up in value.

Between this tutorial and last week’s, you now know six different ways to set a breakpoint in Dev Tools. I hope that you will find them useful when you are trying to diagnose tricky JavaScript bugs. Happy bug hunting!

How to Use Breakpoints in Dev Tools- Part I

The modern software development team is beginning to blur the traditional lines between developer and tester. This means that developers are starting to get more involved with writing test automation at all levels of the pyramid, and it also means that testers are starting to get more involved with the inner workings of an application. Wouldn’t it be great if you were able to find the causes of JavaScript bugs rather than just reporting on them? Using breakpoints in Chrome’s Dev Tools is a great way to do this!

In this post, I’ll be leading you through a hands-on tutorial on using Chrome Dev Tools for debugging. I learned this information from this helpful Google blog post, but I’m using an example application so you can try the various breakpoint methods yourself.

It’s important to note that in order to use these breakpoints, you’ll need to have your application installed locally. You can’t just go to a deployed version of your company’s application and debug it. This post shows you how to run a sample React application locally; you can work with your developers to get your team’s application running locally as well.

Getting Started

To follow along with this post, you’ll need to have Node.js and Git installed. Then you’ll need to clone this repository. If you’ve never cloned a repository before, you can find instructions here. This repo is a very simple counter application that could be used for something like adding items to a shopping cart. It doesn’t do much, but it does enough that we’ll be able to try out some breakpoints with it.

Once you’ve cloned the repository, then you’ll need to do the following:
cd counter-app This moves you to the application folder.
npm install This gets all the packages needed to run the application and builds it.
npm start This starts the application.
You should see the application open up in your Chrome browser. It will look like this:

Next you’ll need to open up Dev Tools. You can do this by using the three-dot menu in the upper-right corner of the Chrome browser. From that menu, choose “More Tools”, and then “Developer Tools”. The Dev Tools will open at the side of the browser, and will look something like this:

We are now nearly ready to begin! With each type of breakpoint, we’re going to set it, watch it work, press the “Resume script execution” button, then clear the breakpoint. The “Resume script execution” button is found at the top of the right-most panel, and looks like this:

To clear a breakpoint, simply right-click on it, and choose “Remove breakpoint”. Let’s get started!

Line of Code Breakpoint
The line of code breakpoint is the most commonly used breakpoint. When the application code is executing and it arrives at this line, the code execution will pause. You can use this pause to analyze the current state of the application, from what is visible to what the variable values are.

If the “Sources” tab is not already selected at the top of the Dev Tools pane, select it now. Then look in the left section of Dev Tools to find the src folder, and inside that folder, click on the App.js file. The App.js file will open up in the center pane of Dev Tools.

Now find line 17, and click on the line number. The number will be highlighted with a blue arrow like this:

This line of code is in the handleIncrement function, which is the function that is called when you press one of the plus (+) buttons in the application. Press a plus button now. You should see Line 17 highlighted, and a message in the rightmost pane that says “Paused on breakpoint”. While you are paused, you can look at the Call Stack and Scope sections to learn more about what’s happening in the application at this moment.
Don’t forget to remove the breakpoint on line 17, and click the Resume button before going on to the next section!

Conditional Line of Code Breakpoint
Now let’s try out a conditional line of code breakpoint. This is a breakpoint that only executes if a certain parameter has been met. Right-click on line 19 of the App.js code, and choose “Add conditional breakpoint”. A breakpoint will be added, and there will be a little popup window where you can add your condition. Add this condition: index === 0 and click the Return or Enter key.

Now that the conditional breakpoint has been set, let’s see it in action. If you haven’t clicked any other buttons since the previous exercise, you should have a counter that is currently set to 1. Click the plus button again. The code execution won’t stop at the breakpoint, because the counter is currently set to 1. Click the minus button () to return the counter to Zero. Now click the plus button again. This time the code execution will stop at the breakpoint, because the current condition of the counter at line 19 is Zero.
Don’t forget to remove the breakpoint on line 19, and click the Resume button before going on to the next section!

DOM Breakpoint

It’s also possible to set a breakpoint directly in the DOM. To do this, we’ll first click on the Elements tab in the top bar of Dev Tools. Change the topmost counter from 1 back to Zero. Now right-click on that Zero counter and choose “Inspect”. The center pane of Dev Tools will navigate to and highlight the section of the DOM where this counter exists. Right-click on that highlighted section and choose “Break on” and then “Attribute modifications”. When this counter moves from Zero to 1, it changes attributes (namely, the color), so by selecting “Attribute Modifications” we are telling the code to stop whenever the attribute of this icon is about to change.

Click the plus button and you’ll see the execution stop at the breakpoint, because the color of the counter is about to change from yellow to blue. Click the “Resume execution” button and you’ll see the code execute and the counter change to 1 (and turn blue). Click the plus button again, and the execution won’t stop at the breakpoint, because when going from 1 to 2, the color doesn’t change. But if you click the minus button twice to go back to Zero, you’ll see the code execution pause at the breakpoint again, because the color of the counter is about to change from blue to yellow.
Don’t forget to remove the breakpoint and click the Resume button when you are done with this section!

This is becoming quite a long post, and we’ve got four more breakpoints to learn about! So I’m going to stop here and continue next week. Until next time!

A Tale of Two Testers

Meet Derek and Emma. They are both Software Test Engineers. Derek works for a company called ContactCo, which is building a web application to allow users to add and manage their contacts. Emma works for a competitor of ContactCo, called ContactsRUs. ContactsRUs is building a similar application to the one ContactCo is buildling.

Emma is very proud of her ability to create test automation frameworks. As soon as development begins on the new app, she gets to work on a UI automation suite. She writes dozens of well-organized automated tests, and sets them to run with every build that the developers check in. The tests are all passing, so she feels really good about the health of the application. She also creates a set of smoke tests that will run with every deploy to every environment. If the smoke tests pass, the deployment will automatically continue to the next environment, all the way through Production; if the tests fail, the deployment will be rolled back and the deployment process will stop. After just three weeks, she’s got a CI/CD system in place, and everyone praises her for the great job she’s done.

Derek begins his involvement with ContactCo’s new app by attending the product design meetings and asking questions. He reads through the user stories so he understands the end user and knows what kinds of actions they’ll be taking. As the application takes shape, he does lots of manual exploratory testing, both with the API and the UI. He tries out the application on various browsers and with various screen sizes. At the end of the first two weeks of development, he’s found several UI and API bugs that the developers have fixed.

Next, Derek works with developers to find out what unit and integration tests they currently have running, and suggests some tests that might be missing. He talks with the whole team to determine what the best automated framework would be for API and UI testing, and works with them to get it set up. He spends a lot of time thinking about which tests should run with the build, and which should run with the deployment; and he thinks about which tests should be run solely against the API in order to minimize the amount of UI automation. Once he has a good test strategy, he starts writing his automated tests. At the end of the third week of development, he’s got some automated tests written, but he’s planning to add more, and he doesn’t quite have the CI/CD process set up yet.

At the end of the three weeks, both ContactCo and ContactsRUs release their applications to Production. Which application do you think will be more successful? Read on to find out!


Derek’s application at ContactCo is a big hit with users. They comment on how intuitive the user interface is, and by the end of the first week, no bugs have been reported. Customers have suggestions for features they’d like to see added to the application, and the team at ContactCo gets started with a new round of product design meetings, which Derek attends. When he’s not in meetings, he continues to work on adding to the automated test framework and setting up CI/CD.

Emma’s application at ContactsRUs was released to Production, and the very same day the company started to get calls from customers. Most of the ContactsRUs customers use the Edge browser, and it turns out there are a number of rendering issues on that browser that Emma didn’t catch. Why didn’t she catch them? Because she never tested in Edge!

The next day the company receives a report that users are able to see contacts belonging to other customers. Emma thinks that this can’t be possible, because she has several UI tests that log in as various users, and she’s verified that they can’t see each other’s data. It turns out that there’s a security hole; if a customer makes an API call to get a list of contacts, ALL of the contacts are returned, not just the contacts associated with their login. Emma never checked out the API, so she missed this critical bug.

Developers work late into the night to fix the security hole before anyone can exploit it. They’ve already lost some of their customers because of this, but they release the fix and hope that this will be the last of their problems. Unfortunately, on the third day, Emma gets an angry message from the team’s Product Owner that the Search function doesn’t work. “Of course it works,” replies Emma. “I have an automated test that shows that it works.” When Emma and the Product Owner investigate, they discover that the Search function works fine with letters, but doesn’t work with numbers, so customer’s can’t search their contacts by phone number. This was a critical use case for the application, but Emma didn’t know that because she didn’t attend the product meetings and didn’t pay attention to the feature’s Acceptance Criteria. As a result, they lose a few more customers who were counting on this feature to work for them.

The Moral(s) of the Story

Were you surprised by what happened to ContactsRUs? It might have seemed that they’d be successful because they implemented CI/CD so quickly into their application. But CI/CD doesn’t matter if you neglect these two important steps:

  1. Understand the product you are testing. Know who your end users are, what they want from the product, and how they will be using it. Pay attention in planning meetings and participate in the creation of Acceptance Criteria for development stories.
  2. Look for bugs in the product. Many software test engineers jump right to automation without remembering that their primary role is to FIND THE BUGS. If there are bugs in your product, the end users aren’t going to care about your really well-organized code!

Every good fable deserves a happy ending! Hopefully you have learned from Derek and Emma and will make sure that you understand and test your software before writing good automation.

Adventures in Node: Shorthand and Destructuring

One of the things I struggled with when I started learning object-oriented programming (OOP) was the way objects were created and referenced. Things seemed so much simpler to me years ago when a computer program was in one file and you declared all your variables at the top!

But the more I’ve worked with OOP, the more I’ve been able to understand it. And the work I’ve done while taking this awesome Node.js course has helped me even more. I’ve already written a few posts about the great things I’ve learned in Node.js: Async/Await functions, Promises, and Arrow Functions. In this post, I’ll talk about two great ways to write less code: Object Property Shorthand and Object Destructuring.

First, let’s take a look at how Object Property Shorthand works. We’ll start with a few variables:
var name = ‘Fluffy’
var type = ‘Cat’
var age = 2

Now we’ll use those variables to create a pet object:
const pet = {
name: name,
type: type,
age: age

When we create this object, we are saying that we want the pet’s name to equal the name variable that we set above, the pet’s type to equal the type variable we set above, and the pet’s age to equal the age variable we set above.

But doesn’t it seem kind of silly to have to repeat ourselves in this way? Imagine if the pet object had several more properties: we’d go on adding things like ownerName: ownerName, address: address, and so on. Wouldn’t it be nice to save ourselves some typing?

Good news- we can! If the property name in our object matches the variable name we are setting it to, we can save typing time by doing this:
const pet = {

That’s a lot easier to type, and to read! If you have Node.js installed, you can try it for yourself by creating a simple file called pet.js. Begin by declaring the variables, then create the object the old way, then add console.log(pet). Run the program with node pet.js, and you should get this response: { name: ‘Fluffy’, type: ‘Cat’, age: 2 }. Now delete the object creation and create the pet the new way. Run the program again, and you should get the same response!

Now let’s take a look at Object Destructuring. We’ll start by creating a new book object:
const book = {
title: ‘Alice in Wonderland’,
author: ‘Lewis Carroll’,
year: ‘1865’

The old way of referencing the properties of this book object is to refer to them by starting with “book.” and then adding on the property name. For example:
const title = book.title,
const author =,
const year = book.year

But just as we saw with Object Property Shorthand, this seems a little too repetitive. If the property name is going to match the variable name we want to use, we can set all of the variables like this:
const {title, author, year} = book

What this command is saying is “Take these three properties from book, and assign them to variables that have the same name.”

You can try this out yourself by creating the book object, setting the variables the old way, then adding a log command: console.log(title, author, year). Run the file, and you should see Alice in Wonderland Lewis Carroll 1865 as the response. Then replace the old variable assignments with the new Destructuring way, and run the file again. You should get the same response.

Keep in mind that Shorthand and Destructuring only work if the property name and the variable name match! In our pet example, if we wanted to set a pet property called petAge instead of age, we’d need to do this:
const pet = {
petAge: age

And in our book example, if we wanted to use a variable called authorName instead of author, we’d need to do this:
const {title, author:authorName, year} = book

Even if we don’t have a perfect match between all our object properties and variables, it’s still easy to see how much less typing we need to do when we use Shorthand and Destructuring! I hope you’ll find this helpful as you are writing automation code.

Book Review: Explore It!

I’ve been recommending the book Explore It! by Elizabeth Hendrickson for years, because I had heard the author interviewed in a podcast, and because I was familiar with her Test Heuristics Cheat Sheet. This month, I decided it was about time that I actually read her book, and I am so glad I did!

This book should be required reading for anyone who wants to test software. It contains the most thorough descriptions I have ever read of how to think about what to test. Developers will find the book extremely helpful as well; if they would use its ideas to test their own software, they’d find bugs long before anyone else did!

The author begins the book with a discussion of the difference between exploring and checking. Checking is what a tester does when they want to make sure that the software does what it’s supposed to do. Exploring is what a tester does when they want to find out what happens if the user or the system doesn’t behave as expected. In order to fully test a system, you need to use both methods. I’ve met many software testers who just check the software. Then they (and their team) are surprised when bugs are discovered in production!

My favorite thing about the book is the testing heuristics that are suggested. These are concepts that you can apply to virtually any application, and they’d make a great mental (or physical) checklist when you are testing. Here are some of my favorites:

  • Zero, One, Many: what happens if you have zero of something that is expected, or just one of something where there are supposed to be many, or many of something where is supposed to be one?
  • Beginning, Middle, End: what if you do something at the beginning of a list or a text block? What if you do it at the end? What if you do it somewhere in the middle?
  • Nesting: for a file structure, XML, or JSON that is nested, how deep can the nesting go? Is there a point where nesting is so deep that it breaks the system?
  • Nouns and Verbs: think about all the nouns in your application, such as “file”, “message”, “record”. Then think about all the verbs in your system, such as “create”, “send”, “delete”. Try pairing the nouns and verbs in new ways and doing those actions to see if you can find any action that is unsupported and causes errors.
  • Reverse: think about the typical user workflow and try it all in reverse. See if you can confuse the system or generate unexpected behavior.
  • Files: delete a file that is expected by the application, or replace it with a corrupted or empty file. See how the system responds.
  • Stress the system: leave the application running overnight and see what happens. Or try chaos testing, either through using chaos testing software or by putting a shoe (or a toddler or cat) on the keyboard.
  • Interrupt the state: see what happens if you disconnect from the network or put the device to sleep in the middle of an operation.

Another thing I really enjoyed about the book was the stories the author told of real-world bugs she found and situations she encountered. These are always so entertaining and instructive for testers! My favorite story was the one where she had a product owner and a lead developer who she was absolutely sure were misunderstanding each other. When she voiced her concerns to each of them, they dismissed her and said they didn’t need another product meeting; they knew they were both clear about the product expectations. Finally, she got them to come to a “test planning” meeting, and when she outlined the most basic use case that the product owner was expecting, the developer said that the use case would be impossible. It was eye-opening for both of them!

Talking with product designers and developers is an important theme in the book. The author advises that it’s important to meet with designers and developers to determine what the Never and Always rules are for a feature or application. For example, if you are testing a financial app, it’s fairly certain that you would Never want a monetary calculation to be rounded incorrectly. And when you are working with a medical device, you would Always want it work, even in the event of a power failure. When you learn what the Never and Always rules are for your application, you can use that knowledge to design appropriate tests.

Explore It! was clearly written, entertaining, and filled with great advice for exploratory testing and for creating test plans. I recommend it for anyone who wants to make sure they are releasing high-quality software!