3

Background:

I have a Flex web app that communicates with a Java back-end via BlazeDS. The Flex client is composed of a flex-client module, which holds the views and presentation models and a separate flex-service module which holds the models (value objects) and service objects.

I am in the process of writing asynchronous integration tests for the flex-service module's RemoteObjects using FlexUnit4. In some of the tests, I modify the test data and query it back to see if everything works (a technique shown here: http://saturnboy.com/2010/02/async-testing-with-flexunit4)

Question:

How do I go about resetting the database to a known state before each FlexUnit4 test method (or test method chain)? In my Java server integration tests, I did this via a combination of DBUnit and Spring Test's transactions -- which rollback after each test method. But these Flexunit integration span multiple requests and thus multiple transactions.

Short of implementing an integration testing service API on the backend, how can this be accomplished. Surely others have run into this as well? Similar questions have been asked before ( Rollback database after integration (Selenium) tests ), but with no satisfactory answers.

Community
  • 1
  • 1
Dave
  • 21,524
  • 28
  • 141
  • 221
  • How much of an integration test are you looking for? Fully end to end, or simply that the ROs connect to the services correctly? – Gregor Kiddie Oct 28 '10 at 10:06
  • End to End (but no GUI). In the case of this flex-service module, I am looking to verify that all of the service methods on all of the Flex service classes (they extend RemoteObject) function correctly on all supported database, OS, and app-server combinations. This means that I need to verify all CRUD methods from Flex to a running BlazeDS/Java server and back to Flex. I expect these integration tests to help verify that there are no client/server API mismatches and that all data-types are being converted properly. I need to set up the data for each test case and tear it down afterward. – Dave Oct 28 '10 at 12:49

3 Answers3

5

There are several options:

  1. If you use sequences for primary keys: After the database has been loaded with the test data, delete the sequence generator and replace it with one that starts with -1 and counts down. After the test, you can delete objects with a primary key < 0. Breaks for tests which modify existing data.

    A similar approach is to create a special user or, if you have created timestamp columns, then the initial data must be before some date in the past. That needs additional indexes, though.

  2. Use a database on the server which can be quickly wiped (H2, for example). Add a service API which you can call from the client to reset the DB.

  3. Add undo to your web app. That's quite an effort but a very cool feature.

  4. Use a database which allows to move back in time with a single command, like Lotus Notes.

  5. Don't use a database at all. Instead write a proxy server which will respond to the correct input with the correct output. Add some code to your real server to write the data exchanged into a file and create your tests from that.

    Or write test cases which run against the real server and which create these files. That will allow you to track which files change when you modify code on the server or client.

    On the server, write tests which make sure that it will do the correct DB modifications.

  6. Similar to "no database at all", hide all code which accesses the DB in a DB layer and use interfaces to access it. This allows you to write a mock-up layer which behaves like the real database but which saves the data in memory. Sounds simple but is usually a whole lot of work.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • 1
    Excellent suggestions. #3 is quite intriguing -- especially since we have considered implementing the command pattern..which supports this. Also I think the point covered in #2 about providing a service API is mandatory for #4, #5, and #6 as well. Without this, I don't see how the FlexUnit4 test runner "tells" the server when to reset the datastore. – Dave Nov 01 '10 at 20:46
  • @HDave: I agree. To find the option which suits you best, select the one that will cause the least work. Don't hesitate to spend a week to try 2-3 of the approaches above to see which works best for you. It will save so much time later! – Aaron Digulla Nov 02 '10 at 17:06
1

Depending on the size of your test database, you could automate clean backups/restores that gives you the exact environment you had on each test run.

I've that approach in on of my current projects (different platform) and we also test data schema change scripts with the same approach.

eglasius
  • 35,831
  • 5
  • 65
  • 110
  • Did you do this for each test method or each test case? We are looking for something at the method level. Also, how would this be invoked by the FlexUnit test running. FlexUnit provides a Junit-like before/after methods, but what gets called from within those? – Dave Nov 01 '10 at 20:41
  • @HDave I have some tests that do it for each test method, and others for the whole class. As I said I'm using a different platform/language, and the database is very light weight, so it might not be comparable. – eglasius Nov 01 '10 at 20:46
0

I'm dehydrated (my fav excuse for short-comings). So sorry if this answer is too close to the "integration testing service API on the backend" response that you didn't want.

The team that set-up flexUnit 'ages ago' made choices and created solutions based on our architecture, some of which would only apply to our infrastructure. Things to consider: 1) all of our backend methods return the same remotely-mapped class. 2) most all of our methods have an abstracted method that telling the method to (or not to) run a "begin transaction" at the beginning of the method and a "commit transaction" at the end (not sure of your db chunk).

The latter isn't probably the most object oriented solution, but here's what an asynchronous unit-test call does: Every unit test calls the same method-wrapper, and we pass-in the method-name/package-locale, plus the [...]args. A beginTransaction is done. The method is called, passing a false to the method for FE unit tests (to ignore the beginTransaction and commitTransaction lines), everything is run and the main 'response' class is generated and returned to the unit test method. A db-rollback is run and the response is returned to the unit test.

All of our unit tests are based on rolling-back transactions. I couldn't tell you of the issues that they had when setting up that jive, but that's my general understanding of how schtuff works.

Hope that helps. Understandable if it doesn't. Best of luck, --jeremy

jeremy.mooer
  • 645
  • 3
  • 9
  • I use Spring Transactions and through that could probably find a way to automatically rollback all transactions. However these tests involve persisting new data and then (in a seperate request) querying to find that same data. Therefore transaction rollback won't work...unless I manage transactions on the client side, which I do not want to do. – Dave Oct 30 '10 at 21:29
  • Right... I guess you only had to say the "multiple request" thing four times! :-). If it were me, I'd start experimenting with database transactions to see how well our Oracle libraries handle our database transaction class being passed back and forth to the backend. We try to limit remotely aliased/mapped classes, but doing so with a db transaction might be doable, though you might have to do something squirrelley with keeping db connections open between 'spring transactions' Either way, you have a fun task on your hands! Not sure I was ever of help, but best of luck! Keep us updated! – jeremy.mooer Nov 01 '10 at 18:41
  • and thanks for listening to me blab... the 500+ character limit is always a kick in the head for me! – jeremy.mooer Nov 01 '10 at 18:42