Sponsored Link •
Automated tests can make demands on an API that are not made by any other client of the API. For example, you may find yourself wanting to add methods to a class that are not needed by any other, non-test clients. To what extent do you feel automated tests should be allowed change the API being tested?
Writing tests can help improve the usability design of an API, because when you write tests, you put on the shoes of a client trying to use your API. The simple act of writing a test can help you see problems with the usability of your API design, which encourages you to improve the design. But tests can also influence API designs in less desirable ways, because tests can make demands on the API that aren't made by any other client. For example, you may find yourself making private methods package access just so you can test them.
I always felt a bit dirty when making changes to an API solely to accomodate tests. I felt that the tests should be testing the API that would exist if there were no tests, because that's the "true" API. That's the API that serves the "real" clients. However, recently I started questioning that attitude. Should I consider tests as first class citizens of the application? Should I see tests as just another client that needs to be served, equal in status to other, non-test clients?
A couple months ago I was writing tests for a Java class called
Merger, which contains a Velocity template name and a context
Map. Instances of this class are returned by the controllers in Artima's new architecture.
Mergers contain a
merge method that renders the named Velocity template with the contained
Map. I was writing tests that verified that the template name and context
Map returned from our controllers were as expected. I first added
get methods that allowed the tests to grab the template name and context
Map. The tests were the only client that needed access to these private fields, so I didn't feel quite right about adding the get methods. But I did it anyway, because I wanted these tests. I soon found myself creating helper methods in the test class for comparing two context
Maps and two template names.
After finding I needed to call the helper methods from a different test class, I started feeling the object-oriented urge to move the helper methods into the
Merger class itself and get rid of the
get methods I had added before. This would move the code that's using
Merger's private data into class
Merger, where the data resides. I struggled with this a while, then finally decided to go ahead and do it. Now there are no
get methods, but there are two
verify methods (formerly the helper methods) in the public API of class
verify methods are called only by tests.
To what extent do you feel automated tests should be allowed change the API being tested? What would you say in a design review of class
|Bill Venners is president of Artima, Inc., publisher of Artima Developer (www.artima.com). He is author of the book, Inside the Java Virtual Machine, a programmer-oriented survey of the Java platform's architecture and internals. His popular columns in JavaWorld magazine covered Java internals, object-oriented design, and Jini. Active in the Jini Community since its inception, Bill led the Jini Community's ServiceUI project, whose ServiceUI API became the de facto standard way to associate user interfaces to Jini services. Bill is also the lead developer and designer of ScalaTest, an open source testing tool for Scala and Java developers, and coauthor with Martin Odersky and Lex Spoon of the book, Programming in Scala.|