Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

database related tests in CI

 
Gian Franco
blacksmith
Ranch Hand
Posts: 979
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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 ]
 
Paul Duvall
author
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Gian Franco
blacksmith
Ranch Hand
Posts: 979
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

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
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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).
 
Francesco Bianchi
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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?
 
Gian Franco
blacksmith
Ranch Hand
Posts: 979
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic