Deciding how to mark in-container vs client
dan.j.allen May 14, 2010 1:24 AMWe've got our terminology mixed up with regard to where the test is executed. We've tried to sort it out in ARQ-126, but a recent discussion with ALR revealed that perhaps we need to look at the problem from further out.
Arquillian's motto is to test in-container. There are actually two interpretations, and hence two possible run modes in Arquillian.
In the first run mode, the code being tested is packaged into an archive (i.e., @Deployment), deployed to the server, and the test case exercises the deployed code as a client (e.g., HTTP, remote EJB invocation). In this case, the code being tested is running in-container, but not the test case.
In the other run mode, the test case and the test framework is packaged into an archive along with the code being tested. The combined archive is deployed to the server and the test case executes inside the context of the container through remote a remote protocol (e.g., HTTP). The test case is just another component in the system and can inject the components under test directly. In this case, the code being tested and the test case are both running in-container.
(Not that I've avoided the terms local and remote to describe these modes. Those terms depend too much on context and therefore cause confusion when used to describe what is going on).
The tricky part about the second case is that it is subject to the Heisenberg uncertainty principle. In order for the test case to run in-container, the deployment archive has to be modified to include the test case, the test framework and the remote protocol endpoint. This modifies the deployment and effects the nature of the code under test (it can affect global JNDI names, for instance).
Arquillian 1.0.0.Alpha1 assumed that the @Deployment method returned a EAR module and would package it instead of an EAR named test.ear and deploy it to the server. The trouble is that we were making assumptions about what the developer wanted to deploy.
In trunk, Arquillian now honors the test developer's archive choice (e.g., EnterpriseArchive) and tries to weave in the test artifacts intelligently. But the fact remains, the user's archive is being modified. And we should take care to communicate this through the metadata.
In ARQ-126, we were discussing the @Run annotation and it's possible values. The @Run annotation and packaging are tightly coupled. Running the test as a client is the same as not packaging the test in the archive. Running the test in-container requires packaging the test in the archive. (Except for local bean containers, in which case packaging is not necessary and everything runs locally).
With all that said, we would like to offer some proposals for how to set the run mode, with some focusing on the packaging aspect. We also want to clearly document what happens to the deployment in the in-container mode so that the developer is not confused when what is being deployed has been modified from the original @Deployment.
Option 1: In terms of run-mode
// deploys test.jar @Deployment @Run(AS_CLIENT) public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); } // deploys test.ear containing test.jar as a module @Deployment @Run(IN_CONTAINER) public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); }
Option 2: In terms of packaging
// deploys test.jar @Deployment public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); } // deploys test.ear containing test.jar as a module @PackageTest @Deployment public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); } // deploys mytest.ear containing test.jar @PackageTest(archiveName = "mytest.ear", type = EnterpriseArchive.class) @Deployment public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); }
Option 3: In terms of package relationship
// deploys test.jar @Deployment public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); } // deploys test.ear containing test.jar as a module @BundleTest @Deployment public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); } // deploys mytest.ear containing test.jar as a module @BundleTest(archiveName = "mytest.ear", type = EnterpriseArchive.class) @Deployment public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); }
Option 4: Use @Package as customization w/ @Run
// deploys test.jar @Deployment @Run(AS_CLIENT) public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); } // deploys mytest.ear containing test.jar as a module @Deployment @Run(IN_CONTAINER) @TestArchive(archiveName = "mytest.ear", type = EnterpriseArchive.class) public static JavaArchive createTestArchive() { return ShrinkWrap.create("test.jar", JavaArchive.class); }
I'd like to just get some thoughts from the team members and community about how best to communicate the pure deployment (test case as client) vs packaged deployment (test case in-container).