Why you should refactor your test automation scripts
Originally Published on TechBeacon, 9/4/2019
Paul Merrill
CEO, Test Automation Consultant, Beaufort Fairmont
Refactoring isn't just for software developers. Test engineers can also use it in testing and test automation.
I'm going to show you how below (as well as at my upcoming presentation this month at STPCon Boston). But first, let's be clear on what "refactoring" means. My definition is similar to Martin Fowler's: changing code so that functionality does not change, but the readability, design, structure, or maintenance of the code is better.
I recall pair programming with people who refactored and feeling as if they were "working above the code." They didn't get stuck on the details of algorithms or complex logic, as I did. Instead they would massage the code to the point where they could better understand it, wrapping it in unit tests, and changing functionality only once they had a clear understanding of the code.
How many times have you been in a sprint planning meeting and heard a developer say, "All I have to do is refactor the blah-blah-blah to do that new thing"? If you didn't know what refactoring was, you might believe it to be an elixir—something developers are gifted after slaying the dragon of a computer science degree.
You might believe it can solve any problem, and heal any Scrum team's codified woes. The use of the word is so commonly associated with fixing problems that you might think "refactoring" fixes functionality.
You'd be wrong.
The key to refactoring
A major aspect of refactoring is the second phrase in Fowler's definition, "... so that the functionality does not change." When people say they're "refactoring so that ..." stop them right there. The "so that" implies a change in functionality. In that case, whatever the person is doing is not refactoring.
To be clear, when refactoring, functionality does not change.
Refactoring in testing: The benefits
Fowler's strict definition is that refactoring is only for code. It "improves the design, maintenance, and readability of code." He also states that using the term outside of coding is inaccurate. You should use "restructuring," or some other term, he says, but I'm a bit more flexible.
I believe there is a one-to-one correlation between many of the formal refactorings Fowler discovered and similar techniques in modifying test cases, both automated and written.
I've found great pleasure and use in refactoring test cases using a similar mechanism to what Fowler described. Here's a list of four of the benefits that I will be speaking about at STPCon in Boston, where I'll talk more about my specific techniques and how I see them used with testing.
1. Better test cases
My clients often want to automate long-running, complex test cases. On the surface this makes sense, to save time on long-running tests with automation. (I've found that using this approach at the beginning of an automation effort is counterproductive, but that's a story for another article.)
Many long test cases should be broken up into smaller test cases. Let's compare a test case to a class in an object-oriented programming language so that you can see the parallel between Fowler's refactoring and the modifications you can make to tests.
In refactoring, when a class is too big, you use refactorings such as "extract method," "pull up field," "pull up method," "push down field," and "extract superclass" to break classes and methods into smaller chunks of code that you can more easily understand. Once you understand it, you can see what the class is doing.
How often do you look at a test case and think, "What is this test case doing?" This is much the same issue as with code. This may indicate an unclear or overly complex test case.
You may be able to break the test case down into smaller chunks to see what it's doing. Then, you may want to split the test case into smaller test cases. The smaller the test case, the easier it is to maintain, understand, manage data for, run in parallel with other test cases, and execute. Together, these constitute "better test cases."
2. Better test automation
Test automation isn't all test cases, and good test automation code is about more than creating page objects. Many times we need to interact with databases and APIs, mock data, simulate third-party services, and more.
The code you use for that can be refactored to better support you and reduce maintenance.
3. Lower test automation code maintenance with more reuse
Maintenance is the single most under-resourced activity in test automation. Refactoring can reduce maintenance by breaking down test automation code into smaller, more reusable pieces. And it can do the same for automated test cases.
More reuse in your codebase means fewer places to fix problems. It also means less time to search for defects in your test automation code.
Lower maintenance means less cost for automation, quicker feedback for developers, and faster delivery of features.
4. Easier ramp-up for new testers and test automation engineers
I've rarely met an automation engineer who didn't want to rewrite whatever code he inherited at a new job. People want to use tools they're comfortable with and codebases they already know. But businesses don't run on comfort. They run on cash flow.
Redoing the work of another instead of using it is costly, and doing so dooms many an automation project. Working in-sprint to create high-quality features for paying customers is preferable.
My team works diligently to use existing automation code that our clients have already written. We rewrite a section of code only when it's clear that rework is less costly.
Our preference is to refactor what's there, if refactoring is needed, and leave code alone whenever possible. This endears our clients to us, since our costs are less over time and we produce better work, and more of it, than do other groups.
Earn your refactoring chops
Learn the skills of refactoring to modify frameworks you inherit. This way you and others can better understand it. Improve the design so that you can better add to it.
The test automation code you inherit may be written in a way you don't prefer, but that doesn't mean it doesn't have value. Many times people just as smart as you, with more understanding of the business, wrote what you're rewriting. Give them a break. Learn their code. Refactor it so that you can understand better. Consider refactoring your test cases as well.