[Note: I covered this topic somewhat in my earlier post on maintainable tests; however, this concept is so critical, in my opinion, that it deserves a separate post. You’ll continue to hear lots about this practice from me as I write and speak more!]
Test code should always be treated with the same care production code is – because test code IS production code! Your source code for your tests may not be deployed to your customers’ production servers, but it’s every bit as important as the components that are
Approach the design, implementation, and maintenance of your test suites with the same engineering and craftsman mindset you approach the design, implementation, and maintenance of your system’s data access layer, business logic layer, etc. If you’re not already familiar with the SOLID principles authored by “Uncle Bob” Martin, then take some time to read up on them. These principles are targeted to developers writing systems; however, the same principles apply directly to testers writing automation suites – if perhaps not quite to the same degree.
While I try to pay attention to all the SOLID principles in my test harnesses, I find that the DRY principle (Don’t Repeat Yourself) is especially critical for keeping my sanity as I build and maintain test suites. If you’re going to pick up one new thing about software engineering or craftsmanship, learn to love DRY.
DRY means avoid duplicating things in your test suite. One example of duplication in a test suite include having your element locators (IDs, CSS class names, XPath definitions, etc.) defined in more than one spot. Another example would be having every test perform the same steps to log on to a system.
This sort of duplication doesn’t seem like an issue when you have 20 or 50 tests, but wait until your test suite grows to hundreds or thousands of tests – and then go try to fix failing tests when (not if!) your UI or system flow changes. Duplication of this sort crushes the maintainability of your test suite over time – you spend more time fixing broken tests than you do delivering great value elsewhere.
Avoid this pain by adhering to the DRY principle: define locators in one location; look to make your tests modular and define workflows in one place. Have your other tests refer back to those central definitions.
If you’re working with test suites which are completely code based then I encourage you to spend some time reading up on the Page Object pattern. This concept treats each individual page on a site (or sub-sections of pages, in some cases), as an object with services and properties. You create a class for those areas and define element locators as properties, and things like error messages or interactions as services. Your actual test code then creates instances of those pages and interacts with them just like you would another class.
Selenium’s wiki has a great introduction to Page Objects, and David Burns has a nicely done blog post on the same topic. Other testing frameworks have community-created tools to help with Page Objects in their particular implementations. (Creating examples of Page Object patterns with the WebAii framework is high on my priority list!)
If you’re working with Test Studio then you have several great features to help you keep your tests DRY. First off, the element repository lets you store your locators in one spot and refer back to them from other tests. You can pull up the element repository explorer and manage those locators in one spot!
If you’re working with Test Studio then you have several great features to help you keep your tests DRY.
First off, the element repository lets you store your locators in one spot and refer back to them from other tests. You can pull up the element repository explorer and manage those locators in one spot!
Secondly, you can use the Test-as-Step feature to use actions from one test in another. This lets you do things like handle logins, environment setup, and test prerequisites in one spot. I recently posted a Telerik TV episode which demonstrates this in action. Chris Eyhorn posted another video showing how to do test-as-step within pure code tests inside Visual Studio.
Using Test-as-Step ensures you only have to define a flow, or set of actions, in one spot. This is a wonderful practice to follow since you’ll be less impacted when your logon screen changes its UI or requires some additional information, for example.
Keeping your test suites maintainable and clean is a critical part of having a long-term successful automation effort. Take some time to learn about the DRY principle. Take some time to think about how to best implement it in your environment. You’ll be much happier as you find yourself spending less time fixing brittle tests and more time doing the actual testing and development which delivers great value to your users and customers!
Jim Holmes has around 25 years IT experience. He is co-author of "Windows Developer Power Tools" and Chief Cat Herder of the CodeMash Conference. He's a blogger and evangelist for Telerik’s Test Studio, an awesome set of tools to help teams deliver better software. Find him as @aJimHolmes on Twitter.