September 2008

Monthly Archive

Defining the “Unit” in Unit Testing

Posted by on 27 Sep 2008 | Tagged as: Agile, Architecture, DotNet, Java, TDD, XP

“Hey, Ben. We just figured out a great way to manage test-driven development and good database design.”, said an enthusiastic developer using Extreme Programming (XP) practices on their project. “Our application is highly data-centric. Therefore, in the first iteration we design the database schema modifications and create tests to validate all of it’s implementation characteristics. The next iteration we build the data access layer and business services on top of the database modifications. This has allowed us to design the database correctly before developing code around the wrong data model. What do you think about this approach?”

Ben is an agile coach who checks in with this team from time to time. He likes the fact that this team has continually looked for improvements in the way they develop software. In this case Ben sees a potential issue and so he asks a question, “What do you deliver to the customer at the end of your first iteration?”.

“We show the customer our database design and tests executing.”

“What does the customer think about this?” Ben probes further.

“He doesn’t seem to care about this part of our product review. He told us that we should just show him the finished feature after the next iteration.”

“Didn’t we setup a Definition of Done for the team to assess quality of our delivery each iteration? If we don’t have customer accepted functionality at the end of the iteration didn’t we decide that the work is not done?”

“Yeah, but we found out that the data design and automated test case development for it takes too long to fit into an iteration along with feature development on top of it.”

“Hmmm, that sounds like we may be working around our definition of done which seems like a ‘smell’ in our process. Lets sit down and see what the root cause of this new process that extends development of functionality over two iterations rather than within one iteration.”

Relational databases have proven themselves to be great persistence platforms. As their usage increased in software development they have gone beyond their intended usage into the application server realm with stored procedures, functions, and triggers not to mention parsing and other functionality added recently in the marketplace. Applications become highly dependent on a relational database and become more difficult to change over time. The more difficult the relational database becomes to change the more we baby it and look for ways to not have to modify it for long periods of time. This leads to designing up front and the “getting it right the first time” mentality with our data models.

When we start in the bowels of our system with design, tests, and implementation we tend to “gold plate” our implementation. Thus developing more code and tests than is actually needed for the implementation. Many times this approach violates the YAGNI (“you ain’t gonna need it”) guideline for agile software development.

During coaching engagements I speak with team members about starting from the user’s point of view even in development of your unit tests. What is the next piece of functionality that will support their feature request? Many developers immediately comment that these are no longer “unit tests” as they have previously defined them. I ask what they characterize as a unit test and it usually is not easy for them to verbalize. If we think of a unit as part of an existing design we will tend to write tests for all potential ways the design could be used. If we always drive our next test based on what the next unit of functionality should do for the user then we will implement only what is necessary.

Behavior-Driven Development (BDD) describes a process for developing from the outside in. The first piece of code the developer implements in this approach is the interface. From the interface a developer drives out the rest of the functionality. This ensures that all code is directly related to functionality valuable to the customer or other code already written. Although there are great frameworks out there to support BDD in your development environment you can begin by starting to think about your xUnit tests in this manner. Start from the interface and make sure each additional capability implemented to satisfy a test is adding or supporting value from the user’s point of view. Please read this wikipedia entry on BDD for actual test case and code examples.

In addition, I will make a suggestion that whenever a technology element within your architecture is difficult to change you should definitely minimize interactions with it and abstract all access. Proper unit testing that focuses on a unit of code will force the use of proper interface abstractions in order to not make the test dependent on components external to the unit such as a database. Minimizing interactions will reduce your application’s dependence and also increase changeability of it for future business functionality to be implemented. Business changes so software should be able to change with it.