| Author |
database related tests in CI
|
Gian Franco
blacksmith
Ranch Hand
Joined: Dec 16, 2003
Posts: 975
|
|
Dear authors, Recently I've been busy setting up a CI environment with CruiseControl, Ant and CVS, for our J2EE projects. I had my manual build script, written in Ant, on the shelf and working for quite some time. With some refactoring now it's used by CC and works, a bit slow, but fine. One of the Ant targets involves performing unit tests. One issue that will probably take me some time to solve is how to perform tests on code that touches the database. My problem is that I don't really want my unit tests to touch the database, but at the moment, it does: it is legacy code that needs some refactoring. Do you have any suggestions as how to go about with these issues? Kind regards, Gian [ August 28, 2007: Message edited by: Ilja Preuss ]
|
"Eppur si muove!"
|
 |
Paul Duvall
author
Greenhorn
Joined: Jul 17, 2007
Posts: 29
|
|
One of the Ant targets involves performing unit tests. One issue that will probably take me some time to solve is how to perform tests on code that touches the database. My problem is that I don't really want my unit tests to touch the database, but at the moment, it does: it is legacy code that needs some refactoring.
In chapter 6, "Continuous Testing", we refer to different categories of tests: unit, component, system and functional tests. For instance, we refer to a test that uses a database as a "component" test. The reason this is important is that *if* you can segment slower-running tests (such as the tests against your database) from faster-running tests, such as those that have no heavy-weight dependencies such as a database or file system, you can run these tests as part of a secondary integration build (after a successful commit build) enabling more rapid feedback. If you are using JUnit 4, you can use annotations to segment these tests. If you're using JUnit 3, you can use a directory or file-naming scheme to run these tests. More to your point, though, if you don't want tests to touch your database, you could stub out your DAO so that it doesn't actually connect to a database (you can insert some test data that uses this stub). Since Andy wrote this chapter, let's see if he has any other ideas.
|
Co-author of <a href="http://www.amazon.com/gp/product/0321336380/" target="_blank" rel="nofollow">Continuous Integration: Improving Software Quality and Reducing Risk </a> <br />(Addison-Wesley Martin Fowler Signature Series, 2007). Companion website for the book is <a href="http://www.integratebutton.com/" target="_blank" rel="nofollow">IntegrateButton.com</a>
|
 |
Gian Franco
blacksmith
Ranch Hand
Joined: Dec 16, 2003
Posts: 975
|
|
The build script I wrote relies on every project having the same package containting the AllTests.java and SmokeTests.java test suites. I use the same script both on the CI machine and locally, and for all projects, this is possible because the script is in it's own project that physically has the same relative position both in the local as in the remote CI machine directory structure. Now those tests that touch the database I never include them for CI to run, so they practically maintain the status of exploratory tests or at the most local unit tests. I'll wait for Andy's tips as well I didn't know 'two phased' integration builds where possible, do you know if CC supports this? Gian
|
 |
Paul Duvall
author
Greenhorn
Joined: Jul 17, 2007
Posts: 29
|
|
I didn't know 'two phased' integration builds where possible, do you know if CC supports this?
I will write more later, but for now see http://www.testearly.com/2007/04/25/staged-builds-with-cruisecontrol/ as it describes how to setup a staged build/build pipeline by monitoring the CC commit log.
|
 |
Andrew Glover
author
Greenhorn
Joined: Dec 19, 2002
Posts: 16
|
|
|
I take it, Gian, that you don't want to run tests that rely on a database as they are slow? If you can segregate these tests (one easy way to figure out which tests require a database is to run all your tests without a database running-- those that fail are most likely dependent on it) then create a new Ant target that only runs these tests. I'd then schedule a build to run at some interval that includes executing this particular target (say named component-test).
|
Certified City Slicker
|
 |
Francesco Bianchi
Ranch Hand
Joined: Jun 22, 2007
Posts: 62
|
|
Originally posted by Gian Franco: Now those tests that touch the database I never include them for CI to run, so they practically maintain the status of exploratory tests or at the most local unit tests.
Hope I'm not sayng something idiot..I'm completely new to the topic.. Why don't you simply create a common mechanism (an ancestor class) for all of your unit classes writing on DB which begin a DB transaction, do what they have to do and, in the end, do a simple rollback? Or, to run more reality-close tests, simply change your DB connection string so that that your units test work with a "test DB"? What I mean is a snapshot of the production DB structure filled with some predefined sample data which are restored by a SQL script right periodically?
|
SCJP 5 & 6, SCWCD 5, SCBCD 5
|
 |
Gian Franco
blacksmith
Ranch Hand
Joined: Dec 16, 2003
Posts: 975
|
|
Andrew, Speed is one of my problems, the database is an expensive resource, but also controlling the external data. I could start by stubbing out the DAO for my local tests as Paul proposed, and as you say run tests on the live database as well as part of a CC schedule. [Francesco] I wouldn't like to do rollbacks, but the idea of a test database, like Ruby on Rails, with fixtures loaded after a cleanup would indeed be the next step. Gian
|
 |
 |
|
|
subject: database related tests in CI
|
|
|