After a few weeks of real world testing with Arquillian I’ve noticed a few things to consider when building integration tests. These items should grow or evolve, here or in other post, as experience is gained.
To manage provided dependencies. The building of a project most of the time considers dependencies to libraries, toolkits, frameworks, etc., and for each of them you define a scope. You find some to be provided-scoped as your company’s login jar, the jee6-spec.jar library, etc. What’s to consider here is that these libraries are provided by the environment, so they don’t need to be in your deployment file. If you just drop them in your deploy or lib folders when you start the container, without your test file yet, you can make sure the can actually deploy by them selves. Then, if your test-deployment-file fails to deploy it’s less likely because of the provided dependencies.
To separate logs. Test-code logs too. So the least you should do is to drop a configuration file in your test resources to make sure the test log is separated from the production and server logs. A good place to relocate this file is to the target folder, maven speaking, or wherever you place your binaries. If you can make a log file per test class and save them into the test-reports folder, that’s heaven. This way, in the unlikely scenario your test fails, you won’t be searching the cause inside a 5 MB+ file which rolls every hour at best, but in a 1 KB ~ 1 MB test-only log file which is deleted next time you run your tests, build the project or just clean it up.
To isolate persistence. When data is involved you should always have a test-only schema or catalog, or whatever your DBMS calls it, where you can create and drop objects as you need. Once you grant this, you could tune up a little your test persistence.xml file to provide better data isolation. Ideally, a create-drop configuration for every test-case over a schema in the same DBMS where the development schema resides helps keeping a closer production-like isolated environment, but much time will be consumed to drop and create DB objects and purging might be needed. A quick fix is to move the test schema to a local light DBMS, like the JBoss AS embedded HSQLDB, which can be maintained as long as you don’t use DB-specific syntax. Another, is to configure the persistence to only update changes instead of dropping and recreating the schema every time; hibernate for this would be hibernate.hbm2ddl.auto = update. Using both fixes really cuts-off some time.
To package light. Adding a whole package to a testing deployment is not the best choice even when easier. Consider this integration tests as unit-integration tests; you want your component isolated but standing over the environment where it will perform in production. So, next time you are going to test the ClientSuscriber.java class use
addClass(ClientSuscriber.class) instead of
addPackages(ClientSuscriber.class.getPackage()) This will reduce the potential failure points to your test.
To default to off maven profiles When building with maven, it’s a good idea to turn off integration tests for regular building. An integration test besides testing components on the real environment also helps making sure you don’t break co-workers code and usually are developed and run after unit tests. So, setting them up in a non-active-by-default profile helps keeping them out of the way till they are needed because they cost time and running only a specific one reduces its efficiency. You may enforce the running of these tests by a CI system.