Saturday, November 15, 2008
Here is a presentation I wrote on what Unit Testing is all about, and how TDD fits into the ATDD cycle.

There are specific things here on testing the UI code with Selenium and JSUnit, and recommendations on how to do unit testing on your database code.

This presentation is in PDF format, but I can post the PPTX format also if needed.

A Practical Guide to Unit Testing1.pdf (503.29 KB)

ATDD | Mocks | Refactoring | Selenium | TDD | Testing | Unit Tests | SQL
Saturday, November 15, 2008 1:08:59 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Tuesday, October 07, 2008
Do you ever wonder why there is an extra "False" printed at the end of each run for unit tests?

C:\Code\sample>ipy UnitTests.py
.....
----------------------------------------------------------------------
Ran 5 tests in 0.395s

OK
False


It looks like there is an exit statement buried inside the unit test framework. We can eliminate the problem pretty easily with the addition of a try/except around the unit test execution. Here is the code to put at the end of your unit test script:

if __name__ == '__main__':
    try:
        unittest.main()
    except SystemExit:
        pass

This catches and eats the SystemExit exception, and runs without printing the "False" at the end of the execution:

C:\Code\sample>ipy UnitTests.py
.....
----------------------------------------------------------------------
Ran 5 tests in 0.387s

OK

cheers!

Tuesday, October 07, 2008 8:09:49 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Tuesday, September 30, 2008

I have been using IronPython lately, and am having a good time testing code with its built-in unit test framework. Here is a brief example of how to write some unit tests for IronPython (or CPython if that's your flavor). These unit tests leverage the "unittest" module available in Python 2.2 and above.

Here is a short test class:

class TestCode:
    localInt = 1
    @classmethod
    def Method1(self):
        return 100
    def Method2(self, a, b):
        self.localInt = a * b

Here are some sample unit tests for it, using the unittest framework:

import unittest
class UnitTests(unittest.TestCase):
    def testMethod1(self):
        cut = TestCode()
        actual = cut.Method1()
        self.assertEqual(100, actual)

    def teststaticInt(self):
        self.assertEqual(1, TestCode.localInt)

    def testMethod2(self):
        cut = TestCode()
        cut.Method2(7, 4)
        self.assertEqual(28, cut.localInt)

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

This example should illustrate that we can write some unit tests for our Python code fairly easily and quickly. It's nice to have a built-in framework for unit testing. There is also a "doctest" module available for doing more like system testing. I am pretty new to Python, so I haven't got examples of this as yet.

If anyone has any suggestions on tools or experience with integration with Visual Studio those comments would be appreciated.

TDD | Testing | Tools | Python
Tuesday, September 30, 2008 5:26:26 AM (Pacific Standard Time, UTC-08:00)  #    Comments [2]  | 
Monday, September 22, 2008

Shawn Neal has a great post (ok it might be a rant) on organizing test code. I agree with his article, on the separation of different kinds of tests into separate assemblies that perhaps can be run at different times (not always with the build). Only the true unit tests should probably be running with each build, and for each developer. If there are other tests that run very fast (by my definition, a fast test either passes or fails in under 1/10 second [100ms]) they too could be included in per-build and per-developer runs, provided that they don't bog down the total test time too much, and provided that they are in separate assemblies.

Someday, when technology allows for it, we should even be able to run our tests in parallel threads or parallel processes (see the 2.5 target features for NUnit). Speed is truly important. If your development team has 10 developers, every minute they wait for a build to complete or a test run to complete is 10 minutes a day of development time wasted. If they build and test 6 times a day each (that's not very much BTW) that is one team development hour per day. Realistically it's likely to be more like 5 or 6 development hours a day.

So if someone is paying attention to how time is spent, we could say perhaps that spending a couple of development hours on the tests to make them run faster, and save one minute per execution would more than pay for itself in a single day.

The moral of this story is keep the tests fast, and when they aren't, fix them or move them out of the main test path.

Monday, September 22, 2008 9:21:35 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Tuesday, August 26, 2008
I posted a simple sample of accepance test code in Selenium and WatiN along with a sample web site to test. You can download the zip file here.

I also have posted a Fitnesse fixture in that zip file that illustrates how we can create a simple test fixture for Fitnesse acceptance testing. The Fitnesse tests aren't in the set, but here is the page wiki code that makes use of the fixture:

!define COMMAND_PATTERN {%m %p}
!define TEST_RUNNER {dotnet\FitServer.exe}
!define PATH_SEPARATOR {;}
!path dotnet\*.dll

Here is an acceptance test using our BusinessObjectTestFixture test class:

!|FitnesseFixture.BusinessObjectTestFixture|
|UserId|Password|Authenticate()|
|administrator|secret0|ADMIN|
|admin|secret0|NONE|
|administrator|secret|NONE|
|user11|secret11|USER|
|user11|secret0|NONE|
|user|secret|NONE|


I also created some STIQ tests, here is the code for the tests and components. Extract this zip file under repository\ProjectRoot folder and it should be able to test the sample site also.

ATDDSTIQ.zip (3.57 KB)
ATDD | Automation | Selenium | TDD | Testing | Tools | WatiN
Tuesday, August 26, 2008 7:03:11 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Monday, August 04, 2008
I have been asked recently about tools I prefer to use in my every-day development. Here is a list of tools, and where to get them.

Visual Studio 2008      Development IDE                   Microsoft
TestDriven.net           Test Runner                         TestDriven.net
WinMerge                  Diff / Merge tool                   WinMerge.org integrates with VS and Tortoise too!
nUnit                        Unit Testing Framework          nUnit.org     Also see mbUnit and Gallio
Selenium                   UI test framework                 OpenQA       Also see WatiN
ReSharper                  Integrated toolkit for VS        JetBrains     (OK I don't actually use it but it's good.)
Tortoise SVN              Shell Integration with SVN      Tigris
Ankh SVN                  Visual Studio Plugin for SVN     CollabNet
Subversion (Server)     Version Control System          VisualSVN
Cruise Control.net       CI system                            ThoughtWorks
RhinoMocks                Mock Object System              Ayende
nAnt                         .NET Build Tool                     nAnt
Fitnesse                    Acceptance Test Tool            Fitnesse
STIQ                         Story Test Tool                    Solutions IQ
GIMP                         GNU Image Manipulation Prog. SourceForge
Notepad++                 Smart Text Editor                 SourceForge UK when Visual Studio just won't do...

Not development tools exactly, but extremely handy:
Process Explorer          Smarter Task Manager           SysInternals
FileZilla                      Upload/FTP client                  FileZilla
DivX                          Decoder                              DivX         Because sometimes we need to watch movies...

That's all I can think of at the moment, but am probably missing some things. I'm sure you'll all (please) chime in with what I forgot... :-)


Automation | Mocks | Selenium | Testing | WatiN | Tools
Monday, August 04, 2008 9:29:38 PM (Pacific Standard Time, UTC-08:00)  #    Comments [6]  | 
Tuesday, July 22, 2008
We the practitioners of Agile and users of Beer, hereby proclaim Agile Beer Night.

The Agile Beer Users Group (Seattle Chapter) will be meeting on Thursday Aug 21, for information sharing, networking, agile discussions, a brief topic presentation on Automated Acceptance Testing, oh - and BEER. Come meet us for a discussion and brief presentation on Agile practices each month.

There is good food, good beer, and a good chance to meet some of the folks who do agile development in the Pacific Northwest, get to know their tricks, and share in their success. The Owl has a fine selection of food, drinks, and spirits for those who choose them.

ABN next meeting will be held in Seattle at the Owl and Thistle Irish Pub and Restaurant at 808 Post Avenue in downtown Seattle from 5PM to 8PM on Thursday August 21 2008.

The September ABN meeting will be on the East side in Redmond or Bellevue, but plans are not firm yet - stay tuned...


Please link this post, track it back, and let everyone know!

Next ABN on Thursday August 21 2008 5PM to 8PM at the Owl and Thistle Irish Pub and Restaurant at 808 Post Avenue in downtown Seattle

Tuesday, July 22, 2008 9:14:39 PM (Pacific Standard Time, UTC-08:00)  #    Comments [1]  | 
Monday, July 21, 2008
I learned a valuable lesson today using Selenium. It seems that the DragAndDropToObject() function doesn't scale well when the HTML is being updated in a loop by the mainline code... This method uses two locator strings, one to find the object to drag, and the other to find the object to drop.

It apparently has to examine the entire XML DOM for each locator, each time through. So, when I created a loop that did a drag and drop 250 times on a page, the first few were not too bad only a couple hundred milliseconds. However, as more and more DHTML was added to the page, it took longer and longer to drop the next objects. I measured this time, and when I charted the data, it was a moderately increasing exponential slope. Definitely not even linear...

It seems that the more HTML was added to the DOM, the longer it took both of the locators to locate their objects, even though those objects were static on the page. It walked the DOM each time, for each locator. Thus the increasing non-linear time slope, because the DOM grows with every loop iteration.

By the time it got to the 50th iteration through the loop, the time taken was almost 2 orders of magnitude higher than the initial one. It made testing this particular feature not doable through this framework. And in measuring how long it took the actual javascript to render the new DHTML, it was just around 100ms, when the Selenium locates for the command took upwards of 7000ms for the 50th loop, but was only 200ms at the initial loop.

The Solution
I didn't find a complete solution to the excruciating amount of time the locator code needs to walk the DOM, but I did end up switching from the DragAndDropToObject() method to the DragAndDrop() method. The latter uses one locator string and a relative X,Y coordinate string (NOT a locator). It's just about zero time for it to process the relative coordinate string rather than the locator. So, in my specific case with this test, I was able to cut the time down to 2.5 seconds for the 250th drag and drop. Still a very LONG running test, but it worked (oh yeah and it found a nice juicy bug too...).

OpenQA people - it might behoove you to take a look at optimizing how you interact with a DOM that is growing or being updated by the code under test... A bit of performance gain in this area would really come in handy.

Monday, July 21, 2008 10:33:26 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Both Selenium and WatiN have been around for a while, and both are fairly good tools when it comes to UI automated testing. Both tools now drive both IE7 and FF2, and are free to download. I have been using Selenium RC for a while now, and it seems to be fairly robust, although sometimes rather frustrating and somewhat slow. Both have a recorder mechanism, and both emit C# code for me. However the WatiN recorder did blow sky high with an unhandled exception when a pop-up window came up, but the recorder code was written by someone else so I won't hold it against WatiN.

I tried WatiN for the first time today, and decided to go with the V.2 CTP instead of the .NET 1.1 release. It seems that some of the API's have been refactored into more sensible structures (factory patterns, etc.), but somehow the things that would have made the most sense to me in the API were structured much differently that I would have expected. There were some problems with my IE (it kept crashing unless I ran the debug version of W2). However, I blame this on IE, not on W2. FF has a plug-in that needs to be manually installed. It comes with the CTP, but doesn't get installed. Hopefully this will be integrated by release.

Most of the basic features are similar in function but not implementation. I can see writing an interface class and a couple of wrapper classes that implement the interface, one each for WatiN and Selenium, so we can have the best of both worlds.

WatiN Pro's
  • No proxy server required. It just runs. Runs both FF and IE, switchable with the parameter to the factory method that creates the instance.

WatiN Con's
  • Documentation is less than sparse.
  • I could not find a way to do a "drag and drop" which is easily accomplished with Selenium.
  • Does not handle pop-up windows. This was the show-stopper for me.
Selenium Pro's
  • polished code
  • well-documented functionality
  • lots of examples
  • handles lots of weird types of conditions and situations (most of which we will all need at some point.)
Selenium Con's
  • have to run a java proxy in a separate process and set it up and tear it down
  • slow in places, due to proxy and not-so-well-written sections of code
  • locators aren't always easy to figure out. Tools like Firebug and XPather help identify locator strings.
Since it does not handle pop-up windows (or I just couldn't figure it out in about 4h of research), this was the end of the line for it. Selenium does handle them, and has been able to accomplish 100% of the weird scenario tests I have needed so far. Loads of tweaking and frustrating trial and error notwithstanding.

So, until we have a bit closer to release for WatiN, Selenium still wins (for now). However, I definitely plan to write the interface and shim both out so I can use either or both later on. Stay tuned for that posting, that will be the money shot...

In closing, let me just reiterate that every developer should be thinking about UI automated testing for web code. Each user-interactive element on the page NEEDS AN ID. That's every link, every button, every text box, checkbox, radio button, and other user input elements. The ID's need to be simple, and either fixed, or predictable. With these things in place in the production code, it will be testable and easier to validate. Better quality code will make it out to the hands of the users, and all will be right with the world. Amen.

<steps down from soapbox./>

Automation | C# | Selenium | Testing | WatiN
Monday, July 21, 2008 10:18:35 PM (Pacific Standard Time, UTC-08:00)  #    Comments [1]  | 
Monday, June 30, 2008
Do you write installers? A lot of times I hear that all the features or stories are completed, but nobody has given any thought to how actually to ship the software and install it. This is not a trivial story, and usually it is the user's first experience with the software, so if it doesn't go well, your reputation starts out in the hole and that's not easy to overcome. Let's assume that we are more thorough and professional than the average joe, and we create an installer for our application that does three things: Install, Upgrade, and Uninstall.

Most of the time I write installers that are MSI or Setup.exe based, since I sort of get those for free with Visual Studio and .NET. If I have a file or dependency, I simply add it to the package and tell it where on the target machine it is supposed to go. It gets compiled and built (only by DEVENV.EXE by the way - MSBUILD doesn't know how to build setup projects...) after the main assemblies.

The main assemblies all have unit tests of course that run with the build, so everybody is green before anything gets built to install. Installers can be kind of tricky. Don't be tempted to run it on your native development box. If you haven't got lots of proven experience with them, be sure to run the installer for the first few iterations ONLY on a virtual machine that you can restore to its original image with a couple clicks. Let's just say I have seen some interesting recursive registry damage from an installer...

We need tests for the installer, but in this case we are not talking about "unit" tests, but rather functional tests. We need the tests to actually install and uninstall the software.

Testing the Installer Code
First up - test the UNinstall. From my experience, I have seen this path as the best one to start with. Install it manually only after the failing test has been created (and test it only on the VM). You can use either NUnit or MSTest as the framework to run the installer. HINT: to uninstall the software exec this command line:
MSIEXEC /X {guid}
where guid is the identifier for your project. This guid can be found in the .VDPROJ file as the key called "ProductCode." Don't change this value ever, or it will disconnect your next install from your current uninstall, and all kinds of weirdness can happen.

Assert that the registry keys get removed from CurrentVersion as discussed below, and that any registry entries created by the installer are removed.

Gotcha
So it didn't work as planned, and there's an error... an Assert fails, which throws an exception, and your tests end and have left the software installed on the system. The next time the install test runs, it won't work because the software will already be installed. So... make sure you have try-catch logic on everything before you assert anything. The finally block should call a function that uninstalls the product. We know that it will work, because we have tests for it...

Unlike most unit tests where we want to be able to run tests in any order, and have complete independence, functional tests for an installer are much simpler to write if they can be run in the Install, Upgrade, and Uninstall order. However, we don't write them in this order, we start with the uninstall first, then add tests for install, and finally the upgrade cases.

Make sure to catch everything done by the installer in the uninstall test, and do not proceed to write install tests until you are absolutely certain that the uninstall works properly and is adequately tested.

When you move on to the install case, it should be a bit easier, as all you need do is reverse the tests in the uninstall. Make sure that you place this test code before the uninstall test code, so that it is now automated.

Now, voila - you have automated tests for your install code. Finally, your upgrade test can be written to confirm the behavior if the installer is run on a system where the software is already installed. You may want to just fail the install and tell the user to uninstall the previous version, or you may want to upgrade in place. A true upgrade is far nicer to the user, but it is a lot of complexity some times when data migration, customized configurations, or other scenarios are needed. Make sure that any of this functionality is captured in stories, and documented with thorough testing.

What do I test?
  • Make sure to open the registry after you install your application, and find the key to make sure you can uninstall it later:
    • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{guid}
    • This key's value should have the above mentioned MSIEXEC uninstall statement. Check it with an assert to make sure it's correct.
  • Make sure each of the assemblies and executables are sent to the correct target folder on the target machine.
  • If you support command line options or fancy things for the installer, make sure to test each and every one.
    • Write the tests first of course...
  • Make sure that config files, documentation, and support files (such as XML or other things) are delivered to the correct locations.
  • If any files are dynamically generated or modified by the installer with custom actions after delivery, make sure that the modifications are correct.
  • Make sure that directories are created on install
  • Make sure that the ACL security on the folders and files is correct, if this is something your installer does.
  • Make sure that directories are deleted on uninstall (except if logs or other artifacts are in them, they won't be deleted)
  • Make sure these things are written in such a way that they are easy to call from a test, and that they handle errors and take care to leave the system in the same state as before the tests ran (with the software uninstalled).

Where do I run the tests?
A word of advice: DO NOT RUN THESE TESTS ON THE BUILD SERVER... it is tempting since they look like "unit" tests, but don't do it. Build servers are not something we want to be messing with installing and uninstalling software. Especially software that gets built every few minutes... The best way to automate the whole process is to have the build server build the app, the installer, and the installer tests and deliver them to an install server, or sandbox server. This can be done through a build step that copies all the executables to a UNC share on the sandbox server after each build. The sandbox server can be set to watch for new files in a folder and automatically begin to run the tests. If you are using CruiseControl.net, this is nicely accomplished by running CC.NET on both the sandbox server and the build server. The build server can "import" the red/green status of the functional tests from the installer to its own dashboard, just as if they were local. It takes a bit of work to get this all figured out, but once it's done it is a nice way to live. I wish I had all my CC.NET code to post, but unfortunately it belongs to someone else and I don't have the rights to post it. If someone has wrapped this concept up in an easier to run turn-key package I would love to hear about it with a comment.

If there are any questions about this, please feel free to comment below and I will try to reply as soon as I am able.
TDD | Testing
Monday, June 30, 2008 8:41:41 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Wednesday, June 04, 2008
Why to Do It
When running lots of unit tests, there are distinct advantages in using all of those cores and cpu's that most of our modern computers have. We can parallelize testing so that we gain two distinct advantages. First, the testing will complete much faster. If you have 4 cpu's or 4 cores, we should see at least a halving of test time, if not more. Secondly, we prove our code is able to run in the closer-to-real-world scenario that other things might be going on while our code under test is executing. Plus its just cool to do multi-threading.

The by-product or side effect benefit we get also in multi-threading our tests is that we need to put more careful thought into the design and construction of test cases, and by that virtue, our software under test. The ability to multi-thread tests is I think one of the highest bars we have in demonstrating conclusively that our software is robust.

Advice on How to Do It
Separate tests into separate test assemblies that can be launched by the build server in parallel. There is no real reason to sequence tests, unless they sometimes interfere with each other. If they do interfere with each other, the tests are poorly designed and should be re-written as independent.

See the Pragmatic Unit Testing book or see this article for good advice on how to write good tests that you can parallelize.

Tests must be thread-safe. We probably should be able to run the same test at the same time without collisions.
Tests must be TRULY independent. This usually means that tests need to generate data that is keyed specific to that test run.
Tests must not have side-effects. They must leave the test system in the state they found it.

The new version of NUnit (2.5) is rumored to have functionality to be able to run tests in parallel threads. The currently released version has only one thread to run all the tests. In some preliminary research I have done, when manually coding up multiple threads to run each test in parallel from a single "unit test" method, it has some contradictory behavior. NUnit reports that all tests pass, but the GUI bar turns red.

More to follow on multi-threading test with MS Test...

C# | TDD | Testing
Wednesday, June 04, 2008 1:20:10 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Tuesday, June 03, 2008

I was explaining to someone about different types of testing I do with my code, and how mock objects can be used in unit tests. I used the example of the paint truck at the airport that spray-paints lines on the tarmac. Its job is to put down wide lines, narrow lines, in yellow, and white, and of a certain length, at specific places on the runways and taxiways. The truck is driven by a person, and the paint spray system is operated by driver. It's not a perfect example, but it may get the point across.

When we model this with truck software and try to test it, most developers seem to tend to go right for testing the whole solution end to end. That means trying to figure out how to fire up the engine, position the truck at certain coordinates, be at a certain speed, and then test the spray gun and see if it paints the correct stripes. It's a hard problem to solve, to try to set up with all these things and get it just right - just to see if the painter works properly. It can be a daunting task to try to test software this way, yet most developers who do "unit testing" are trying to do just this kind of thing. My take is that this is not really "unit testing" but actually "functional" testing. While it is definitely good to have functional tests, I prefer my development team to focus on more narrow areas such as individual classes. If these are thoughtfully designed and tested individually, they should work well when combined. This is also where integration and scenario testing come in. These types of tests are beyond the scope of unit tests.

Let me give an example that explains how we might be able to go about testing this a bit more carefully. Let's take the truck as a single "system" and the paint sprayer as a separate "system." These systems are really not very coupled - the sprayer runs on the truck's electric system, but that's about it. It makes sense to decouple them in trying to test them.

If we separate out the sprayer as a separate system, the only inputs it needs from the truck are the electrical connection and the trigger input. We can "mock" out these connections by supplying a new power source and trigger input connector that has the same "interface" (that is - implements the same interface class in code). Now we can test the system without needing to have the actual truck around. This is the concept of mock objects at its best in unit testing.

We can separate even the power mock object from the trigger mock object. We can control how these mock objects behave precisely, and keep them in specific states so that the only variables under test are in the sprayer system. We can then test what happens to the sprayer if we make the power go away, what happens if we trigger both paint guns at the same time, and making sure we can turn on and off each gun. These make great unit tests and document how our code is supposed to work. They should run very fast, and not require any diesel fuel...

All of the ability we have to be able to mock things like this, depends on programming to interfaces, which is a long-time engineering best practice to avoid decoupling. If we design our software to implement interfaces, we can then easily substitute dependency systems at test time with our own controlled version, and focus the testing on a more narrow area, while making the tests run faster at the same time.

TDD | Testing | Mocks
Tuesday, June 03, 2008 10:55:32 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Monday, June 02, 2008
I have been using TestDriven.net as a tool now for a few weeks, and I have to say that it is a fine addition to my tools collection. It gives me the flexibility I need to run tests in any manner I choose, simply by right-clicking. It's a Visual Studio add-in for 2005, and 2008, and it works seamlessly with a variety of test frameworks (NUnit, MbUnit, and MSTest being the most notable).


Speaking of NUnit, another excellent tool that I find invaluable to help me test my code. NUnit now has RowTest extensions (like MbUnit) in the production release (2.4.7 and if you aren't using this version, you should upgrade), and Parameterized Tests coming soon, and they look really cool. I find that I can replace a lot of repetition in my tests with this row based system. It enables me to write more tests faster, and that's always good. I am hoping that the new release goes into production mode very soon.

UI testing with Selenium is another favorite topic, I will write up another article later with examples of how to do real automated user interface testing using NUnit and Selenium. However, feel free to start playing with it now... its a great tool also, and plays nicely with the other tools in the toolbox.

Use these tools in good health, to help get your code into production as bug-free as possible by testing the heck out of it!

P.S.
Please make your unit tests into separate assemblies... no one-massive-monolithic-test assemblies please... and the tests should run FAST. If you mock out all the database, network, web service, etc. calls, you should be able to get all of your tests in an assembly run in under 5 seconds. Aim for a target of 100 tests per second, and you will be a much happier camper.

If you are a real stickler for this (and I recommend it...) add this code to your test assemblies:
private static DateTime assemblyStart;

 [ClassInitialize]
 public static void MyClassInitialize(TestContext testContext)
 {
     assemblyStart = DateTime.Now;
 }

 [TestCleanup]
 public static void TestCleanup()
 {
     Assert.IsTrue(
         assemblyStart.AddMilliseconds(5000) > DateTime.Now,
         "Tests took too long to execute.");
 }
Enjoy!
C# | TDD | Testing
Monday, June 02, 2008 10:31:40 PM (Pacific Standard Time, UTC-08:00)  #    Comments [2]  | 
Tuesday, April 01, 2008

Acceptance criteria should be our measuring stick when we write software. These criteria should give us the direction to go in writing features, and ultimately the final answer on whether the software is "done" or meets the customer's need. When the customer (or the customer representative, product owner, or business analyst) gives us a notion of what the software is to do for them, it represents a guideline and a goal for our development.

  This article is a discussion of ATDD in an Agile development context with Scrum project management and Extreme Programming [XP] development methodology. However it does not apply specifically to Agile. These same techniques can be applied with almost any mechanism.

  Test-Driven Development [TDD] says that we should first write a test before we write the code. This forces us to understand clearly what the code is to do, because we have to write the test to verify it. Writing the test is usually the hard part - the code next is easier. This is where the discipline of TDD is most needed. The test itself should be failing when executed, since we don't have the code under test [CUT]. This is a good sign - we need to actually "test the test." We then write as little CUT code as needed, just to make the test pass. Then, we start all over again - write a test, some more code, etc. We refactor the CUT as needed, to make it a cohesive, maintainable design, while still keeping all the tests passing. In this way, we have a complete test framework wrapped around our high-quality code, which makes certain that the code always functions the way we intended no matter what kinds of changes we make internally to it.

  This process of TDD as described, is the traditional mechanism we now refer to at Unit Test-Driven Development, or UTDD. There are higher-level tests that we can write also, that have the same impact on our development process. Applying this same concept of a failing test driving us to write code is where this discussion now leads, but at one level of abstraction higher. We now look to the Acceptance Criteria to drive our TDD, or now ATDD.

  1. Acceptance Criteria gives us a target for writing Automated Acceptance Tests [AAT's] a. Acceptance Criteria need to be written into an executable set of automated tests. b. AAT's should be able demonstrate to the customer that their criteria for the functionality has been met. c. Ideally, this should include as much detail as the requirements bear out, and as many tests and checks are necessary to convey that each of the criteria has been accounted for.

  2. AAT's give us a reason to write code (they are failing - no CUT yet) a. AAT's can be written before writing the code, or written one at a time following this process.

  3. We now write the empty framework for the CUT. Some AAT's may still be failing, but that's OK. a. This step deviates from strict TDD in that we are writing code, but not for the intent of passing a test. b. One example is that if a criteria states that a customer is able to bring up a web page with a set of information, obviously we need to provide a web page. c. This framework concept is creating the empty page or container for the code we are going to write. d. The empty framework should not cause AAT's to pass, because AAT's should written to test at a higher level of functionality.

  4. To make the AAT's pass, we need to start providing the functionality inside the empty framework. Here we need to apply the standard TDD concepts, and write a failing unit test.

  5. We now have a failing unit test, so we write enough CUT to pass that test.

  6. We repeat at step 4, refactor, and continue following the UTDD process as described above.

  7. When the functionality that the AAT's require is there, they will be passing, Unit Tests [UT's] are passing, and our story (feature) is complete. We now continue to step 1 again for the next story.

  How do I do it? What do I need to get started?

Acceptance Test Driven Development is a practice that can yield good returns on the time invested. Customers will be pleased with the software they receive, bugs will be fewer, and delivery times will be shorter. However, there are a few things that are needed to make this practice effective in an organization.

  1. Buy-in
    1. People must be bought-in to the concept that test driven development is a good thing.
    2. Management must support this practice, for if not, it will be a much more difficult thing to accomplish.
    3. Developers must be willing to put aside their "classical" training and try something new.
  2. Testing Tools
    1. If we can't write an automated acceptance test for our product, we can't do ATDD. We need a tool designed for testing the particular type of product we are shipping.
    2. Story Test IQ [STIQ] is a great tool for automated testing of web applications. Straight Selenium RC under C# code, driven by NUnit also works great, in my experience. VSTS has some good tools also, as do Fiddler, and probably lots of other products.
    3. The framework must be in place on day 1 of the iteration to begin writing acceptance tests. If it isn't available, we won't be able to do ATDD.
  3. Skills
    1. Developers need the skills to be able to envision what is to be delivered, and be able to write automated test scenarios for the acceptance criteria.
    2. Testers need to be able to validate that the tests cover enough of the functionality through testing the criteria, and provide other functional, integration, load, and performance tests in addition to the developers' unit tests and acceptance tests.
    3. Management needs to be able to direct the right resources at tasks, no matter whether they are Development or Test tasks. Sometimes it's best to blur the lines between the disciplines to make this practice most effective.
    4. Customers need to be aware that they are actually going to get what they specify (and perhaps ONLY that much). Education on criteria evolution is almost always required for customers. Don't be surprised if only 50% of the criteria are discovered in sprint planning and story generation for the first couple of iterations.
  4. Experience
    1. TDD takes discipline, and ATDD even more so. This is not a practice for an organization just beginning down the road of TDD. Put in at least 6 iterations of using strict TDD first before trying ATDD. The experience gained with using TDD will naturally flow into ATDD, and the organization and the customers will see the benefits.
  5. Perseverance
    1. Good things don't happen instantly. It takes some time to see the benefits of ATDD.
    2. Be patient for a few sprints. It should take approximately three iterations to get it dialed in.
  6. Customer Cooperation
    1. Customers must be available for providing their criteria for acceptance.
    2. Customers generally are not experts in this type of "specification" of criteria, and must often be helped through the process at first, to generate usable criteria.

ATDD | TDD | Testing
Tuesday, April 01, 2008 10:10:03 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Sunday, March 23, 2008

Aren't developers just supposed to write their code and let the test team test it?

ahem.

no.

As a developer, I take pride in delivering *working* software. If I don't test my own software, I think that I'm really failing to do my job. Testing is not just for "testers."

As a professional software engineer, I need have not only unit tests for my code (a Development practice by the way), but I also need to write automated functional tests to make sure that all the functionality works as I think it should. Then, I need to have automated Acceptance tests that tell me if indeed the whole system works together to deliver the business solution that the story or requirements describe.

Acceptance Tests
  Why do I start with acceptance tests?

Because... they should drive the entire development process. Test-Driven Development doesn't necessarily have to *always* mean Unit Test-Driven Development...

The Acceptance tests drive me to write code.
In order to write code, I need a unit test.
Then I can write the code that passes the unit test and the acceptance test.

job well done.

Unit Tests
  I write enough unit tests to be able to make sure that the functionality I write works as I intended. Not too many - tests require maintenance as well as the code they test - but enough to ensure that it's safe to refactor just about anything in the code and make sure that it still works as intended. This is the safety net that unit tests provide.

Code
  Write some. It should make the tests pass. Failure is not an option.

Functional Tests
  We need to make sure that all the pieces of functionality behave in a known way. This is what functional testing does.



Integration Tests
  We need to make sure that all the systems co-operate. Integration tests are deeper yet than functional tests, these are more like "end-to-end" tests of particular scenarios. Usually these scenarios cover all the happy paths of end-to-end, and most likely a couple of failure scenarios as well, to illustrate how the system overall behaves in failure modes.

Deployment Tests
  You DID want to INSTALL the software and use it, right?

So... you got a test for that?

Sure you do.

Deployment tests are essential for making sure the software delivers and configures the binary bits in a way that's useful to the user. Uninstall is a particularly critical issue as well. Make sure that you have complete testing around these critical fundamental features of the software.

ATDD | TDD | Testing
Sunday, March 23, 2008 9:47:08 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
Monday, February 11, 2008

Test Driven Developer


Assert.AreEqual(13, stripes);
Assert.AreEqual(50, stars);
see
ms like enough tests to me...

NOT!

Welcome to Test Driven Developer! This site is dedicated to those who understand the benefits of test-first development, and the advancement of the practice.

  It is sometimes hard to convince traditionally trained developers that it is better to write a test first, before writing the code. In Test Driven Development, we always write a test first before writing the code.

Many developers are hard to convince to use this methodology. It is very often difficult for a developer to understand completely what the code needs to do. Yet - they want to proceed to write it anyway? It's kind of a flaw in the thinking process.

Lucky that you are smart enough to know that there's a better way..

TDD is not a Java thing. It's not a .NET thing. It's not language dependent. Anyone can do test-first development, for literally any kind of software development.

Figuring out the test for some code is always the hard part... that's why we like to do it first, and get it out of the way.

TestDrivenDeveloper.com is a John E. Boal web site. Please see also my personal blog and my Agile Development blog

TDD | Testing
Monday, February 11, 2008 10:33:29 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]  | 
© Copyright 2008, John E. Boal