What to test your code change against
Posted by Kenneth Selin on October 5th, 2010In this blog entry, I’m gonna discuss how how big part of the rest of the system/application you need to integrate in your test, before checking in your code.
We have all heard how much more expensive it gets when a fault is found at a later stage of the test chain (or even in a production system). It is a fact that software companies of any notable size does use several test stages. What these stages are called and how many they are, varies from company to company. The first test stage however is the test the developer is supposed to perform before checking in the code. This might be called “unit test” or “basic test” for example. Then there is typically an integration test, where it is tested that several modules delivered independently are able to talk to each other. At the next test stage, maybe called “function test”, it could be tested that the system’s functionality works. Another test stage could test non-functional requirements, like stability and performance.
The further down the test chain, the closer to the real production environment we get. Real database management systems are used (I call these “databases” from now on), expensive hardware, and so on.
And again, if a bug is found late in the test chain, it is usually more expensive to fix, since you might want to pass all the test stages again. This could make you feel guilty as a developer, when a bug is found, and maybe lead to pretty strange behaviour to avoid finding the bugs “late”.
There are many examples of companies where the developers are supposed to test in production like environments, with real databases, expensive hardware and so on before checking in the code. It is easy to understand that this kind of testing takes a lot of time, and is typically performed manually.
All these test stages and the company culture revolving around the test stages can be very confusing. What is a developer actually supposed to do before checking in the code?
The developer needs to test the changed code towards it’s interfaces until the developer is confident the change works.
This statement holds a lot in it, so let me elaborate.
First we consider that the code must be tested towards its interfaces (for example other classes, protocols, etc). Here, it helps a lot if the interfaces are clearly understood. If you know (by documentation or experience) what the interfaces used by the code return, you can much faster get confident that the change works, by somehow getting the interface to return the values you need for your test. Now, you should preferrably mock the interface in an automated test case, which will let you get confident of your code change very quickly.
Understand that as long as you get the interface to return the values you like, it does not matter where the values originate from. A String is a String, regardless if you mock it into your stubs or if you dig it up from a database in some layer far below yours.
That is, it does not add value to the test if you dig up the string from the database, it just takes more time and money.
A recurring statement from people prefering to test (manually) using real databases is that “they want to be sure that it works”. This is in a sense a good ambition. They want to do a good job for their employer, and not get blamed later. However, time and money are critical resources for the employer, and time and money must be spent right. If you can test quickly and cheaply, getting you confident that the change works, you should do it. At odd times, a bug you could have found using (manual) database-based test might slip to later test stages, but this means 1) you did not understand the interfaces and/or 2) you were sloppy while testing.
Testing faster and cheaper frees up time and money for the employer, making the developers more productive.
Sometimes however, you might not be able to get confident of the test using just stubs. This is when the interface is not well understood, since it is not well documented or for some reason can not be trusted. Also, if you are new to the code base, it is harder (and should be harder) to get confident. In this case it might be fine to test using real databases (if not anything else, it will teach you more about how the real system functions), but it could be smarter try understanding the interface instead and then test the code change using stubs.
To sum it up, it is a waste of time and resources to integrate a lot of “real” software (like databases) into your test, and you should not do it routinely.
(The topic of manual versus automated testing is maybe for some other time
)
Recent Comments