Email Subscription Form

Saturday, January 19, 2019

Easy Free Automation Part I: Unit Tests

This post is the beginning of an eight-part series on easy, free ways to automate each area of the Automation Test Wheel.  It's been my experience that there are a number of barriers to learning test automation.  First, the team you are on might not need certain types of automation.  For example, my team has been solely API-focused, so for the last two years I haven't had much reason to do UI automation.  Second, your company may already have invested in specific automation tools, so when you want to learn to use a different tool, you need to do it on your own.  Third, there are many tools that have barriers to using them, such as a high cost or a complicated setup.  And finally, there is not always good documentation out there to help people get started.

In this series, I'm hoping to provide simple, free examples that will demonstrate each area of the Automation Test Wheel in practice, which you can use as a jumping-off point in your own automation journey.  We'll begin with unit tests.



Unit tests are usually written by developers, but it's a good idea for all software testers to understand what they are and how they work.  Unit tests test just one method or function, and they aim to exercise as many paths of that method or function as possible.  The major benefit of unit tests is that they provide extremely fast, accurate feedback.

I'm going to use Python and Pytest to demonstrate how unit tests work.  I am admittedly not an expert in either, but I managed to put together a little project with just one function.  If you would like to try the code out yourself, I have added it to GitHub here.  (If you have never cloned a Git repository before, you can find some instructions here.)

To run the tests, you will need to have Python installed.  There are some great directions for installing Python here.  Installing Python 3 will most likely install pip, the Python package installer, but if it doesn't, you can get installation instructions here.  Finally, you'll need to use pip to install Pytest; there are instructions for that here.  (If all this seems like too much work, you can just read on and look at the examples.)

In the file called _init_.py, I've written a simple function called isItADozen that determines whether a number of objects equals a dozen.  Here's the code:

def isItADozen(input): 
if type(input) != int:
result = "This is not a number"
elif input == 12:
result = "Yup, it's a dozen!"
elif input < 12 and input > 0:
result = "Nope, you have less than a dozen"
elif input > 12:
result = "You have more than a dozen here"
elif input <=0:
result = "You don't have any at all!"
return result

The function takes the input and first checks to see if it's an integer.  If not, it returns the message "This is not a number".  Then it checks to see whether the number is 12, or is more than 12, or is between 0 and 12, or is less than 0.  Depending on which statement is true, it will return an appropriate message.  

Before we look at the unit tests, let's think about how we would test this function manually, assuming it had a UI interface.  We'd check to make sure it recognized 12 as a dozen, we'd check to make sure it recognized when a number was more than or less than a dozen, and we'd also try some of the usual QA tricks, like passing in a negative number or "FOO".  

That's exactly what we'll do with our unit tests!  Here is the code in my test.py file:

import unittest

from my_test import isItADozen

class TestDozen(unittest.TestCase):
    def test_a_dozen(self):
        result = isItADozen(12)
        self.assertEqual(result, "Yup, it's a dozen!")

    def test_more_than_a_dozen(self):
    result = isItADozen(15)
    self.assertEqual(result, "You have more than a dozen here")

    def test_less_than_a_dozen(self):
    result = isItADozen(10)
    self.assertEqual(result, "Nope, you have less than a dozen")

    def test_less_than_zero(self):
    result = isItADozen(-1)
    self.assertEqual(result, "You don't have any at all!")

    def test_not_a_number(self):
    result = isItADozen("FOO")
    self.assertEqual(result, "This is not a number")

if __name__ == '__main__':
    unittest.main()

I have five test cases here, aptly named:
test_a_dozen
test_more_than_a_dozen
test_less_than_a_dozen
test_less_than_zero
test_not_a_number

In each test, I call the isItADozen function with the number I want to test with.  Then I assert that the result I got matches the result I was expecting.  

To run my tests, I simply go to the command line, navigate to the unitTestProject folder, and type:

python3 test.py --verbose

(If you don't know how to use your command line, see my blog post from several years ago.)

You may not need to use the "3" in "python3"- I need to do this because I have Python 2.7.1 installed as well and I want to run on the newer version.  You don't need to do the "--verbose" command; I like to do this because then it shows me the names of my tests as they pass instead of ".....", which isn't much fun.  

Once you have the tests running, try making one fail by changing one of the assert statements like this:

self.assertEqual(result, "This is not the real result message")

Then see if you can change a test so that you are passing in a different value.  For example, you could pass the number 13 into the "test_more_than_a_dozen" test instead of 15.  

Once you have mastered that, you may want to copy my entire test folder and see if you can write your own simple function and unit tests.  If you are more familiar with another programming language, you can try writing unit tests in that language as well.  

Hopefully this has been an easy way to get you started with writing unit tests!  We'll continue with the Easy Free Automation series next week.  

Saturday, January 12, 2019

Automation Wheel Strategy: Moving from What to How to When to Where

Last week, we talked about how I would decide what to test in a simple application in terms of testing every segment of the Automation Test Wheel.  I find it's very helpful to answer the question "What do I want to test?" before I think about how I'm going to test it.  This week we'll look at how to take the "What" of automated testing and continue on with how I want to test, when I want to test it, and where (what environment) I'm going to test it in.  As a reminder, my hypothetical application is a simple web app called Contact List, which allows a user to add, edit, and delete their contacts.


How I'm Going to Test:

I'm going to run my unit and component tests directly in the code.  Unit tests are designed to specifically run in the code, because they are the smallest possible unit and test the code directly.  My component tests are very simple- just one call to the database and one call for authentication- so I will run those directly from my code as well.

For my services tests, I'm going to use Postman, which is my favorite API testing tool.  I'll run the Postman tests using Newman, which is the command-line tool for Postman.  I'll also include some security tests in Postman, validating that any requests without appropriate authentication return an appropriate error, and I will also do some performance checks here, verifying that the response times to my API requests are within acceptable levels.

For my UI tests, I'm going to use Selenium and Jasmine, because I like the assertion style that Jasmine uses.  I'll be adding a few security tests here, making sure that pages do not load when the user doesn't have access to them.  I'll also be integrating my visual tests into my Selenium tests, using Applitools, and I'll be using both Selenium and Applitools to run my accessibility tests. 

Finally, I would set up a performance testing tool such as Pingdom that would consistently monitor my web page loading times and alert me when load times have slowed.  

When I'm Going to Test:

Now that I've figured out how I'm going to test, it's time to think about when I'm going to run my tests.  I'm going to organize my tests into four times.

With every build: every time new code is pushed, I'm going to run my unit tests, component tests, and Newman tests.  These tests will give me very fast feedback.  I'm not going to run any UI tests at this time, because I don't want to slow my feedback down.

With every deploy: every time code is deployed to an environment, I'm going to run all my Newman tests, and a small subset of my Jasmine tests.  My Jasmine tests will include at least one visual check and one security check.  This will ensure that the API is running exactly as it should and that there are no glaring errors in the UI.

Daily: I'll want to run all of my Newman tests and all of my Jasmine tests early in the morning, before I start my workday.  When I begin my workday I'll have a clear indication of the health of my application.

Ongoing: As mentioned above, I'll have Pingdom monitoring my page load times throughout the day to alert me of any performance problems.  I'll also set up a job to run a small set of Newman tests periodically throughout the day to alert me of any server downtime.

Where I'm Going to Test:

Now that I've decided how and when to test, I need to think about where to test.  Let's imagine that my application has four different environments: Dev, QA, Stage, and Prod.  My Dev environment is solely for developers.  My QA environment is where code will be deployed for manual and exploratory testing.  My Stage environment is where a release candidate will be prepared for Production.  Let's look at what I will test in each environment.

Dev: My unit and component tests will run here whenever a build is run, as well as my Newman and Jasmine tests whenever a deploy is run.

QA: I'll run my full daily Newman and Jasmine suites here, and I'll run my full Newman suite and a smaller Jasmine suite with a deploy.

Stage: I'll run the full sets of Newman and Jasmine tests when I deploy.  This is because the Stage environment is the last stop before Prod, and I'll want to make sure we haven't missed any bugs.  I'll also run my Pingdom monitoring here, to catch any possible performance issues before we go to Prod.

Prod: I'll run a small set of daily Newman and Jasmine tests here.  I'll also point my Pingdom tests to this environment, and I'll have those tests and a set of Newman tests running periodically throughout the day.

Putting it All Together:

When viewed in prose form, this all looks very complicated.  But we have actually managed to simplify things down to four major test modalities tested at four different times.  Are we covering all the areas of the Automation Test Wheel?  Let's take a look:

CodeNewmanJasminePingdom
UnitServicesUIPerformance
ComponentSecuritySecurity
PerformanceVisual
Accessibility

We are covering each different area with one or more testing modalities.  Now let's visualize our complete test plan:

HourlyDailyBuildDeploy
DevUnitNewman
ComponentJasmine
Newman
QANewmanNewman
JasmineJasmine
StagePingdomNewman
Jasmine
ProdPingdomNewmanNewman
NewmanJasmineJasmine

Viewed in a grid like this, our plan looks quite simple!  By considering each question in turn:

  • What do we want to test?
  • How are we going to test it?
  • When will we run our tests?
  • Where will we run them?

We've been able to come up with a comprehensive plan that covers all areas of the testing wheel and tests our application thoroughly and efficiently.  

Saturday, January 5, 2019

The Automation Test Wheel in Practice

Last week's blog post, "Rethinking the Pyramid: The Automation Test Wheel", sparked many interesting discussions on LinkedIn, Twitter, and in the comments section of this blog!  The general consensus was that the Test Pyramid is still useful because it reminds us that tests closest to the code are the fastest and most reliable to run, and that the Automation Test Wheel reminds us to make sure to include categories such as security, accessibility, and performance testing.  Also, a reader pointed us to Abstracta's Software Testing Wheel, which looks at the definition of quality from a number of different perspectives.

This week I'm talking about how to put the Automation Test Wheel into practice.  Let's imagine that I have a simple web app called Contact List.  It allows a user to log in, view a list of their contacts, and add new contacts.  I want to design a complete automation strategy for this application that will enable my team to deploy all the way up to production confidently.  In order to feel confident about the quality of my application, I'll want to be sure to include tests from every segment of the Automation Test Wheel.


Unit Tests: I will make sure that every function of my code has at least one unit test.  I'll run these tests using mock objects.  For example, I will create a list of mock contacts and a mock new contact, add the new contact, and verify that the new contact has been added to the list of mock contacts.  I'll update a contact with new data and verify that the contact has been updated in the list.  I'll create a mock contact with invalid data and verify that attempting to add the contact results in an appropriate error.  These are just some examples; for each function in my app, I'll want to have several tests which exercise all possible code paths.

Component Tests:  My application is very simple and relies on just one database.  The database is used for both authentication and for retrieving the contact data.  I will include one test for each function; I'll send an authentication request for a valid user and verify that the user is authenticated, and I'll make one request to the database to retrieve a known contact, and verify that the contact is retrieved.

Services Tests: My application has an API which allows me to do CRUD operations (Create, Read, Update, Delete) on my contacts.  I have a GET endpoint which allows me to retrieve the list of contacts, and a GET endpoint which allows me retrieve one specific contact.  I have a POST endpoint which allows me to add a contact to the contact list.  I have a PUT endpoint which allows me to update the data for an existing contact, and I have a DELETE endpoint which allows me to delete an existing contact.  For each one of these endpoints, I will have a series of tests.  The tests will include both happy paths and error paths.  I'll verify that in each request, the response code is correct and the response body is correct.  For example, with the GET endpoint where I retrieve one contact, I'll verify that a GET on an existing contact returns a 200 response and the correct data for the contact.  I'll also verify that a GET on a contact that doesn't exist returns a 404 Not Found response.

User Interface (UI) Tests: This is where I will be testing in the browser, doing activities that a real user would do. A real user will want to fetch their list of contacts, add a new contact, update an existing contact, and delete a contact.  I will have one test for each of these activities, and each test will have a series of assertions.  To take one example, when I add a new contact, I will navigate to the new contact page, fill in all the form fields, and click the Save button.  Then I will navigate to the list page and verify that my new contact appears on the page.

Visual Tests: This is where I will verify that elements are actually appearing on the page the way I want them to.  I will navigate to the list page and verify that all of the columns are appearing on the page.  I will navigate to the add contact page and verify that all of the form fields and their labels are appearing appropriately on the page.  I will trigger all possible error messages (such as the one I would receive if I entered an invalid zip code), and verify that the error appears correctly on the screen.  And I will verify that all of the buttons needed to use the application are rendering correctly.

Security Tests: I will run security tests at both the Services layer and the UI layer.  I will test the API operations relating to authenticating a user, verifying that only a user with the correct credentials will be authenticated.  I will test every request endpoint to make sure that only those requests with a valid token are executing; requests without a valid token should return a 401.  For the UI layer, I will conduct a series of login tests that validate that only a user with correct credentials is logged in, and I will verify that I cannot navigate to the list page or the add contact page without being logged in.

Performance Tests: I will set benchmarks for both the server response time and the web page load time.  To measure the server response, I will add assertions to my existing Services tests that will verify that the response was returned within that benchmark.  To measure the web page load time, I will run a UI test that will load each page and assert that the page was loaded within the benchmark time.

Accessibility Tests:  I want to make sure that my application can be used by those with visual difficulties.  So I will run a set of UI and Visual tests on each page where I validate that I can zoom in and out on the text and that scroll bars appear and disappear depending on whether they are needed.  For example, if I zoom in on the contact list I will now need a vertical scrollbar, because some of the contacts will now be off the page.

With this series of automated tests, I will feel confident that I'll be able to deploy changes to my application and discover any problems quickly.

I've received a few questions over the last week about what percentage of total tests each of spokes in the Automation Test Wheel should have.  The answer will always be "It depends".  It will depend on these and many other considerations:

  • How many other services does your application depend on?  If it depends on many external services, you'll need more Component tests.
  • How complicated is your UI?  If it has just a page or two, you'll need fewer UI and Visual tests.  If it has several pages with many images, you'll need more UI and Visual tests.
  • How complicated is your data structure?  If you are dealing with large data objects, you'll need more Services tests to validate that CRUD operations are being handled correctly.
  • How secure does your application need to be?  An application that handles personal banking will need many more Security tests than an application that saves pictures of kittens.
  • How performant does your application need to be?  A solitaire game doesn't need to be as reliable as a heart monitor.

The beauty of the Automation Test Wheel is that it can be tailored to all types of software applications!  By considering each spoke in the wheel, we'll be sure that we are creating great automated test coverage.

Saturday, December 29, 2018

Rethinking the Pyramid: The Automation Test Wheel

Anyone who has spent time working on test automation has likely heard of the Test Automation Pyramid.  The pyramid is typically made of three horizontal sections: UI Tests, API Tests, and Unit Tests.  The bottom section is the widest section, and is for the unit tests.  The idea is that there should be more unit tests run than any other kind of tests.  The middle section is for the API tests, and the idea is that fewer API tests should be run than unit tests.  Finally, the top section is for the UI tests, and the idea is that the least number of tests run should be UI tests, because they take the most time and are the most fragile.

In my opinion there are two things wrong with the pyramid: it leaves out many types of automated tests, and it assumes that the number of tests is the best indicator of appropriate test coverage.  I propose a new way of thinking about automated testing:  the Automation Test Wheel.



Each of these test types can be considered as spokes in a wheel; none is more important than another, and they are all necessary.  The size of each section of the wheel does not indicate the quantity of the tests to be automated; each test type should have the number of tests that are needed in order to verify quality in that area.  Let's take a look at each test type.

Unit Tests:  A unit test is the smallest automated test possible.  It tests the behavior of just one function or method.  For example, if I had a method that tested whether a number was zero, I could write these unit tests:
  • A test that passes a zero to the method and validates that it is identified as a zero
  • A test that passes a one to the method and validates that it is identified as non-zero
  • A test that passes a string to the method and validates that the appropriate exception is thrown
Because unit tests are independent of all other services and because they run so quickly, they are a very effective way of testing code.  They are often written by the developer who wrote the method or function, but they can also be written by others.  Each method or function should have at least one unit test associated with it.

Component Tests: These tests check the various services that the code is dependent on.  For example, if we had code that called the GitHub API, we could write a component test that would make a call to the API and verify that the API was running.  Other examples of component tests are pinging a server or making a call to a database and verifying that a response was received.  There should be at least one component test for each service the code relies on.

Services Tests:  These are tests that check the web services that are used in our code.  In today's applications, web services often use API requests.  For example, if we have an API with POST, GET, PUT, and DELETE requests, we will want to have automated tests that check each request type.  We will want to have both "happy path" tests that check that a valid request returns an appropriate response, and also negative tests that verify that an invalid request returns an appropriate error code.

User Interface (UI) Tests: UI tests verify that end-user activities work correctly.  These are the tests that will fill out text fields and click on buttons.  As a general rule, anything that can be tested with a unit, component, or service test should be tested by those methods instead.  UI tests should focus solely on the user interface.

Visual Tests: Visual tests verify that elements are actually appearing on the screen.  This is slightly different from UI tests, because the UI tests are focusing on the functionality of the user interface rather than the appearance.  Examples of visual tests would be: verifying that a button's label is rendered correctly, and verifying that the correct product image is appearing on the screen.

Security Tests:  These are tests that verify that security rules are being respected.  These tests can overlap with services tests, but should still be considered separately.  For example, a security test could check to make sure that an authorization token cannot be generated with an invalid username and password combination.  Another security test would be to make a GET request with an authorization token for a user who should not have access to that resource, and verify that a 403 response is returned.

Performance Tests: Automated performance tests can verify that request response times happen within an appropriate time period.  For example, if your company has decided that GET requests should never take longer than two seconds, test requests can be set to return a failure state if the request takes longer than that time.  Web page load times can also be measured with performance tests.

Accessibility Tests:  Automated accessibility tests can check a variety of things.  When combined with UI tests, they can verify that images have text descriptions for the visually impaired.  Visual tests can be used to verify that the text on the screen is the correct size. 

You may have noticed that the above descriptions often overlap each other.  For example, security tests might be run through API testing, and visual tests might be run through UI testing.  What is important here is that each area is tested thoroughly, efficiently, and accurately.  If there is a spoke missing from the wheel, you will never be comfortable relying on your automation when you are doing continuous deployment. 

Next week, I'll discuss how we can fit all these tests into a real-world application testing scenario!

Saturday, December 15, 2018

Fifteen Free Tools to Help With Testing

There are a great many articles, blog posts, and presentations that discuss automation frameworks and strategies.  But even the most robust automation framework won't eliminate the need to do exploratory testing.  There will always be situations where we need to generate a large amount of text to test a text field or where we need to encode a string in HTML to test for cross-site scripting.  In this week's post, I share fifteen of my favorite free tools that make testing faster and easier.  


Text Tools:

1. Letter Count:  This tool will count the characters or words in a block of text.  I use it for creating strings with a specific character count when I test text fields.

2. Lorem Ipsum Generator: I use this tool when I need to generate large amounts of text for text fields where a user will be able to enter several paragraphs of text.

3. Convert Case: This tool comes in handy when I'm testing with Postman and my assertions are expecting the exact casing for string comparison.  Convert Case will set all the characters in a string to lower case, upper case, sentence case, alternating case, and more.

JSON Tools:

4. Pretty Print: JSON objects need indentation to be easily readable.  This tool will take care of all of the indentation and spacing for you.  This is especially helpful when you receive flattened JSON in a response and you want to be able to read through it.

5. Online JSON Viewer: This tool will flatten your JSON for you by removing all the white spaces, which is helpful when you need to use your JSON in code.

6. JSON Lint: I use this tool whenever I'm using JSON in a test and getting 400 errors.  I paste the JSON into the tool and it will tell me whether my JSON is valid.  If it's not valid, it shows me the line with the error.

Encoding and Decoding Tools:

7. URL Encoder/Decoder: This tool is great for testing cross-site scripting.  Simply paste in your script and it will encode it in valid HTML format for you.

8. JWT.IO: This official JWT documentation includes a tool that will decode a JWT.  It's really helpful for testing authorization, because you can see exactly what information your JWT is sending.  

9. Base 64 Decode and Encode: When you have an image or string that's been encoded into Base 64, this is an easy way to decode it.  

GUID Tools:

10. GUID Generator: I often need random GUIDs for my testing, and this tool will generate as many as I need.

11. GUID Test and Validate: I use this tool to check GUIDs to make sure that they are valid. 

Miscellaneous Tools:

12. Rubular: This is a regex editor that allows you to put in a regex, add a string to test, and find out whether your string matches the regex.  It is specifically designed for Ruby but can be used with other languages as well.  

13. NumVerify: This tool is helpful when you are testing international phone numbers.  It lets you know whether a given number is valid, and which country it is valid in.  

14. WePay Testing: I use this site when I need a fake bank account to test with.  It also lists fake credit card numbers for use in testing.  Some of the features may be specific to Chase Bank.  

15. Online Random File Generator: When you need to test files of a very specific size, this tool uses random strings to generate a file with exactly the size you need.

Just as we use tools in our daily life to make our tasks easier, these free online tools can help speed up our testing, giving us more time to write test automation or do further exploratory testing.  

What are your favorite free tools for testing?  Let me know in the comments below!  


Saturday, December 8, 2018

Six Steps to Writing an Effective Test Report

As testers, we know how important it is to test our software thoroughly and document our findings meticulously.  But all of our talent will be useless if we can't effectively communicate our test results to others!  If your test results are written in a giant, poorly organized spreadsheet with tiny text and lots of unnecessary details, even the most dedicated test manager will find her eyes glazing over with boredom when she looks at it.  In this post, I'll describe six steps to take to make sure that you can communicate your findings to others efficiently and effectively.



Step One: Determine what goal you are trying to accomplish with your report

Why are you creating your report?  What do you want people to understand when they read it?  You might be creating a report to demonstrate that you have tested all the acceptance criteria in the user story.  You could be showing your manager exactly which areas of the application are not functioning properly.  You could be demonstrating that after a recent code change several bugs were fixed.  

There are all kinds of reasons to create a report, but if you don't stop and think about why you are creating it, it's probably not going to be very clear to your readers.  Simply sending over your test notes is not enough to communicate effectively.

Step Two: Focus on the viewer's needs

Who will be reading your report?  Will it be a developer, your test manager, your product owner, your team lead, or the CTO of your company?  You will want to tailor your test report for your audience.  The CTO of your company is probably very busy and will not care how many permutations of your form data you ran, or how you developed the permutations.  She will want to see that you ran 100 tests and that 99 passed.  Your product owner will want to see that you have tested the user stories and that the outcomes were as expected.  Your test manager might be interested in how many different permutations of the test you ran, and what logic you used to create them.  Your developer might want to know what test data you used and what your server response times were.  

You can see how the interests of your reader will vary quite a bit depending on their role, so think about how you can best present the information that he or she wants.

For steps three through six, we'll once again use the example of the Superball Sorter.  This is a hypothetical software feature that sorts out superballs of varying sizes and colors to four children according to a set of rules.  

Step Three: Avoid Extraneous Information

Make sure that your report contains only the information that your reader needs.  Extraneous information means that a reader has to sift through your report to find the important results.  Consider this report, which shows the results of two tests where two children have a sorting rule:

Rules Amy  Bob Carol Doug
Amy-small blue balls; Doug- large green balls small blue ball; small blue ball; small blue ball; small blue ball large red ball; small orange ball; large yellow ball; small purple ball large purple ball; small green ball; large yellow ball; small red ball large green ball; large green ball; large green ball; large green ball
Bob- large red balls; Carol- small yellow balls large orange ball; small purple ball; large yellow ball; small green ball large red ball; large red ball; large red ball; large red ball; large red ball small yellow ball; small yellow ball; small yellow ball; small yellow ball small blue ball; small green ball; large purple ball; small orange ball

Did the tests pass?  How long did it take for you to determine that by looking at the test report?  There is a lot of information here that is unnecessary.  It doesn't matter that Bob got the large red ball first and the small orange ball second.  What matters is that Amy only got small blue balls and Doug got large green balls.  Contrast that test report with this one:

Rules Rules respected?
Amy-small blue balls; Doug- large green balls Yes
Bob- large red balls; Carol- small yellow balls Yes

Here you can very quickly see what rules were set, and whether those rules were respected.  If a reader of your report needs to know what balls Bob got, they can ask you for those details and you can look them up in your notes.

Step Four: Make the report visually immediate

We are all busy people; developing and testing software is fast-paced and time-consuming!  Your manager or CTO is probably sent dozens of reports and emails a day, so make your report so easy to read that just a glance at it will give them information.  Take a look at this test report:

Number of Rules Pass/Fail
0

1

2

3

4


How many seconds does it take you to see that a test failed?  This report is pretty immediate!  It's also really easy to see how many rules were used when the test failed.  Compare that with this test report, which shows the same tests and the same results:

Test Case Result
None of the children have rules The balls are sorted evenly amongst the children
One child has a rule The child’s rule is respected
Two children have rules The two children’s rules are respected
Three children have rules The three children’s rules are respected
Four children have rules None of the balls are sorted

A reader needs to read through all the text of this report in order to see that the fourth test failed.

Step Five: Make the report easy to read

In addition to making the report visually immediate, it also needs to be easy to read. Take a look at this example, where two tests are run where three children are given rules:

Rules
Rules respected?
Amy- small blue; Bob- large blue; Carol- small purple
Amy gets only small blue balls, and Bob gets only large blue balls, but Carol gets balls other than the small purple balls
Amy- large blue; Bob- small purple; Carol- small yellow
Amy gets only large blue balls, Bob gets only small purple balls, and Carol gets only small yellow balls

This report shows very quickly that one of the tests failed, but in order to see why the test failed, it's necessary to read through the whole description to see that Carol's rule was not respected.  This report conveys exactly the same information:

Rules Amy Bob Carol
Amy- small blue; Bob- large blue; Carol- small purple PASS PASS FAIL
Amy- large blue; Bob- small purple; Carol- small yellow PASS PASS PASS

With this report, it is so easy to see that Carol's rule was not respected, and it's also easy to look to the left to see which rule she had.

Step Six: Make the report readable without any additional explanation

How long does it take for you to figure out what this report means? 

Rules
Result
A-SB; B-LO; C-L; D-S
A-Y; B-Y; C-Y; D-N
A-L; B-S; C-Y; D-P
A-Y; B-N; C-Y; D-Y
A-LY; B-L; C-S; D-SG
A-Y; B-Y; C-N; D-Y

It's fine to use all sorts of abbreviations when you are testing and taking notes for yourself, but you shouldn't need to provide a key to your reader in order to have them interpret it.  Who but the most interested testers are going to take the time to see where the bug is here?

This report conveys exactly the same information:

Test One
Amy- small blue
Bob- large orange
Carol- large
Doug- small
Rule respected?
Yes
Yes
Yes
No
Test Two
Amy- large
Bob- small
Carol- yellow
Doug- purple
Rule respected?
Yes
No
Yes
Yes
Test Three
Amy- large yellow
Bob- large
Carol- small
Doug- small green
Rule respected?
Yes
Yes
No
Yes

It's easy to see exactly what rules each child was given for each test.  Through the use of color, the report demonstrates very clearly where the bug is: whenever a child is given a rule that they should get only small balls, that rule is not respected.

Conclusion:

In today's fast-paced world, we all have vast amounts of information coming to us every day.  If we are going to make a difference with our testing and influence decision-making where we work, we need to be able to convey our test results in ways that clearly show what is going on with our software and what should be done to improve it.

Easy Free Automation Part I: Unit Tests

This post is the beginning of an eight-part series on easy, free ways to automate each area of the Automation Test Wheel .  It's been my...