Abstractions Save Testing Time in TDD

April 27, 2015 — Posted by Ken Pugh

In my Prefactoring book, I have a guideline “When You’re Abstract, Be Abstract All the Way”. The guideline recommends never using a primitive (e.g. int or double) in a parameter list, except as a parameter to a constructor. Although the book was primarily focused on creating high quality code in general and not specifically on test-driven development (TDD) , it turns out this guideline can help save time in TDD by aiding in reducing redundant tests.

In TDD tests, you are specifying the semantic contract of a module – its behavior. You need to specify every aspect of behavior with a test. However, you can specify behavior by using syntactic contracts. An example can help clarify what I mean:
Suppose you had a class such as:

class Event {
Event(int level);
setLevel(int level);
// other methods
};

Now you have an additional requirement that the level must be between 0 and 2. So the behavior of the system should be to not allow an Event to have a level outside of those values.

Using TDD, you would create tests that demonstrated that behavior and then write the underlying code to pass those tests. You would have tests for the boundary conditions -1,0,2,and 3. The tests would need to be applied to both Event() and setLevel(). Alternatively, you could create a semantic contract that enforced that behavior. You would create an enumeration, such as:

enum Level {ZERO, ONE, TWO} ;

The Event class interface would now be:

class Event {
Event(Level aLevel);
setLevel(Level aLlevel);
// other methods
};

Now you cannot construct an Event that has a level outside of 0 to 2. Unless you play some funny games (such as in C++), you cannot compile a test that has a value outside of that range. Note that in addition, you have explicitly documented in code that the parameter value cannot be outside these limits. Compare that to the first version of the class – are the limits shown in the method signature?

For the next step, say that you want to be able to vary the limits on the levels. You now turn the enumeration into a class:

class Level {
Level(int value) throws BadLevelException
static setMaximumLevel(int value);
static setMinimumLevel(int value);
}

The Event class doesn’t change. You have to perform tests on the Level constructor to make sure it does not allow a Level to be constructed outside of the minimum and maximum levels. Note you might also use a generic template with tokens for the minimum and maximum, but the concept is the same. Instead of throwing an Exception, you may constrain the input value to the limits. In any case, it is Level’s responsibility to take care of itself, not Event’s.

Subscribe to our blog Net Objectives Thoughts Blog

Share this:

About the author | Ken Pugh

Ken Pugh was a fellow consultant with Net Objectives (www.netobjectives.com). He helps companies transform into lean-agility through training and coaching. His particular interests are in communication (particularly effectively communicating requirements), delivering business value, and using lean principles to deliver high quality quickly.



        

Blog Authors

Al Shalloway
Business, Operations, Process, Sales, Agile Design and Patterns, Personal Development, Agile, Lean, SAFe, Kanban, Kanban Method, Scrum, Scrumban, XP
Cory Foy
Change Management, Innovation Games, Team Agility, Transitioning to Agile
Guy Beaver
Business and Strategy Development, Executive Management, Management, Operations, DevOps, Planning/Estimation, Change Management, Lean Implementation, Transitioning to Agile, Lean-Agile, Lean, SAFe, Kanban, Scrum
Israel Gat
Business and Strategy Development, DevOps, Lean Implementation, Agile, Lean, Kanban, Scrum
Jim Trott
Business and Strategy Development, Analysis and Design Methods, Change Management, Knowledge Management, Lean Implementation, Team Agility, Transitioning to Agile, Workflow, Technical Writing, Certifications, Coaching, Mentoring, Online Training, Professional Development, Agile, Lean-Agile, SAFe, Kanban
Ken Pugh
Agile Design and Patterns, Software Design, Design Patterns, C++, C#, Java, Technical Writing, TDD, ATDD, Certifications, Coaching, Mentoring, Professional Development, Agile, Lean-Agile, Lean, SAFe, Kanban, Kanban Method, Scrum, Scrumban, XP
Marc Danziger
Business and Strategy Development, Change Management, Team Agility, Online Communities, Promotional Initiatives, Sales and Marketing Collateral
Max Guernsey
Analysis and Design Methods, Planning/Estimation, Database Agility, Design Patterns, TDD, TDD Databases, ATDD, Lean-Agile, Scrum
Scott Bain
Analysis and Design Methods, Agile Design and Patterns, Software Design, Design Patterns, Technical Writing, TDD, Coaching, Mentoring, Online Training, Professional Development, Agile
Steve Thomas
Business and Strategy Development, Change Management, Lean Implementation, Team Agility, Transitioning to Agile
Tom Grant
Business and Strategy Development, Executive Management, Management, DevOps, Analyst, Analysis and Design Methods, Planning/Estimation, Innovation Games, Lean Implementation, Agile, Lean-Agile, Lean, Kanban