Better Software - September 2008 - (Page 28) bunch of other people in a workshop) a clever way of explaining how automated acceptance tests in ATDD differ from your typical automated system test. He referred to levels of abstraction used in interaction design. He explained that interactions can be described at three different levels, as shown in table 1. Typical automated testing tools—both commercial and open source—work at the tasks level. For our executable specifications, made up of automated acceptance tests, we want to express the intent and automatically validate the system against examples of anticipated realworld usage. Furthermore, we don’t want to duplicate the effort by writing the tests as a document and then writing them again in a programming or scripting language. This is wasteful and risky when the document and code become out of step with each other. So that the tests are expressive of intent, we write them at the activities level. Because they express concrete examples, they also must be specific (rather than general). For example, a generalizing statement would be “valid username and invalid password” whereas a specific statement would be “username of ‘antony’ and a password of ‘thisaintright.’” In reality, I find it useful to clarify intent in certain situations, so I might want my example to be more specific but hint at the general—for example, “a valid username of ‘antony’ and an invalid password of ‘thisaintright.’” Thus, the acceptance tests, in the simultaneous roles of requirements specification and automated tests, must be more activities level than tasks level and more specific than general. Let’s consider this user story: As a registered user, I want to identify myself to the system So that I can use the personalization features. One of the automated tests for this story might look like figure 1. Behind the test in figure 1 are an ATDD framework called FIT and some fixture code that is written by the team, acting as a gateway between the framework and the application you’re developing, as shown in figure 2. 28 BETTER SOFTWARE SEPTEMBER 2008 Table 1: Levels of interactions Figure 1 The fixture code receives inputs given to it by the framework, performs the tasks associated with the activities, and returns the application’s response to the framework. The test framework compares the returned result with the expectation in the test artifact and displays whether each condition passed or failed. This has many benefits, not the least of which is encouraging reuse of code that supports the automated tests. This looks a lot like the idea of datadriven tests. Nothing new, of course, but what is different is how expressive these tests are and how people go about implementing them. The fixture code www.StickyMinds.com tends to be written in the same language as the production code and is version controlled in the same way as the production code. It is also often tied into a continuous integration server so it is executed automatically several times per day as part of the software build process. These characteristics result in tests being run more frequently, developers helping to maintain the test code as the application changes, and the test artifacts and production code being kept in sync through shared version control. These characteristics also make it simpler to run business-logic tests through http://www.StickyMinds.com
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.