bookmark_borderOh, the places I’ll go

I’ve been attempting to travel less recently, and I’m happy to say that beyond early November, I have no (work related) travel plans anywhere on the horizon. For better or for worse, I’ve had a deluge of great opportunities converge over the next thirty days.(for those of you who may be experiencing déjà vu, I mentioned this travel spurt a few months ago).

I’m off to Portland, Oregon tomorrow. I’m planning to spend the weekend goofing off before frantically updating my slides Sunday night. My PNSQC presentation is Monday at 11:00, and I’ll spend the remainder of the conference trying to attend as many presentations as I can.

I return home on Tuesday evening, and on Wednesday morning, I’ll be giving a presentation on build verification tests for the STP automation summit.

Then – after ten or so days of time at home, I’m off to Israel. I’ll be spending a day at Microsoft’s Israel office, and then giving a keynote at an Intel internal software conference. I’m honored to have been invited and am looking forward to my first trip to Israel.

I get home just in time for Halloween, but depart a week later for a keynote at German Testing Day. Again, I’m honored to have been invited and I’m excited both to attend, and about the topic I’ll be speaking about.

Frankly, this is probably more travel and presenting than a non-consultant should be doing, but I do believe there’s value in establishing and maintaining industry relationships, and I’m grateful that Microsoft supports my participation (and time away from work). As much as I know I’ll enjoy the travel and meeting so many testers, I know I’ll be glad when the flurry is over.

In between all of that, I have some interesting projects brewing at work – and I can’t wait to share more details…stay tuned.

bookmark_borderAll you have to do is ask

Ever wanted to find out even more about me without actually asking me? I had a few interviews with me posted in the last month..

The first is on the IT Knowledge Exchange site

The other interview is on testzonen.se (in Swedish). Bing (or other) translation engines turn it into something almost readable – you’re welcome to give it a shot if you want to see what else I have to say..

Of course, I’m never short of opinions, so if there’s anything else you’ve been dying to know, please either ask in the comments, or write your question on a $20 dollar bill and mail it to me at Microsoft.

bookmark_borderLessons from TapeOp

I had a short bit of travel this week, and got a bit of reading done on the flights. I love my kindle, and use it when in the air, but I also pack a magazine or two to read during takeoff and landing.

On the way home, I was catching up on a few issues of Tape Op. I haven’t done much with recording in years, but I still love to read about the process – both the creative and technical aspects are extremely interesting to me. Perhaps I was in a “testing mindset”, but a few of the articles screamed testing at me. I’m sort of tired of the “testing is like …” metaphors, so I won’t stretch this too far, but still felt the need to share.

The latest issue (#84) has an article by Garrett Haines on Building Troubleshooting Skills. Garrett founded Treelady Studios in Pittsburgh, and consistently has pragmatic advice for recording enthusiasts of all skill levels. As far as I know, the article isn’t available online, but I’ll summarize the main points with some testing comments and see where it goes.

Troubleshooting

One of the most important skills for a recording engineer is troubleshooting. If something goes wrong, you can either figure out what the problem is and fix it, or you can send the band home just when they’re hitting their groove. I’ve always enjoyed the troubleshooting aspect of testing. For me, finding the bug is secondary to isolating the bug. I don’t find the exact root cause (or causes), or offending line of code for every bug I find, but I do like to isolate the bug as much as possible.

Let’s say that I get to a login screen and it doesn’t work. I try again, ensuring that my test username and password are correct. I could enter a bug and be done with it, but there’s likely some more I can do (even from an entirely black box perspective). I’ll see if other username / password combinations work, I’ll try variances of case, and compare simple passwords with complex passwords** until I can get some more clues to what’s going on.

Get in the right frame of mind

When something goes wrong (all of a sudden the test code won’t run an half of the machines), don’t panic. I don’t often have days when everything goes perfectly, and I doubt you do to. One reaction is to freak out and claim the sky is falling, but it helps to expect that things may go wrong and just address those issues as they arise.

Recreate the problem

That’s weird – something isn’t working- the first thing to do is reproduce it. I love the example Garrett uses here. “Sometimes reproducing the problem  can lead to an immediate solution – e.g. lifting the mute on the ‘track that won’t play;”

I remember working on a product when a tester ran into a colleague’s office, panicked because none of the audio tests he was running were working. My colleague calmly walked to her office, and had her reproduce the problem. He looked at her computer for a moment and informed her that she didn’t have any speakers connected. This is an extreme (yet true) example, but sometimes looking at the problem – and thinking through how the success path should work is a huge help.

Isolate the root cause

Garrett has a few dozen examples of how to use this technique, and most relate to software testing. Tell me if some of the troubleshooting scenarios he lists are familiar to us in the testing world.

  • Intermittent problems – these are my favorite to debug and isolate (in software, at least)
  • Not understanding the studio configuration – as a tester, you have to have an idea of how the system works in order to isolate many (most?) issues.
  • Invest in diagnostic tools – I couldn’t survive as a tester without debuggers, network sniffers, process monitors and other tools that let me know what’s going on
  • Trace the thunder – this is the concept of thinking through the flow of how the scenario works. The path from microphone to mixer (which may go through one or more effects), is similar to the flow of logging into a system (keystrokes go to UI, which encrypts the credentials, then sends them to a server (perhaps checking a local cache first), etc.
  • Make sure you’ve had enough coffee and sugar, but don’t have so much that you’re twitchy – ‘nuff said.
  • Don’t be afraid to call for help if you’re in over your head – Good advice for anyone.

Repair the problem & test the solution

Not always necessary for a tester to do, but something you can try if it will confirm your hypothesis. Think your problem is due to a missing configuration file or reg key – add the file or setting and see if it fixes the problem. You’ll learn more about the system whether the solution works or not.

Learn from the experience

Garrett says, “Tell your studio mates and colleagues what you’ve learned. Post findings on some of the various discussion forums.” Can you think of better advice for testers?

There’s plenty more to learn, but I think you get the point. Software (like recording studios) are complex environments that break or malfunction – but a structured approach to troubleshooting will minimize downtime (and yak-shaving time) and you’ll make more progress in the long run.

bookmark_borderIt’s (probably) a Design Problem

As you know, I occasionally rant about GUI automation; but I don’t think I’ve done a good job explaining some of the reasons why it can be fragile, and when it can actually be a good idea.

Let’s take a deeper look at some of the attributes of the GUI automation design challenges.

  • Record & Playback automation. This is a non-starter for me. I’ve never seen recorded automation work well in the long term– if your automation is based on record & playback, I can’t imagine it being successful. Yes, the tools are getting better, but the real problem is …
  • What are you going to do about the oracle? – Regardless of whether you write the automation, or you record it, simple playback of a user workflow has an oracle problem. The failure model in many UI tests is that nothing “bad” happens – the problem is that you don’t often know what flavors of “bad” you’re looking for, so your tests may miss stuff. However, if you design your tests with a trusted oracle (meaning if the test fails, you know there’s a problem, and if it passes, you know the scenario works), you probably have usable UI automation. By the way – if your oracle solution involves screen comparisons, I think you’re heading down a scary path – please consider this solution as a last, end-of-the-world type solution.
  • Bad Test Design I – Many authors of UI tests seemingly fail to realize they’re writing automation. Basic verification that would be hit by anyone walking through the basics of the application isn’t worth much to me. However, if your automation actually takes advantage of automation – meaning that loops, randomness, input variations, and loads of other ideas are part of the automation approach, the approach may be worthwhile.
  • Bad Test Design II – I dislike tests that do exactly the same thing every time. While valuable for regression testing, “hard coded” tests have severe limitations. In notepad, I can open a file by clicking the file menu, then selecting open, or I can press Alt-f, then o on the keyboard, I can press Ctrl-o, I can drag a file onto an open instance of notepad, or I can double click a file associated with notepad. A well-designed notepad test could just state File.Open(filename), and then use a randomly selected file open method. Too much UI automation doesn’t have this sort of abstraction and limits the effectiveness of the approach.
  • Bad Test Design III – Lack of forward thinking is another design flaw I see often. I once saw a GUI test suite that ran (successfully) on over 20 different localized versions of Windows 95, including RTL languages – and it ran successfully on Windows 98. Unfortunately, not all test authors consider the variety of scenarios where their tests could run.
  • Bad Test Design IV – Failure to consider what can fail. This one irks me, because testers should know that bad things can happen. Consider what will happen when someone changes window text, a control type, or dialog layout. Consider what happens when Windows reboots your machine in the middle of a test run. You don’t necessarily have to make your test resilient to these changes, but at the very least, you need to make the error text point to exactly what changed and caused the error. Too often, tests fail and give zero information on why they failed. Plan for failure and ensure that all test failures tell you exactly what is wrong.
  • Bad Test Design V – As a UI tester, you should have some notion of what sorts of UI automation are reliable, and which sorts are flaky. Using SendKeys works…but it probably should be a last resort. Good UI automation means that you know at least three ways to accomplish any task, and know which of the approaches is most reliable and which is least reliable.
  • Bad Test Design VI – One of my test design smells is Sleep (or similar) statements. The more I see in your test code, the less I trust it. Repeat after me – “Sleep functions are not a form of synchronization”. Most frameworks have an alternative to Sleep. There is always a better alternative to Sleep statements.
  • Fragile UI – It’s really easy to write automation that fails anytime the UI changes. It’s also really easy to write UI that breaks automation. If you don’t start testing until late in the product cycle, and know that the UI automation won’t be used in subsequent versions of the product, an investment in UI automation may make sense (given that it solves a real testing problem. Alternatively, if you’re involved early in the product cycle, you could wait to write UI automation until the UI was complete. A third (and recommended) approach is to make sure that the application under test is designed in a way that makes UI automation more robust (i.e. increase testability). Testability is, in short, the expense of test. Rewriting automation frequently during the product cycle is expensive. Writing complex oracles to verify things that should be easier is expensive. Working with developers to implement a UI model that enables straightforward and sustainable automation is cheap  – especially when you consider the long term benefits and gains.I probably have another post on this subject (testability) alone.

My annoyance with GUI automation isn’t a blanket view. The problem is that few teams put the effort into product and test design that successful GUI automation requires. I think GUI automation can be awesome – but we (as an industry) don’t seem to care enough…yet.

bookmark_borderNumberz Winnerz

Thanks everyone who played the Numberz Challenge. I’ll get the boring part out of the way first. Based on response time and completeness (and bonus points for reverse engineering the “bad” parts of the app), lixiong is the winner of either a signed copy of HWTSAM or an Amazon gift certificate. Li – email me and we’ll figure out the details of the exchange. A definite honorable mention goes to Aleksander Lipski – he came up with the same conclusions as Li, and also took the time to establish some context (which is easy to forget in contrived examples such as this). Aleksander – send me an email and we can work out some sort of prize for you too.

Thanks to everyone else for playing along and testing the app. It was nice to see a high interest level in my silly little experiment.

Analysis

For those interested in the what, why, and how of this exercise, read on.

The Numberz App v1

Brent Jensen noted that the first version of the application was quite buggy. It had several issues calculating the total. I released this buggy version on purpose. I have a bit of a distaste for testing applications that are so buggy that finding bugs is like shooting fish in a barrel – bugs should be hard to find. I think the applications we use to learn testing should be (mostly) working applications with some seeded defects that are difficult to find. Once I save up enough money for another Amazon gift certificate, I’ll see if I can come up with a more difficult exercise.

A more important point I’d like to bring up is that as testers, I hope we aren’t seeing apps like this as part of our day jobs. Something as broken as the first drop of this app shouldn’t make it one micrometer away from the hard drive of the developer who wrote it. If the apps and functionality you see on a daily basis is this bad, your software development process is broken (IMO of course, YMMV).

Numberz v2 – the Bugs

You can dig the details out of the comments, but basically, Numberz had three notable bugs.

The first bug was an intermittent addition error. Occasionally, the total would be one more than it should be. Some reports said that it seemed to happen about 2% of the time. Given the code, that sounds just about right. This gem was “hidden” in the source code.

    if ((rand() % 50) == 0)
    {
        total+=1;
    }

The second bug was that the number 3 showed up slightly more often than other numbers. In 100 roles, the difference (likely) isn’t statistically significant, but in larger number of roles, the delta was pronounced.

In 10,000 rolls of 5 numbers spanning 10 digits, you’d expect roughly 5000 occurrences of each digit. Most numbers had less than 5000 – mostly because the number 3 was being a hog.

        [0]    5096    int
        [1]    4619    int
        [2]    4730    int
        [3]    6842    int
        [4]    4513    int
        [5]    5068    int
        [6]    4601    int
        [7]    4986    int
        [8]    4958    int
        [9]    4587    int

Based on the distribution (6842 / 50000), it appears that the number 3 has about a 13% chance of occurring when it should have a 10% chance of occurring. Sure enough, the pesky programmer wrote this:

        vals[i] = (rand() % 10);
        if ((rand() % 30) == 0)
        {
            vals[i] = 3;
        }
        total += vals[i];

 

The third bug had to do with the app not closing all the time. This one, I’m afraid to say was unintentional, and is the sort of thing that occurs when one doesn’t write a windows app in C for a very long time, then decides to “whip one out”. For those interested in the root cause, it was a missing call to EndDialog() (win32 apps aren’t dialog based by default, and I forgot the extra magic to make it actually exit when closed).

The Testing Challenge

Would you believe that I, the hater of GUI automation, wrote an automated GUI test to test the app? I thought it would be fun to write a quick test from a pure black box perspective. Staying close to my roots, I used a win32 app in C as the test app. I used Spy++ to get the control IDs and went off to the races. The entire app (minus header declarations is below). It takes about five seconds on my middle of the road dev machine to execute the 10000 iteration test (and slightly longer if I were to actually log the test results).

#define LOOPLENGTH 10000
 
int values[5][LOOPLENGTH];
int counts[10];
int additionErrors = 0;
 
// I got the IDs of the window items I care about from spy++
int numIDs[] = 
{
    0x3ea,
    0x3eb,
    0x3ec,
    0x3ed,
    0x3ee
};
int resultID = 0x3ef;
int buttonID = 0x3e8;
 
 
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,  
                       LPTSTR lpCmdLine, int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
 
    HWND hwnd = FindWindow(NULL, L"Numberz");
 
    //ok - now we have all the window handles we need, the rest is (mostly) easy
    ShowWindow(hwnd, nCmdShow);
    for (int loop = 0; loop < LOOPLENGTH; loop++)
    {
        SendDlgItemMessage(hwnd, buttonID, WM_LBUTTONDOWN, 0, 0);
        SendDlgItemMessage(hwnd, buttonID, WM_LBUTTONUP, 0, 0);
        int total = 0;
        for (int i = 0; i < 5; i++)
        {
            int val = GetDlgItemInt(hwnd, numIDs[i], NULL, FALSE);
            total +=val;
            // fill an array with values that we can examine later
            values[i][loop] = val;
            // counts may be enough
            counts[val]++;
        }
        int proposedVal = GetDlgItemInt(hwnd, resultID, NULL, FALSE);
        if (proposedVal != total)
        {
            additionErrors++;
        }
    }
    // logging omitted for now
}

Note, that while this test app runs and obtains accurate results, it will break as soon as a single control ID changes. For a more sophisticated app, I’d prefer a model that would let me get the values in a more reliable fashion. But given the context, it’s a good solution.

But real bugs aren’t seeded!?!

The seeded errors in the Numberz app were contrived, but that’s about the best you can do in a 120 line application. However, the applications we test – and the applications we will be testing in the future, are huge complex systems where interactions and interoperability scenarios cause errors like this to exist. In many of these systems, an automated test is the only way to find these interaction bugs – but most importantly, we need to recognize when automation can help us find errors that we wouldn’t be able to discover otherwise.

Remember, as testers, our job isn’t to write automated tests, or do exploratory testing; our job is to test. Automate what is necessary in order to test efficiently, and explore where it’s necessary to test effectively (which is another way of saying you should automate 100% of the tests that should be automated, and in a nutshell, is how I view test design).

If you’re interested in playing with the source code for the app or test, I put the code in my git repo (open to the public). I didn’t include make files, but those shouldn’t be too hard to put together for anyone who can figure out git.

bookmark_borderNumberz Challenge

Last week I wrote about test design and imagined an app where I thought automation could help with testing. I had some time this morning, so I went ahead and made the application.

image

When you press the “Roll!” button, the app generates 5 random numbers between 0 & 9 (inclusive), and sums the numbers in the “Total” above. The stakeholder’s primary objectives are that the numbers are random, and that the summing function is correct.

To be honest, this is an app where you could probably prove functional correctness via code review, but let’s stick with black box testing for this exercise. The hints in the original post may or may not provide clues to defects in this implementation (that may or may not exist).

Here’s the challenge

If you want to play a little game for me and do some testing, test this app and tell me if it’s ready to ship (according to the stakeholder expectations). Report your findings in the comments section by 11:59pm on Wednesday, September 7. For the best report (tie-breakers go to earlier submissions), I’ll send you a copy of HWTSAM (optionally autographed), or a $20 Amazon gift certificate.

In a perfect world, I’d have an object model or some other way to test the functionality without using the GUI. Sorry – for this example, the world isn’t perfect.

Oh yeah – the app is Windows only – sorry. But if someone wants to send me a Mac Air, I promise I will write Mac version of the app.

I’ll answer any other questions on twitter (@alanpage), or in the comments. Good Luck.

If you want to play, a zip file with the binary is here.

bookmark_borderDesign for *GUI* Automation

I’ve stated my distaste for GUI automation before, but after my last post, I feel the need to share some clarification. I’ve been meaning to write this post ever since I wrote GUI Shmooey, so here goes.

First off, let me state my main points for disliking GUI automation:

  • It’s (typically) fragile – tests tend to break / stop working / work unsuccessfully often
  • It rarely lasts through multiple versions of a project (another aspect of fragility)
  • It’s freakin’ hard to automate UI (and keep track of state, verify, etc.)
  • Available tools are weak to moderate (this is arguable, depending on what you want to do with the tools).

Let’s ignore the last point for now. Partially because it’s a debatable point, but more importantly because it’s a potentially solvable point (one potential improvement would be if vendors would market these tools as test authoring tools rather than record and playback tools).

The first two points above have more to do with test design than the authoring of the tests. It’s possible to write robust (or at least less fragile) tests that work as the product evolves. Designing tests with abstractions and layers and other good design principles will help immensely. Doing this right drives the third point home. Designing robust GUI automation is difficult. Of course it can be done well, but I’m not completely convinced it’s worth the ROI.

That’s why it’s important when designing any test to think about the entire test space and use automation where it helps you discover information about the application under test that would be impractical or expensive to test otherwise. I hate loathe automated tests that walk through a standard user scenario (click the button, check the result, click the button, check the next result, etc.) But I love GUI automation that can automatically explore variations of a GUI based task flow. The problem is that the latter solution requires design skills that many testers don’t consider.

Another example where I like GUI automation is in stress or performance issues. A manual test that presses a button a thousand times is out of the question, but it’s perfect for an automated scenario. In fact, I wrote about something similar in HWTSAM.

Brute force UI automation
In most cases, UI automation that accesses controls through a model or similar methods tests just as well as automation that accesses the UI through button clicks and key presses. Occasionally, however, automating purely through the model can miss critical bugs.

Several years ago, a spinoff of the Windows CE team was working on a project called the Windows Powered Smart Display. This device was a flat screen monitor that also functioned as a thin client for terminal services. When the monitor was undocked from the workstation, it would connect back to the workstation using a terminal server client.

The software on the device was primarily composed of core Windows CE components, but also contained a simple user interface that showed a history of connected servers, battery life, connection speed, and any local applications, as shown in the following graphic. The CE components were all well tested, and the small test team assigned to the device tested several user scenarios in addition to some manual functionality testing. Toward the end of the product cycle, I spent some time working with the team, helping them develop some additional tests.

The missing screenshot**

One of the first things I wanted to do was create a few simple tests that I could run overnight to find any issues with the software that might not show up for days or weeks for a typical user. There was no object model for the application, and no other testability features, but given the simplicity of the application and the amount of time I had, I dove in to what I call brute force UI automation. I quickly wrote some code that could find each of the individual windows on the single screen that made up the application. I remember that I was going to look up the specific Windows message that this program used, but I’d hit a roadblock waiting for access to the source code. I’ve never been a fan of waiting around, so I decided to write brute-force code that would center the mouse over the position of the control on the screen and send a mouse click to that point on the screen. After a few minutes of debugging and testing, I had a simple application that would randomly connect to any available server, verify that the connection was successfully established, and then terminate the terminal server session.

I configured the application to loop infinitely, started it, and then let it run while I took care of a final few odds and ends before heading home for the day. I glanced over my shoulder once in a while, happy to see the application connecting and disconnecting every few seconds. However, just as I stood up to leave, I turned around to take one final look at my test application and I saw that it had crashed. I happened to be running under the debugger and noticed that the crash was caused by a memory leak, and the application was out of a particular Windows resource. At first, I thought it was a problem in my application, so I spent some time scanning the source code looking for any place where items had been using that type of resource or perhaps where I was misusing a Windows API.

I couldn’t find anything wrong but still thought the problem must be mine, and that I might have caused the problem during one of my earlier debugging sessions. I rebooted the device, set up the tests to run again, and walked out the door.When I got to work the next morning, the first thing I noticed was that the application had crashed again in the same place. By this time, I had access to the source code for the application, and after spending about an hour debugging the problem. The problem turned out to not be in the connection code, but in the graphics code. Every time one of the computer names was selected, the application initiated code that did custom drawing. It was just a small blue flash so that the user would know that the application had recognized the mouse click, much like the way that a button in a Windows-based application appears to sink when pressed. The problem in this application was that every time the test and drawing code ran, there was a resource leak. After a few hundred connections, the resource leak was big enough that the application would crash when the custom drawing code executed.

I don’t think I ever would have found this bug if I had been writing UI automation that executed functionality without going through the UI directly. I think that in most cases, the best solution for robust UI automation is a method that accesses controls without interacting with the UI, but now, I always keep my eye on any code in the user interface that does more than the functionality that the UI represents.

To be clear, I am not completely against GUI automation, but I do think that it’s easy (too easy) to get wrong, and that it’s overrated and undervalued among may testers. The best part about my opinion is that if you disagree with me, you have to write good GUI automation. In that case, we all win.

 

 

**For the heck of it, I’ve included a screen shot of the app that’s missing from the book (this was the best image I had, and I didn’t think it was good enough to publish).

bookmark_borderTest Design for Automation

I’ve been pondering test automation recently. Maybe it’s because of my participation in the upcoming stp summit (note: shameless self-promotion), but that’s only the surface of it. I’ve complained about misguided test automation efforts before, but it’s more than that too. For every tester that cries out that 100% automation is the only way to test software, someone else is simultaneously stating that only a human (with eyes and a brain) can adequately test software.

The answer, of course, is in the middle.

But I worry that even for those who have figured out that this isn’t an all or nothing proposition, many testers have no idea at all how to design an automated test – which means that they don’t know how to design a test in the first place. The problem I see most often is in the separation of automated and human testing. When approaching a testing problem, you have failed if your first approach is to think about how you’re going to (or not going to) automate. The first step – and most important – is to think how you’re going to test. From that test design effort, you can deduce what aspects of testing could be accomplished more efficiently with automation (and without).

A common variation of this is the automation of manual tests. It pains me to hear that some testers design scripted test cases, and then automate those actions. This tells me two things: the manual test cases suck, and the automation (probably) sucks. A good human brain-engaged test case never makes a good automated test case, and automating a scripted scenario is rarely a good automated test (although occasionally, it’s a start). Some teams even separate the test “writers” from the “automators” – which, to me, is a perfect recipe for crap automation.

An example would be good here. Imagine an application with the following requirements / attributes:

  • The application has a “Roll” button that, when executed, generates five instances of random numbers between 0-9 (inclusive)
  • The application totals the output from the 5 random numbers and displays them in the “Total” field.
  • There are no user editable fields in the application

For those of you with no imagination, this is how I imagine it.

image

From a manual only perspective, layout, user experience, and interaction are definitely areas that need to be investigated, and that are usually best done manually. If I were to write a few scripted manual test cases for this (not that I would), they may look something like this:

Test Case 1

  1. Press Roll button
  2. Count (use calculator or an abacas if necessary) to verify that the value in the Total field matches the sum of the values below

Test Case 2

  1. Press Roll
  2. Ensure that the values in the lower fields are within 0-9 inclusively
  3. Repeat at least n times

Test Case 3

  1. Press Roll
  2. Ensure that the value in the top section is between 0 and 45
  3. Repeat

I have two complaints about the above tests. The first is that executing them manually is about as exciting as watching a banana rot, and the second is that (as I predicted), they’re not very good automated tests either.

When designing tests, it’s important to think about how automation can (or won’t) make the testing more efficient. What I hope you’ve realized already (and if not, please take a moment to think about the huge testing problem we haven’t talked about yet with this application), is that we’ve done nothing to test for randomness or distribution.

Testing randomness is fun because it’s harder than most people bother to think about. We don’t have to get it perfect for this example, but let’s at least think about it. In addition to the above test cases (granted, the third test case above may be redundant with the first), we need to think about distribution of values within the bottom five boxes. Given the functional goal we’re shooting for, we can probably hit all those test cases and more in a reasonably designed automated test.

Pseudo-code:

Loop 100,000 (or more) iterations
Press Roll Button
Verify that sum of output and total field are identical
Verify that output values are between 0 & 9
Store count of values from output boxes 1-5
End Loop

Examine distribution of numbers
Examine sequence of numbers
Other pattern matching activities as needed

The first loop takes care of the main functionality testing, but where automation really helps here is in the analysis of the output. I’d expect a statistically accurate representation of values, repeated values, and sequences.

That’s stuff you want to use automation to solve. Yet, I keep discovering stories of testers who either don’t bother to test stuff like that at all, or put their automation effort into trying to navigate the subtleties of UI testing (yet something else I have an opinion about).

I don’t’ care whether you’re an automator, a tester, a coder, or a cuttlefish – your goal in testing is not to automate everything, nor is it to validate the user experience through brain-engaged analysis. Your job is to use the most appropriate set of tools and test ideas to carry out your testing mission. You can’t do that when you decide how you’re going to test before you start thinking about what you’re going to test.

Notes:  I don’t know why I picked 100k for the loop – it may be overkill, but it’s also something you have an option of doing if you’re automating the test. I suppose you could do that manually, but you will go insane…or make a mistake…or both.

There’s more to this concept, and follow ups…maybe. The big point is that I worry that people think that coded tests replace human tests, when they really enhance human testing – and also that human testers fail to see where coded tests can help them improve their testing. I think this is a huge problem – and that it’s one of those problems that sounds bad, but is actually much, much worse than that…but I don’t know how to get that point across.

I should also point out that given my loathing of GUI automation, that I’d really, really, hope that the pseudo-code I scratched out above could be accomplished by manipulating a model or an object model or the underlying logic directly. I want my logic/functional tests to test the logic and functionality of the application – not its flaky UI.

bookmark_borderTitles for Testers

I’ve had a few conversations on twitter over the past few weeks about tester titles. My conclusion is that test titles are meaningless, but let’s look at why I think that, and why it doesn’t matter.

Let’s say you’ve been testing for eight years, given a conference presentation or two and wrote a bit about testing on a blog. You’re definitely experienced – given the turnover in test roles, some may even call you an “expert” – you may or not be an expert, but chances are you are at least above average in the testing skills department.

Now – your company just folded and you’re looking for a new job. You go to monster.com or dice.com and  you search for “test’. You see a huge list of titles like:

  • Test Engineer (and Test Engineer II, Test Engineer III, etc.)
  • Quality Analyst
  • Testing Analyst
  • Automation Engineer
  • Test Architect
  • Test Automation Developer
  • Test Manager
  • Director of Test
  • Senior Test Engineer
  • many, many more…

OK – which one do you apply for? I’ll save you a bit of work and tell you that the job descriptions are mostly the same. I’ll give you some advice – if you’re in the job market, do not look for a job based on title – the titles don’t mean anything. With title being out of the picture, I’d suggest looking for companies and locations that interest you and applying for whatever test jobs they have available. Companies may be advertising for a “Test Engineer”, hoping to get someone with half a brain about testing, but would be delighted to have someone with experience. You may think, “How could I take a Test Engineer job when my qualifications dictate that I’m at least a Test Engineer III?” I’ll say it again – titles don’t matter. It’s what you do, and not what you’re called.

As a side note, I give this same advice to people changing jobs within Microsoft where we have standard titles to match career stage. If you find a product you want to work on, but you’re overqualified for the positions they have open, talk to them anyway. Most test managers I know are usually more than happy to up-level their team.

Now let’s fast forward. You have a new job, the work is challenging, and you’re kicking ass. Your job title is merely tester, and you’re worried that people will look down on you because you don’t have a more prestigious title like Senor Test Engineer, or Senior Software Quality Specialist, or Super Tester from Another Planet!.

One last time: in software testing, titles just don’t matter. Software testing is still a relatively new profession and definitions are still evolving for nearly every aspect of the profession. That’s ok (and expected). Focus on what you do (and on kicking ass), and you’ll be just fine.

Or – if consistent titles are that important to you, you can go get a job as a plumber or garbage man (ahem – sanitation engineer).

bookmark_borderMy Love (or Hate) Affair with Meetings

Years ago, I began to get annoyed with meetings. I wasn’t quite sure what I didn’t like about them, so I attended as few meetings as possible. Of course skipping all meetings is somewhat of a CLM (career limiting move), so I had to be selective. Sometimes I left meetings energized and felt like they were a great use of my time, but mostly, I wished I could have had the hour back plus compensation for emotional damage.

Eventually, I discovered Pat Lencioni’s Death by Meeting and gathered some insight. Just like when I began to study testing and was able to classify my testing knowledge with more widely understood patterns and concepts, Lencioni succinctly described why some meetings worked and some didn’t, and I was able to relate that learning to my own experiences. I learned why some (but not all) meetings need agendas, and why conflict is necessary for essential brainstorming. I haven’t perfected every meeting I attend (or run), but the concepts from that book remain in my conscious. I’ve become sort of a sucker for Lencioni’s writings since then and think all of his stories are fascinating insights into team growth and leadership.

I got a bit of a boost a few weeks ago when I read Read This Before Our Next Meeting by Al Pittampalli. This book is a manifesto on how to run a good meeting – and more importantly on why bad meetings are killing us. Having worked in organizations where status and informational meetings are abundant makes the points in this book ring home, and remind me why we can, and must do better about how we hold meetings and make decisions.

I love a good meeting, and after reading Pittampalli’s book, reflecting on Lencioni’s book, and recalling my own meeting experiences, I’m reminded of why. Brainstorming, collaboration, and a level of conflict all contribute to a meeting where the thoughts of the many are far better than the sum of their parts. These are the meetings that energize me.

I’m also reinvigorated to eliminate the bad meetings from my calendar. Meetings where goal is consensus or shoving information down attendees throats don’t belong in successful organizations. We can do better, and I’m inspired to try.