[almighty] Database test patterns

Thomas Mäder t.s.maeder at gmail.com
Tue Oct 25 15:39:57 UTC 2016


Hi folks,

in PR https://github.com/almighty/almighty-core/pull/294 I have used the 
pattern to roll back to execute tests in a transaction which is rolled 
back at the end of the test. Thus, the test is guaranteed to not change 
the database. There were couple of objections to this patterns, which 
leads me to seek some convergence on the topic of db tests.

Every test has certain preconditions. For example, when I test creation 
of an object with a given ID, the precondition is that this ID does not 
yet exist in the DB. If the preconditions are not met, the test cannot 
properly run and thus does not yield any information about the code it 
is supposed to test.

To solve this problem, there are two approaches. The first one is to 
program the test without having preconditions. For example, instead of 
creating an object with the ID "42" in the above case, the test could 
try to use a UUID as the ID for the object it creates. Since there will 
be no collision with previous runs, there is no precondition that can be 
violated.

The second one is get the system into a well know state before the test 
runs. One of the patterns to do this is to always start with an empty 
database. Alternatively, the test setup could contain code to establish 
the precondition. In our example, the setup would delete the object with 
the ID "42" (if it exists) in order to make sure that the create call 
can be tested.

One of the problems we have is that we run unit often against a local 
database while developing. Even if the tests are written to work 
repeatably, we don't want the test database to be trashed every time nor 
filled up with useless test data. So ideally, tests should clean up 
after themselves.

The rollback pattern keeps the db from filling up, but can't prevent 
failed preconditions. Another pattern is to setup objects used in the 
test before the test and to remove them after the test. However, this 
doesn't really work either: tear down may fail and leave objects in the 
database. The next run of the test may then fail.

I think the only reliable way to write db tests is this:

setup

     delete all objects the test expects NOT to exist

     delete all objects the test expects to exist (because they may not 
be in the correct state)

     create all objects the test expects to exist.

Test

     use the objects from above

tearDown

     remove all objects created in setup or the test

What are your proposals on how to structure db tests?

/Thomas




More information about the almighty-public mailing list