When you start out writing a test suite it is easy to see the benefits. Usually everyone in the team gets a boost from the assurance and extra quality you gain, and that has got to be a good thing.
Once everyone has got the hang of it though, personalities can’t help but shine through. You’ve got those who know what they’re testing, so think it is ok to truncate some of the human readable parts of their test. There are the perfectionists, who just love to write concise code, perhaps forgetting that test code is just as important, and therefore must be as readable, as production code. Then you have programmers, principled souls who adhere to good practice like ‘DRY,’ principles. Last in my list, you may know more, would be the architects, saving the world one base class at a time.
Before you know it, your test suite has become all powerful, it is such a complex piece of software it has the ability to suck up half your team’s time pandering to it’s whims before it will let you add new features, or providing ghost functionality that takes time to isolate to an un-scoped step file or the like.
It’s time you put everyone straight on just who is who in this test suite!
I’m not talking about the people I listed above. They are your colleagues, team mates, and hopefully friends. The test suite is there to help everyone to get more out of their time, so the best thing is to try and consider the types of entity that can help you avoid building a costly test suite.
The main players that I’d like to consider are;
• Features – literally a feature of the system, the behaviour of which you wish to test.
• Scenarios – the scripts that describe the behaviour you require.
• Contexts – the agents that perform the actions in the scripts.
• Page Drivers – classes that provide a consistent api for your pages.
• Partial Driver – classes to represent common elements in pages.
Features are basically areas of functionality that you’d like to represent as a coherent set of behaviour. You may choose to centre them around the management of a particular item, or they may be some cross cutting concern such as validation, or security, which must behave in a consistent way. I won’t go into how to decide on what is a feature, but there is no single rule that works for all.
Scenarios contain the events in your stories, and are usually grouped together under a feature. Think of scenarios as the actions performed in a story. These usually contain some human readable definition of the steps that take place. Some tools (like Specflow) prefer to keep this code separate from the actual code that does the work, but it is not a prerequisite of a good BDD test suite for this to be the case. Indeed some tools allow you to use a human readable language to define your tests and maintain the connection between the scenarios and the working steps with tool generated code. Other approaches see scenarios written as a list of delegate functions to be invoked in sequence, with an obvious link to the working code.
Contexts are classes representing the ‘people,’ performing the actions laid out in scenarios. They are the working code described in the paragraph above and each class provides methods that describe the abilities that a person would expect to have when using the software. Contexts can be represented as static files, but when choosing how to implement contexts, think carefully how you would like them to be able to maintain state across the steps in your scenarios. There are lots of ways to do this, but it is important to keep in mind, who will ultimately end up maintaining the suite of tests, and try to keep things as simple as possible.
Page drivers, are simply classes that represent the interactions with your pages. They are nothing new in BDD, but they are important as they provide an abstraction for your page. This helps if you change a menu, or link, because you only have to change it’s reference in the page driver and not across all the tests that visit the page.
Partial Drivers, like page drivers could be used to abstract common elements like tool bars. With these, and with page drivers too, the complexity of design is up to you. Obviously you could have base classes involved, stick to static classes, but as long as the structure can easily change with your system, the choice is yours. Just beware of creating something that artificially flatter what your system can really do, or that masks things that you don’t want it to do.
Ok, so I haven’t exactly set the world on fire with these descriptions, but I’m not really trying to do that either. I’d just be happy to see developers, who were sceptical about the value of testing, to not give it up as a bad job. If we overcome the initial “testing is just an overhead,” argument, we still have to watch out for the time that it starts to become difficult to change things due to the amount of tests that break.
Thinking about the entities above helps us to understand where we may be able to use software design to help us, without getting things too complicated. There are many ways to implement acceptance tests, and use BDD to help develop software from the ground up. However, thinking about the characters in the test suite, helps us to bring these powerful tools to bear on legacy software too. The, who is who? Idea helps you not to give the wrong powers to the wrong entity in your test suite
How many times have you been told by a client that the measure of success is how little difference there is from the original, when updating or upgrading a system. This is not an invitation to forget how far software production has come, it provides us with the opportunity to bring BDD practices into our productions, and provide our customers with the confidence to make bolder moves in the future.
As the author of the NaughtyStep BDD framework, I’ve got a few ideas on how to implement the actual tests. I’ve also been doing a lot of work recently on thin clients where the use of Sinatra on Ruby has helped uncover the behaviour I need in order to show that things are progressing. Hopefully in the near future I can share these experiences with you. Thanks for reading.