3

We are working on a project where database requirement is not clear. So we are building a database agnostic application.

See my previous question here: Database Agnostic Application

Now I want to test my Spring application DAO with multiple database. I've written number of test cases using TestNG and DBUnit.

When I run these test in a CI environment, I want them to test the application against all the configured databases. I've installed the databases on the 'test server'.

e.g. I want something like this:

for ( each database configured ) {
 run each dao test
}

Not sure what is the best way of doing this? And help is welcome.

Thanks, Adi

Community
  • 1
  • 1
adi
  • 1,711
  • 3
  • 29
  • 50

3 Answers3

2

If you're building a database agnostic application and not using any of the inherent features of a specific database vendor, then the scope of your test cases should be to test the setup, manipulation, and accessing of the data through the DAO objects and less with the testing of the actual database backend. Hibernate 3.5 has dialects available for both Oracle 11g and DB2, so if you were writing test cases that tested the integration of the database agnostic application with a specific database vendor, then really what you are doing is testing that the hibernate dialects do as they say they do (which I'm sure has been covered by test cases in the hibernate project).

In other words, in your case I would think that the testing should focus more on the DAO retrieving the data that you think that it will retrieve after you've set that data up, and in-memory databases are fine for that.

Now all that said, both DB2 and Oracle have very good documentation related to setup. Indeed, both of them have "wizards" to do that. If you still think that it's prudent to test adding data to the database and retrieving it from the physical, non-in-memory database, then I would recommend setting up a "test database" environment and pointing your datasource to that during your continuous integration tests. If you're using Hudson or Jenkins for CI, you can set it up to run a script after the build completes that will truncate the database tables so that the next round of tests work from a blank slate.

EDIT:

I just saw the updates that you posted to your question, so let me address them. Since you already have the databases setup and configured then what you really want to do is dynamically select what the database should be. One way to do this would be to setup your datasource using System properties that can be inherited from a properties file, and running your tests in a "DB2-test" environment and an "Oracle-test" environment. Using this method, you'll have to setup the datasource programmatically and have it read system environment variables to determine which database it connects to. This would essentially require you to change your CI script to run the DB2-test environment first, then the Oracle-test environment following that -- your test suites will run twice.

Hope this helps!

Daniel Woods
  • 1,029
  • 7
  • 10
  • I am doing all that. My aim is only to test the DAO retrieving and persisting the data. I've already got test cases working against Oracle. I am using Unitils to clear all the data before the test runs, loads test data each time. Now what I am searching for is, how to run all the test in a loop so that the DAO's are tested against all the configured databases? – adi Feb 21 '12 at 13:22
  • See the updates to my post... The idea being that you run your test suites in succession against different datasources. – Daniel Woods Feb 21 '12 at 13:24
  • that will become dependent on the CI server then. Can it not be done just using Spring? – adi Feb 21 '12 at 13:26
  • 1
    Well, you could change your test suite to setup the two datasources and store them in a global list that you loop through in your test case, resetting the sessionFactory with each iteration... Is that what you mean? – Daniel Woods Feb 21 '12 at 13:30
  • Something like that was my thought when answering the other question. – Hauke Ingmar Schmidt Feb 21 '12 at 13:51
  • @adi is the sessionFactory in your DAO autowired? – Daniel Woods Feb 21 '12 at 13:53
2
  1. If you want to be database independent, you have to test against every single database system you want to support. There are very fine differences which leak through Hibernate.

  2. What I did in the past was to make the test retrieve their database configuration through some System Property. Typically by using hibernate_.property instead of the default hibernate.property. Then setup CI Jobs, which set the property to different values and provide one hibernate_xxx.property for every database to test against. I did this using JUnit Rules, to have the logic in one place. Don't know the apropriate tool for TestNG

  3. I'm not to fond of the loop construct you are hinting at, because it might make it difficult to run a test suit against a single specific database.

  4. I'm also not to fond of dbunit, because it seems to make maintaining testdata rather painful. I prefer in most cases a handcrafted DSL. Have a look at some articles I wrote about it:

http://blog.schauderhaft.de/2011/03/13/testing-databases-with-junit-and-hibernate-part-1-one-to-rule-them/

http://blog.schauderhaft.de/2011/03/20/testing-databases-with-junit-and-hibernate-part-2-the-mother-of-all-things/

http://blog.schauderhaft.de/2011/03/27/testing-databases-with-junit-and-hibernate-part-3-cleaning-up-and-further-ideas/

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
1

Unit 4.9 has a new Feature: TestRule

You should be able to write a rule, that repeat a test for different databases.

There is this stack overflow question: How to Re-run failed JUnit tests immediately? It is a slightly different question, but the solution should be the same technique.

Community
  • 1
  • 1
Ralph
  • 118,862
  • 56
  • 287
  • 383