Build Status

Arquillian is an innovative and highly extensible testing platform for the JVM that enables developers to easily create automated integration, functional and acceptance tests for Java middleware.

1. Arquillian makes integration testing a breeze!

Picking up where unit tests leave off, Arquillian handles all the plumbing of container management, deployment and framework initialization so you can focus on the task at hand, writing your tests. Real tests. In short…

Arquillian brings the test to the runtime so you don’t have to manage the runtime from the test (or the build). Arquillian eliminates this burden by covering all aspects of test execution, which entails:

  • Managing the lifecycle of the container (or containers)

  • Bundling the test case, dependent classes and resources into a ShrinkWrap archive (or archives)

  • Deploying the archive (or archives) to the container (or containers)

  • Enriching the test case by providing dependency injection and other declarative services

  • Executing the tests inside (or against) the container

  • Capturing the results and returning them to the test runner for reporting

To avoid introducing unnecessary complexity into the developer’s build environment, Arquillian integrates seamlessly with familiar testing frameworks (e.g., JUnit 4, TestNG 5), allowing tests to be launched using existing IDE, Ant and Maven test plugins — without any add-ons.

2. Guide

2.1. Introduction

We believe that integration and functional testing should be no more complex or daunting than unit testing. We created Arquillian to make that vision a reality.

Arquillian is a revolutionary testing platform for Java and the JVM that enables developers to easily write and execute integration and functional tests for Java middleware, ranging from Java EE and beyond.

Arquillian picks up where unit tests leave off, focusing on the integration of application code inside a real runtime environment. Much the same way Java EE 5 simplified the server programming model by providing declarative services for POJOs, Arquillian equips tests with container lifecycle management and test case enrichment. Using Arquillian, you can focus on the test, not the plumbing.

In short, Arquillian aims to make integration and functional testing a breeze.

2.1.1. Core Principles

The Arquillian project adheres to three core principles:

  1. Tests should be portable to any supported container
    By keeping container-specific APIs out of the tests, developers can verify application portability by running tests against a variety of containers. It also means that lightweight containers can be used as a substitute for full containers during development.

  2. Tests should be executable from both the IDE and the build tool
    By leveraging the IDE, the developer can skip the build for a faster turnaround and has a familiar environment for debugging. These benefits shouldn’t sacrifice the ability to run the tests in continuous integration using a build tool.

  3. The platform should extend or integrate existing test frameworks
    An extensible architecture encourages reuse of existing software and fosters a unified Java testing ecosystem.

Arquillian brings your test to the runtime so you don’t have to manage the runtime from the test. Arquillian packs the necessary orchestration logic neatly into the platform an its extensions. As a result, executing an Arquillian test is as simple as selecting "Run As > Test" in the IDE or executing the "test" goal from the build tool.

2.1.2. How It Works

Using Arquillian, you write a basic test case and annotate it with declarative behavior that says, "`@RunWith` Arquillian". This declaration tells Arquillian to take over execution of the test when it’s launched.

That’s when the real magic happens.

Launching an Arquillian test is as simple as right-clicking the test class in the IDE and selecting Run As > Test (e.g., JUnit, TestNG, Spock, etc). Based on the classpath configuration, Arquillian starts or binds to the target container (JBoss AS, GlassFish, OpenEJB, etc) and deploys the test archive defined in the @Deployment method. The archive includes the test case along with the specified classes, resources and libraries. Your test then executes inside the container and enjoys all the same services as an application component. That means you get dependency and resource injection into the test, you can access EJBs, you can load a persistence unit, you can get a handle to a database connection, etc. Arquillian then captures the test results and transports them back to the test runner for reporting.

Arquillian also has a client run mode, which only deploys the test archive, not the test case.

Aside from a few extra declarations (i.e., @RunWith and @Deployment), an Arquillian test looks like any other unit test and launched like any other unit test.

2.1.3. Integration Testing In Java EE

Integration testing is very important in Java EE. The reason is two-fold:

  • Business components often interact with resources or sub-system provided by the container

  • Many declarative services get applied to the business component at runtime

The first reason is inherent in enterprise applications. For the application to perform any sort of meaningful work, it has to pull the strings on other components, resources (e.g., a database) or systems (e.g., a web service). Having to write any sort of test that requires an enterprise resource (database connection, entity manager, transaction, injection, etc) is a non-starter because the developer has no idea what to even use. Clearly there is a need for a simple solution, and Arquillian fills that void.

Some might argue that, as of Java EE 5, the business logic performed by most Java EE components can now be tested outside of the container because they are POJOs. But let’s not forget that in order to isolate the business logic in Java EE components from infrastructure services (transactions, security, etc), many of those services were pushed into declarative programming constructs. At some point you want to make sure that the infrastructure services are applied correctly and that the business logic functions properly within that context, justifying the second reason that integration testing is important in Java EE.

Testing The Real Component

…​or, what you test is what you run.

The reality is that you aren’t really testing your component until you test it in situ. It’s all to easy to create a test that puts on a good show but doesn’t provide any real guarantee that the code under test functions properly in a production environment. The show typically involves mock components and/or bootstrapped environments that cater to the test. Such "unit tests" can’t verify that the declarative services kick in as they should. While unit tests certainly have value in quickly testing algorithms and business calculations within methods, there still need to be tests that exercise the component as a complete service.

Rather than instantiating component classes in the test using Java’s new operator, which is customary in a unit test, Arquillian allows you to inject the container-managed instance of the component directly into your test class (or you can look it up in JNDI) so that you are testing the actual component, just as it runs inside the application.

Finding A Happy Medium

Do you really need to run the test in a real container when a Java SE CDI environment would do?

It’s true, some tests can work without a full container. For instance, you can run certain tests in a Java SE CDI environment with Arquillian. Let’s call these "standalone" tests, whereas tests which do require a full container are called "integration" tests. Every standalone test can also be run as an integration test, but not the other way around. While the standalone tests don’t need a full container, it’s also important to run them as integration tests as a final check just to make sure that there is nothing they conflict with (or have side effects) when run in a real container.

It might be a good strategy to make as many tests work in standalone mode as possible to ensure a quick test run, but ultimately you should consider running all of your tests in the target container. As a result, you’ll likely enjoy a more robust code base.

We’ve established that integration testing is important, but how can integration testing being accomplished without involving every class in the application? That’s the benefit that ShrinkWrap brings to Arquillian.

Controlling The Test Classpath

One huge advantage ShrinkWrap brings to Arquillian is classpath control. The classpath of a test run has traditionally been a kitchen sink of all production classes and resources with the test classes and resources layered on top. This can make the test run indeterministic, or it can just be hard to isolate test resources from the main resources.

Arquillian uses ShrinkWrap to create "micro deployments" for each test, giving you fine-grained control over what you are testing and what resources are available at the time the test is executed. An archive can include classes, resources and libraries. This not only frees you from the classpath hell that typically haunts test runners (Eclipse, Maven), it also gives you the option to focus on the interaction between an subset of production classes, or to easily swap in alternative classes. Within that grouping you get the self-assembly of services provided by Java EE---the very integration which is being tested.

Let’s move on and consider some typical usage scenarios for Arquillian.

2.2. Getting Started

We promised that integration and functional testing with Arquillian is no more complex than writing a unit test. Now it’s time to prove it to you. We’ve prepared a series of guides designed exclusively to teach you how to use Arquillian. You’ll have the tests running from both Maven and Eclipse by the end of the first guide.

Head over to the Getting Started Guide and start writing real tests!

2.3. Deployment Archives

Each Arquillian test is associated with at least one deployment. The deployment is configured using a static method annotated with @Deployment that returns a ShrinkWrap archive. Here’s an example:

@Deployment
public static JavaArchive createDeployment() {
    return ShrinkWrap.create(JavaArchive.class)
        .addClass(Greeter.class)
        .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}

Why is a deployment necessary?

If we want to be able to test inside the container, we need some way to get the code into the container. A container typically accepts some form of deployment. In most Java-based containers, these deployments are some sort of Java archive (jar).

ShrinkWrap provides a way to define a deployment archive (e.g., jar, war, ear) in Java using a fluent API. You use this API to create an deployment that’s associated with the test case, which we call a "micro deployment". Arquillian can then use this object to stream the contents to the server in the most efficient way available.

The deployment archive is more than just a means to an end (getting code inside the container). There are several critical benefits to defining a deployment:

  1. It allows you to isolate the classpath of the test – only those classes and resources inside the deployment are visible to the test.

  2. You can emulate or replicate a deployment scenario, which often triggers behavior (e.g., framework activation) that you cannot otherwise test.

  3. We can skip the build. Since the archive is assembled in Java, we’re able to leverage the incremental compilation provided by IDEs.

In summary, the strategy of using ShrinkWrap-based deployments gives you tremendous control over the code you’re testing and quicker turnaround.

Arquillian provides the SPI org.jboss.arquillian.spi.client.deployment.DeploymentScenarioGenerator to allow an alternate means of defining a deployment, including foregoing the use of a deployment altogether.

2.4. Deployment Archives using Java SPI

In Deployment Archives you’ve read how to create an archive to deploy into container using @Deployment annotation. But you can implement your own method to generate the archive to be deployed using a Java SPI org.jboss.arquillian.container.test.spi.client.deployment.AutomaticDeployment.

The service must conform next signature:

/**
 * Method called for generating the deployment configuration.
 * @param testClass of current running test.
 * @return Model object that contains all the information related to deployment configuration.
 */
DeploymentConfiguration generateDeploymentScenario(TestClass testClass);
To build DeploymentConfiguration type you can use org.jboss.arquillian.container.test.api.DeploymentConfiguration.DeploymentContentBuilder class.
Remember to register the SPI by creating META-INF/services/org.jboss.arquillian.container.test.spi.client.deployment.AutomaticDeployment file containing the fully qualified name of your implementation.

Moreover, you can use @BeforeDeployment method annotation which allows you to modify the archive before it is deployed. The method must be public static and receive as a parameter an org.jboss.shrinkwrap.api.Archive which is the archive created by AutomaticDeployment implementation and return a modified org.jboss.shrinkwrap.api.Archive.

@BeforeDeployment
public static Archive addDeploymentContent(Archive archive) {
    // Modify Archive
    return archive;
}

2.5. Containers

Arquillian’s forte is not only its ease of use, but also its extensibility. Good integration testing is not just about testing in any environment, but rather testing in the environment of your application targets. It’s easy to give ourselves false assurance by validating components in a specialized testing container, or by using mocks, only to realize that small variations and assumptions cause the components to fail when the application is deployed to production. To make tests count, you want to execute them in the target environment, or container.

So what is the container that Arquillian uses? Is it some proprietary testing container that emulates the behavior of the technology (Java EE)?

Nope! It’s pluggable. It can be your target runtime, such as JBoss AS, GlassFish or Tomcat. Or it can even been an embedded container such as OpenEJB, GlassFish Embedded or Weld SE. You can even use one container for development and another for continuous integration.

This portability is made possible by a RPC-style (or local, if applicable) communication between the test runner and the container, a real container. You can run the same test case against various containers and you don’t get locked into a proprietary test environment.

Arquillian recognizes three container interaction styles:

  • A remote container resides in a separate JVM from the test runner. Arquillian binds to the container to deploy the test archive and invokes tests via a remote protocol (e.g., Servlet, JMX).

  • A managed container is similar to a remote container, except its lifecycle (startup/shutdown) is also managed by Arquillian.

  • An embedded container resides in the same JVM and is mostly likely managed by Arquillian. Tests are executed via a local protocol for containers without a web component and via a remote protocol for containers with a web component. No need to fiddle with those Maven plugins!

A container is further classified by its capabilities:

  • Java EE application server (e.g., JBoss AS, GlassFish, WebLogic)

  • Servlet container (e.g., Tomcat, Jetty)

  • standalone bean container (e.g., OpenEJB, Weld SE)

  • OSGi container

Arquillian can control a variety of containers out of the box. If the container you are using isn’t supported, Arquillian provides an SPI that allows you to introduce any additional container to the default collection.

2.5.1. Container Selection

How can a single Arquillian test be executed in different containers? How does Arquillian decide which container to target? And how are both remote and local invocations supported?

The answers to these questions touch upon the extensibility of Arquillian.

Container selection occurs at runtime. Arquillian selects the target container according to which container adapter is available on the runtime classpath at the time the test is launched. Therefore, you must include the container adapter as a test-scoped dependency that corresponds to the container you want to target.

Arquillian delegates to an SPI (Service Provider Interface) to handle starting and stopping the server and deploying and undeploying archives. In this case, the SPI is the interface org.jboss.arquillian.spi.client.DeployableContainer. If you recall from the getting started guide, we added an Arquillian container adapter according to the target container we wanted to use. That library contains an implementation of this interface, thus controlling how Arquillian handles deployment.

If you want to add support for another container in Arquillian, you need to provide an implementation of the DeployableContainer interface.

To switch to another container, you just change which container adapter is on the classpath before running the test.

You can only have one container adapter on the classpath at a time. The execution of the test will be aborted if more than one adapter is detected.

One way to swap the libraries on the classpath is to manually edit the dependencies defined in the pom.xml each time. But that’s just tedious. The recommended approach is to use Maven profiles.

Maven profiles allow you to partition your dependencies into groups, one group for each container adapter and its related artifacts. When running the tests, you activate one of those groups, which in turn selects a target container. The profile is activated either using either a commandline flag (-P) or a preference in the IDE.

The Getting Started Guide explains how to setup and use Maven profiles for this purpose in more detail.

So far we’ve covered how a container adapter is selected. It’s also possible to configure the container adapter, which we’ll look at next.

2.5.2. Container Configuration

We’ve covered how a container gets selected, but how does Arquillian know how to locate or communicate with the container? That’s where configuration comes in.

You can come a long way with default values, but at some point you may need to customize some of the container settings to fit your environment. Let’s see how this can be done with Arquillian.

Arquillian will look for configuration settings in a file named arquillian.xml in the root of your classpath. If it exists it will be auto loaded, else default values will be used. This file is not a requirement.

Let’s imagine that we’re working for the company example.com and in our environment we have two servers; test.example.com and hudson.example.com. test.example.com is the JBoss instance we use for our integration tests and hudson.example.com is our continuous integration server that we want to run our integration suite from. By default, Arquillian will use localhost, so we need to tell it to use test.example.com to run the tests. The JBoss AS container by default use the Servlet protocol, so we have to override the default configuration.

<?xml version="1.0"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://jboss.org/schema/arquillian"
    xsi:schemaLocation="http://jboss.org/schema/arquillian http://www.jboss.org/schema/arquillian/arquillian_1_0.xsd">

    <container qualifier="jbossas" default="true">
        <configuration>
            <property name="providerUrl">jnp://test.example.com:1099</property>
        </configuration>
        <protocol type="Servlet 3.0">
            <property name="host">test.example.com</property>
            <property name="port">8181</property>
        </protocol>
    </container>

</arquillian>

That should do it! Here we use the JBoss AS 6.0 Remote container which default use the Servlet 3.0 protocol implementation. We override the default Servlet configuration to say that the http requests for this container can be executed over test.example.com:8181, but we also need to configure the container so it knows where to deploy our archives. We could for example have configured the Servlet protocol to communicate with a Apache server in front of the JBoss AS Server if we wanted to. Each container has different configuration options.

For a complete overview of all the containers and their configuration options, see the container adapters appendix.

2.5.3. Supported Containers

Please see the container adapters appendix for a list of supported containers, including details for how to use and configure them.

2.5.4. Container Config Runtime Selection

During execution of your Arquillian test-suite, you may have configured one or more containers with which you need to execute the test suite. This is usually configured with maven profiles, but in the case where individual container options need to be specified at runtime to the target container. This is where you will need to specify configurations in your arquillian.xml file, and also activate those configurations using Java system properties.

Example arquillian.xml with two container configurations:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://jboss.org/schema/arquillian"
   xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

   <container qualifier="jbossas_managed" default="true">
      <protocol type="Servlet 3.0">
         <property name="executionType">MANAGED</property>
      </protocol>
      <configuration>
         <property name="jbossHome">${project.baseDir}/target/jboss-as-7.1.1.Final/</property>
         <property name="allowConnectingToRunningServer">true</property>
      </configuration>
   </container>
   
   <container qualifier="jetty">
      <configuration>
          <more configuration>...</more configuration>
      </configuration>
   </container>
</arquillian>
Activating a configuration via the command line

The -Darquillian.launch system property is what controls arquillian.xml configuration selection. If you are running tests from Eclipse or directly from the command like, you should add the -D system property to your launch configuration or command.

Activating a configuration via Maven

These configurations may be activated in the maven profile using the Surefire plugin configuration in your container’s maven profile to set the 'arquillian.launch' system property for test execution, as follows:

<profile>
         <id>JBOSS_AS_MANAGED_7.X</id>
         <build>
            <plugins>
               <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-surefire-plugin</artifactId>
                  <configuration>
                     <systemPropertyVariables>
                        <arquillian.launch>jbossas_managed</arquillian.launch>
                     </systemPropertyVariables>
                  </configuration>
               </plugin>
  ...

2.6. Test Enrichers

When you use a unit testing framework like JUnit or TestNG, your test case lives in a world on its own. That makes integration testing pretty difficult because it means the environment in which the business logic executes must be self-contained within the scope of the test case (whether at the suite, class or method level). The bonus of setting up this environment in the test falls on the developer’s shoulders.

With Arquillian, you no longer have to worry about setting up the execution environment because that is all handled for you. The test will either be running in a container or a local CDI environment. But you still need some way to hook your test into this environment.

A key part of in-container integration testing is getting access to the container-managed components that you plan to test. Using the Java’s new operator to instantiate the business class is not suitable in this testing scenario because it leaves out the declaratives services that get applied to the component at runtime. We want the real deal. Arquillian uses test enrichment to give us access to the real deal. The visible result of test enrichment is injection of container resources and beans directly into the test class.

2.6.1. Dependency Injection

Before Arquillian negotiates the execution of the test, it enriches the test class by satisfying injection points specified declaratively using annotations.

Test Case Injection Points

Injection points are recognized in the following two locations:

  1. Field (any visibility)

  2. @Test method argument

Here’s an example of a field injection in a test class:

@RunWith(Arquillian.class)
public class GreeterTestCase {
    @Inject
    private Greeter greeter;

    ...
}

Here’s an example of a method argument injection in a test method:

@Test
public void testGreeting(Greeter greeter) {
  ...
}

Note that the @Inject annotation is not required when injecting into a method argument.

Default Enrichers

There are three injection-based enrichers provided by Arquillian out of the box:

  • @Resource - Java EE resource injections

  • @EJB - EJB session bean reference injections

  • @Inject, @Resource, @EJB, @PersistenceContext and @PersistenceUnit - CDI-supported injections

The first two enrichers use JNDI to lookup the instance to inject. The CDI injections are handled by treating the test class as a bean capable of receiving standard CDI injections (non-contextual injection). Since CDI requires containers to satisfy all Java EE injection points on a CDI bean, the @Resource, @EJB, @PersistenceContext and @PersistenceUnit injections are supported transitively by the CDI enricher. In fact, because of CDI’s tight integration with the container, @EJB injections in the test class are satisfied according to specification when the CDI enricher is available.

Resource Injection

The @Resource annotation gives you access to any object which is available via JNDI. It follows the standard rules for @Resource (as defined in the Section 2.3 of the Common Annotations for the Java Platform specification).

EJB Injection (without CDI support)

The @EJB annotation performs a JNDI lookup for the EJB session bean reference using the following equation in the specified order:

"java:global/test.ear/test/" + fieldType.getSimpleName() + "Bean",
"java:global/test.ear/test/" + fieldType.getSimpleName(),
"java:global/test/" + fieldType.getSimpleName(),
"java:global/test/" + fieldType.getSimpleName() + "Bean",
"java:global/test/" + fieldType.getSimpleName() + "/no-interface",
"test/" + unqualified interface name + "Bean/local",
"test/" + unqualified interface name + "Bean/remote",
"test/" + unqualified interface name + "/no-interface",
unqualified interface name + "Bean/local",
unqualified interface name + "Bean/remote",
unqualified interface name + "/no-interface"

If no matching beans were found in those locations the injection will fail.

At the moment, the lookup for an EJB session reference relies on some common naming convention of EJB beans. In the future the lookup will rely on the standard JNDI naming conventions established in Java EE 6.

CDI Injection

In order for CDI injections to work, the test archive defined with ShrinkWrap must be in a bean archive. That means adding beans.xml to the META-INF directory. Here’s a @Deployment method that shows one way to add a beans.xml to the archive:

@Deployment
public static JavaArchive createTestArchive() {
   return ShrinkWrap.create(JavaArchive.class, "test.jar")
      .addClass(NameOfClassUnderTest.class)
      .addAsManifestResource(EmptyAsset.INSTANCE, Paths.create("beans.xml"))

In an application that takes full advantage of CDI, you can likely get by only using injections defined with the @Inject annotation. Regardless, the other two types of injection come in handy from time-to-time.

2.6.2. Active Scopes

When running your tests the embedded Weld EE container, Arquillian activates scopes as follows:

  • Application scope - Active for all methods in a test class

  • Session scope - Active for all methods in a test class

  • Request scope - Active for a single test method

Scope control is experimental at this point and may be altered in a future release of Arquillian.

2.7. Rules

If you want to use Arquillian Testing Platform with other JUnit Runner, you can now use JUnit Rules - ArquillianTestClass and ArquillianTest - and happily let Arquillian do the heavy lifting for your tests.

To get the similar functionality what the @RunWith(Arquillian.class) is offering you should require both rules i.e. ArquillianTestClass and ArquillianTest. If you are trying to run tests with one rule, it won’t work as per expectations. We are not enforcing user to define both rules as implementations of MethodRuleChain is different for different users. JUnit doesn’t provide MethodRuleChain similar to the RuleChain, as we don’t know your implementation of MethodRuleChain, we can’t check if your MethodRuleChain has ArquillianTest Rule defined.

In order to use this feature, your project needs JUnit 4.12 version.

2.7.1. How to use it?

public class GreeterManagedBeanWithJUnitRulesTestCase {

    @ClassRule
    public static ArquillianTestClass arquillianTestClass = new ArquillianTestClass();

    @Rule
    public ArquillianTest arquillianTest = new ArquillianTest();

    @Deployment
    public static JavaArchive createDeployment() {
        return ShrinkWrap.create(JavaArchive.class)
            .addClass(Greeter.class)
            .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
    }

    @Inject
    Greeter greeter;

    @Test
    public void should_greet_earthlings() throws Exception {
        String name = "Earthlings";
        Assert.assertEquals("Hello, " + name, greeter.greet(name));
    }

}
However while using above Junit Rules you can’t inject method scoped Arquillian resources. Unfortunately it is not possible to have one rule acting as both test class and test method rule. For more info see this comment. In order to use any other JUnit Method Rule with ArquillianTest Rule, you have to use it with RuleChain having ArquillianTest as outer Rule. e.g.
   @Rule
   public MethodRule testWatchman = MethodRuleChain.outer(new ArquillianTest().around(new TestWatchman());

2.8. Additional Features

This chapter walks through the following additional features that Arquillian provides to address more advanced use cases. These features may even allow you to write tests for scenarios you previously classified as too difficult to test.

2.8.1. Test Run Modes

So far, we’ve focused on testing your application internals, but we also want to test how others (people, or other programs) interact with the application. Typically, you want to make sure that every use case and execution path is fully tested. Third parties can interact with your application in a number of ways, for example web services, remote EJBs or via HTTP. You need to check that your object serialization or networking work for instance.

This is why Arquillian comes with two run modes, in container and as client. in container is to test your application internals and as client is to test how your application is used by clients. Let’s dive a bit deeper into the differences between the run modes and see how they affect your test execution and packaging.

Container mode: @Deployment(testable = true)

As we mentioned above, we need to repackage your @Deployment, adding some Arquillian support classes, to run in-container. This gives us the ability to communicate with the test, enrich the test and run the test remotely. In this mode, the test executes in the remote container.

Arquillian uses this mode by default.

See the Complete Protocol Reference for an overview of the expected output of the packaging process when you provide a @Deployment.

Client mode: @Deployment(testable = false)

Now this mode is the easy part. As opposed to in-container mode which repackages and overrides the test execution, the as-client mode does as little as possible. It does not repackage your @Deployment nor does it forward the test execution to a remote server. Your test case is running in your JVM as expected and you’re free to test the container from the outside, as your clients see it. The only thing Arquillian does is to control the lifecycle of your @Deployment.

Here is an example calling a Servlet using the as client mode.

@RunWith(Arquillian.class)
public class LocalRunServletTestCase {
    @Deployment(testable = false)
    public static WebArchive createDeployment() {
        return ShrinkWrap.create(WebArchive.class, "test.war")
                .addClass(TestServlet.class);
   }

    @Test
    public void shouldBeAbleToCallServlet(@ArquillianResource(TestServlet.class) URL baseUrl) throws Exception {
        String body = readAllAndClose(new URL(baseUrl, "/Test").openStream());
        Assert.assertEquals(
            "Verify that the servlet was deployed and returns the expected result",
            "hello",
            body);
   }
}
Mixed mode

It is also possible to mix the two run modes within the same test class. If you have defined the Deployment to be testable, you can specify the @Test method to use run mode as client by using the @RunAsClient annotation. This will allow two methods within the same test class to run in different modes. This can be useful if, in as client mode, you want to execute against a remote endpoint in your application, and then in the next test method, use in container mode to verify some state the previous remote invocation created on the server side.

@Deployment(testable = true)
public static WebArchive create() {
   ...
}

@Test // runs in container
public void shouldBeAbleToRunOnContainerSide() throws Exception {
   ...
}

@Test @RunAsClient // runs as client
public void shouldBeAbleToRunOnClientSide() throws Exception {
   ...
}

The effect of the different run modes depends on the DeployableContainer used. Both modes might seem to behave the same in some Embedded containers, but you should avoid mixing your internal and external tests. One thing is that they should test different aspects of your application and different use-cases, another is that you will miss the benefits of switching DeployableContainers and run the same tests suite against a remote server if you do.

2.8.2. Descriptor Deployment

We have previously seen Arquillian deploys ShrinkWrap Archives, but some times you need to deploy other items like a JMS Queue or a DataSource for your test to run. This can be done by using a ShrinkWrap sub project called ShrinkWrap Descriptors. Just like you would deploy an Archive you can deploy a Descriptor.

@Deployment(order = 1)
public static Descriptor createDep1()
{
  return Descriptors.create(DataSourceDescriptor.class);
}

@Deployment(order = 2)
public static WebArchive createDep2() {}

@Test
public void testDataBase() {}

2.8.3. Arquillian Resource Injection

When dealing with multiple different environments and hidden dynamic container configuration you very soon come to a point where you need access to the backing containers ip/port/context information. This is especially useful when doing remote end point testing. So instead of trying to setup all containers on the same ip/port/context, or hard code this in your test, Arquillian provides something we call @ArquillianResource injection. Via this injection point we can expose multiple internal objects.

Note that @ArquillianResource injection of URLs is only supported for in-container tests since Arquillian version 1.1.9.Final (see https://issues.jboss.org/browse/ARQ-540[ARQ-540]).

When you need to get a hold of the request URI (up through the context path) your Deployment defined, e.g. "http://localhost:8080/test", you can use @ArquillianResource on a field or method argument of type URL:

@ArquillianResource
private URL baseURL;

@Test
private void shouldDoX(@ArquillianResource URL baseURL)
{
}

If you are deploying an EAR with multiple WARs, and you’ve deployed a given servlet to just one of them, you can provide the servlet’s class to get the request URI up through the context path for the WAR that contains that servlet, e.g. "http://localhost:8080/test1" vs. "http://localhost:8080/test2":

@ArquillianResource(MyServlet.class)
private URL baseURL;

@Test
private void shouldDoX(@ArquillianResource(MyServlet.class) URL baseURL)
{
}
Note that this version does not return the request URI to the given servlet, e.g. "http://localhost:8080/test2/MyServlet", but again just the request URI up through the context path.

2.8.4. Multiple Deployments

Sometimes a single Deployment is not enough, and you need to specify more than one to get your test done.

Maybe you want to test communication between two different web applications?

Arquillian supports this as well. Simply just add more @Deployment methods to the test class and you’re done. You can use the @Deployment.order if they need to be deployed in a specific order. When dealing with multiple in container deployments, you need to specify which Deployment context the individual test methods should run in. You do this by adding a name to the deployment by using the @Deployment.name and refer to that name on the test method by adding @OperateOnDeployment("deploymentName").

@Deployment(name = "dep1", order = 1)
public static WebArchive createDep1() {}

@Deployment(name = "dep2", order = 2)
public static WebArchive createDep2() {}

@Test @OperateOnDeployment("dep1")
public void testRunningInDep1() {}

@Test @OperateOnDeployment("dep2")
public void testRunningInDep2() {}

2.8.5. Multiple Containers

There are times when you need to involve multiple containers in the same test case, if you for instance want to test clustering. The first step you need to take is to add a group with multiple containers to your Arquillian configuration.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
    <group qualifier="tomcat-cluster" default="true">
        <container qualifier="container-1" default="true">
            <configuration>
                <property name="tomcatHome">target/tomcat-embedded-6-standby</property>
                <property name="workDir">work</property>
                <property name="bindHttpPort">8880</property>
                <property name="unpackArchive">true</property>
            </configuration>
        </container>
        <container qualifier="container-2">
            <configuration>
                <property name="tomcatHome">target/tomcat-embedded-6-active-1</property>
                <property name="workDir">work</property>
                <property name="bindHttpPort">8881</property>
                <property name="unpackArchive">true</property>
            </configuration>
        </container>
    </group>
</arquillian>

So what we have done here is to say we have two containers that Arquillian will control, container-1 and container-2. Arquillian will now instead of starting up one container, which is normal, start up two. In your test class you can target different deployments against the different containers using the @TargetsContainer("containerName") annotation on your Deployment methods.

@Deployment(name = "dep1") @TargetsContainer("container-1")
public static WebArchive createDep1() {}

@Deployment(name = "dep2")  @TargetsContainer("container-2")
public static WebArchive createDep2() {}

@Test @OperateOnDeployment("dep1")
public void testRunningInDep1() {}

@Test @OperateOnDeployment("dep2")
public void testRunningInDep2() {}

We now have a single test class that will be executed in two different containers. testRunningInDep1 will operate in the context of the dep1 deployment which is deployed on the container named container-1 and testRunningInDep2 will operate in the context of deployment dep2 which is deployed on container container-2. As the test moves along, each method is executed inside the individual containers.

Arquillian does not support ClassLoader isolation on the client side so for this feature to work the container adapter must support running multiple instances within the same ClassLoader/JVM. Currently this only works with containers of type Remote or Managed as the adapter normally will connect to an isolated server started in its own JVM.

2.8.6. Protocol Selection

A protocol is how Arquillian talks and executes the tests inside the container. For ease of development and configuration a container defines a default protocol that will be used if no other is specified. You can override this default behavior by defining the @OverProtocol annotation on your @Deployment method.

@Deployment @OverProtocol("MyCustomProtocol")
public static WebArchive createDep1() {}

@Test
public void testExecutedUsingCustomProtocol() {}

When testExecutedUsingCustomProtocol is executed, instead of using the containers protocol which is defined by default, Arquillian will use MyCustomProtocol to communicate with the container. Since this is defined on Deployment level, you can have different test methods which operate on different deployments and therefore being executed using different protocols. This can be useful when for instance a protocols packaging requirements hinder how you define your archive, or you simply can not communicate with the container using the default protocol due to e.g. firewall settings.

Arquillian only supports Servlet 2.5 and Servlet 3.0 at this time. EJB 3.0 and 3.1 are planned. But you might implement your own Protocol. For doing this, please see the Complete Protocol Reference for the better knowing what is currently supported.

2.8.7. Enabling Assertions

The first time you try Arquillian, you may find that assertions that use the Java assert keyword are not working. Keep in mind that the test is not executing the same JVM as the test runner.

In order for the Java keyword "assert" to work you have to enable assertions (using the -ea flag) in the JVM that is running the container. You may want to consider specifying the package names of your test classes to avoid assertions to be enabled throughout the container’s source code.

Enabling Assertions In JBoss AS

If you are using JBoss AS, the quickest way to setup debug mode is to add the following line to the end of $JBOSS_AS_HOME/bin/run.conf (Unix/Linux):

JAVA_OPTS="$JAVA_OPTS -ea"

or before the line :JAVA_OPTS_SET in $JBOSS_AS_HOME/bin/run.conf.bat (Windows)

set "JAVA_OPTS=%JAVA_OPTS% -ea"

Keep in mind your container will always run with assertions enabled after making this change. You might want to consider putting some logic in the run.conf* file.

As an alternative, we recommend using the 'Assert' object that comes with your test framework instead to avoid the whole issue. Also keep in mind that if you use System.out.println statements, the output is going to show up in the log file of the container rather than in the test output.

2.9. Protocols

In order to support running the same test locally and in remote containers, Arquillian uses an SPI that controls which protocol is used to negotiate execution of the test. This appendix details the default protocols that Arquillian provides, when they are used and how they can be configured.

2.9.1. Local

The Local Protocol implementation is used by most EE5 compliant containers. It does nothing to the deployment. The Local Protocol is also used when executing in run mode as client.

Packaging rules

@Deployment Output Action

JavaArchive

JavaArchive

Does nothing.

WebArchive

WebArchive

Does nothing.

EnterpriseArchive

EnterpriseArchive

Does nothing.

Configuration

Protocol Configuration Options

Name Type Default Description

2.9.2. Servlet 2.5

The Servlet 2.5 Protocol implementation is used by most EE5 compliant containers. It will attempt to add a war to the deployment.

Packaging rules

@Deployment Output Action

JavaArchive

EnterpriseArchive

Create a new EnterpriseArchive, add @Deployment and ServletProtocol as module, the other Auxiliary Archives as libraries.

WebArchive

WebArchive

If a web.xml is found, a Servlet will be added, else a web.xml will be added. The Servlet WebArchive will be merged with the Deployment and the Auxiliary Archives added as libraries.

EnterpriseArchive

EnterpriseArchive

Same as JavaArchive, but using the @Deployment defined EnterpriseArchive instead of creating a new.

Configuration

Protocol Configuration Options

Name Type Default Description

host

String

none

Used to override the Deployments default hostname.

port

int

none

Used to override the Deployments default http port.

contextRoot

String

none

Used to override the Deployments default contextRoot.

2.9.3. Servlet 3.0

The Servlet 3.0 Protocol implementation is used by most EE6 compliant containers. It will attempt to add a web-fragment to the deployment.

Packaging rules

@Deployment Output Action

JavaArchive

WebArchive

Creates a new WebArchive, adds @Deployment and Auxiliary Archives as libraries.

WebArchive

WebArchive

Adds @Deployment and Auxiliary Archives as libraries.

EnterpriseArchive

EnterpriseArchive

If a single WebArchive is found, the same as for WebArchive is done. If no WebArchives are found a new one is created, adds @Deployment and Auxiliary Archives as libraries. If multiple WebArchives are found, a exception is thrown.

Configuration

Protocol Configuration Options

Name Type Default Description

host

String

none

Used to override the Deployments default hostname.

port

int

none

Used to override the Deployments default http port.

contextRoot

String

none

Used to override the Deployments default contextRoot.

2.10. Build Integration

Just because the Arquillian project uses Maven doesn’t mean you have to use it to run your Arquillian tests. Arquillian is designed to have seamless integration with JUnit and TestNG without any necessary test framework configuration. That means you can use any build system that has a JUnit or TestNG task to execute your Arquillian test cases. Since most of this guide focuses on using Arquillian in a Maven build, this chapter is going to be about alternative build systems, namely Gradle and Ant.

2.10.1. Active Build Ingredient

The secret ingredient required to activate the Arquillian test runner is getting the correct libraries on the classpath. (Often easier said than done). The libraries consist of the Arquillian container integration and the container runtime (for an embedded container) or deployment client (for a remote container).

In general, the steps to incorporate Arquillian into a build, regardless of what build tool you are using, can be summarized as:

  1. Activate/configure the JUnit or TestNG task/plugin

  2. Add the Arquillian container integration to the test classpath (e.g., org.jboss.arquillian.container:arquillian-%VENDOR%-%TYPE%-%VERSION%)

  3. Add the container runtime (embedded) or deployment client (remote) to the classpath

  4. Execute the test build task/goal

If you are only running the Arquillian tests on a single container, this setup is exceptionally straightforward. The challenge comes when you want to run the tests on multiple containers. It’s really just a matter of putting the correct libraries on the test classpath, though.

For some build systems, isolating multiple classpath definitions is more tricky than others. For instance, in Maven, you only get one test classpath per run (without using really advanced plugin configuration). You can toggle between different test classpath pairings through the use of profiles. Each profile contains the libraries for a single target container (a combination of the libraries itemized in steps 2 and 3 above). You’ll see this strategy used in the Arquillian examples.

Other build tools, such as Gradle, can easily define new test tasks that each have their own, unique classpath. This makes it not only possible to separate out the target containers, but also run the tests against each one in the same build execution. We’ll see an example of that later in this chapter. Gradle can also emulate the Maven profile strategy through the use of build fragment imports. We’ll also show an example of that approach for contrast.

2.10.2. Maven

The community has gravitated towards Maven as the preferred build tool for projects that use Arquillian. Details on how to setup Arquillian in a Maven project is covered in detail in the Arquillian Guides.

2.10.3. Gradle

Gradle is a build tool that allows you to create declarative, maintainable, concise and highly-performing builds. More importantly, in this context, Gradle gives you all the freedom you need instead of imposing a rigid build lifecycle on you. You’ll get a glimpse of just how flexible Gradle can be by learning how to integrate Arquillian into a Gradle build.

We’ll be contrasting two strategies for running Arquillian tests from Gradle:

  1. Container-specific test tasks

  2. Test "profiles" via build fragment imports

The first strategy is the recommended one since it gives you the benefit of being able to run your tests on multiple containers in the same build. However, the second approach is less esoteric and will be more familiar to Maven users. Of course, Gradle is so flexible that there are likely other solutions for this problem. We invite you to give us feedback if you find a better way (or another way worth documenting).

Let’s get the common build stuff out of the way, then dive into the two strategies listed above.

apply from: common

The simplest Gradle build for a Java project is a sparse one line.

apply plugin: JavaPlugin

Put this line into a file named build.gradle at the root of the project, which is the standard location of the Gradle build file. (Perhaps after seeing this configuration you’ll understand the reference in the section title).

Next we’ll add the Maven Central and JBoss Community repository definitions, so that we can pull down dependent libraries. The latter repository hosts the Arquillian artifacts.

apply plugin: JavaPlugin

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

If your SCM (e.g., SVN, Git) is already ignoring the target directory, you may want to move the Gradle build output underneath this folder, rather than allowing Gradle to use it’s default build directory, build. Let’s add that configuration to the common build logic as well:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

If you are using Gradle alongside Maven, you shouldn’t set the buildDir to target since Gradle organizes compiled classes different than Maven does, possibly leading to conflicts (Though, the behavior of Gradle can also be customized).

We also recommend that you centralize version numbers at the top of your build to make upgrading your dependency easy. This list will grow as you add other containers, but we’ll seed the list for the examples below:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha4', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

...

We also need to add the unit test library (JUnit or TestNG) and the corresponding Arquillian integration:

dependencies {
   testCompile group: 'junit', name: 'junit', version: libraryVersions.junit
   testCompile group: 'org.jboss.arquillian', name: 'arquillian-junit', version: libraryVersions.arquillian
}

In this example, we’ll assume the project is compiling against APIs that are provided by the target container runtime, so we need to add a dependency configuration (aka scope) to include libraries on the compile classpath but excluded from the runtime classpath. In the future, Gradle will include support for such a scope. Until then, we’ll define one ourselves in the configurations closure.

configurations {
   compileOnly
}

We also need to add the dependencies associated with that configuration to the compile classpaths using the sourceSets closure:

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

Here’s the Gradle build all together now:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha3', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

configurations {
   compileOnly
}

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

Now that the foundation of a build is in place (or you’ve added these elements to your existing Gradle build), we are ready to configuring the container-specific test tasks. In the first approach, we’ll create a unique dependency configuration and task for each container.

Strategy #1: Container-Specific Test Tasks

Each project in Gradle is made up of one or more tasks. A task represents some atomic piece of work which a build performs. Examples include compiling classes, executing tests, creating a JAR, publishing an artifact to a repository. We are interested in the executing tests task. But it’s not necessarily just a single test task. Gradle allows you to define any number of test tasks, each having its own classpath configuration. We’ll use this to configure test executions for each container.

Let’s assume that we want to run the tests against the following three Arquillian-supported containers:

  • Weld EE Embedded 1.1

  • Remote JBoss AS 6

  • Embedded GlassFish 3

We’ll need three components for each container:

  1. Dependency configuration (scope)

  2. Runtime dependencies

  3. Custom test task

We’ll start with the Weld EE Embedded container. Starting from the Gradle build defined in the previous section, we first define a configuration for the test runtime dependencies.

configurations {
   compileOnly
   weldEmbeddedTestRuntime { extendsFrom testRuntime }
}

Next we add the dependencies for compiling against the Java EE API and running Arquillian tests in the Weld EE Embedded container:

dependencies {
   compileOnly group: 'javax.enterprise', name: 'cdi-api', version: libraryVersions.cdi

   testCompile group: 'junit', name: 'junit', version: libraryVersions.junit
   testCompile group: 'org.jboss.arquillian', name: 'arquillian-junit', version: libraryVersions.arquillian

   // temporarily downgrade the weld-ee-embedded-1.1 container
   weldEmbeddedTestRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-weld-ee-embedded-1.1', version: '1.0.0.Alpha3'
   weldEmbeddedTestRuntime group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec
   weldEmbeddedTestRuntime group: 'org.jboss.weld', name: 'weld-core', version: libraryVersions.weld
   weldEmbeddedTestRuntime group: 'org.slf4j', name: 'slf4j-log4j12', version: libraryVersions.slf4j
   weldEmbeddedTestRuntime group: 'log4j', name: 'log4j', version: libraryVersions.log4j
}

Finally, we define the test task:

task weldEmbeddedTest(type: Test) {
   testClassesDir = sourceSets.test.classesDir
   classpath = sourceSets.test.classes + sourceSets.main.classes + configurations.weldEmbeddedTestRuntime
}

This task will execute in the lifecycle setup by the Java plugin in place of the normal test task. You run it as follows:

gradle weldEmbeddedTest

Or, more simply:

gradle wET

Now we just repeat this setup for the other containers.

Since you are creating custom test tasks, you likely want to configure the default test task to either exclude Arquillian tests are to use a default container, perhaps Weld EE Embedded in this case.

Here’s the full build file with the tasks for our three target containers:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha4', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/repositories/deprecated'
}

configurations {
   compileOnly
   weldEmbeddedTestRuntime { extendsFrom testRuntime }
   jbossasRemoteTestRuntime { extendsFrom testRuntime, compileOnly }
   glassfishEmbeddedTestRuntime { extendsFrom testRuntime }
}

dependencies {
   compileOnly group: 'javax.enterprise', name: 'cdi-api', version: libraryVersions.cdi

   testCompile group: 'junit', name: 'junit', version: libraryVersions.junit
   testCompile group: 'org.jboss.arquillian', name: 'arquillian-junit', version: libraryVersions.arquillian

   // temporarily downgrade the weld-ee-embedded-1.1 container
   weldEmbeddedTestRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-weld-ee-embedded-1.1', version: '1.0.0.Alpha3'
   weldEmbeddedTestRuntime group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec
   weldEmbeddedTestRuntime group: 'org.jboss.weld', name: 'weld-core', version: libraryVersions.weld
   weldEmbeddedTestRuntime group: 'org.slf4j', name: 'slf4j-log4j12', version: libraryVersions.slf4j
   weldEmbeddedTestRuntime group: 'log4j', name: 'log4j', version: libraryVersions.log4j

   jbossasRemoteTestRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-jbossas-remote-6', version: libraryVersions.arquillian
   jbossasRemoteTestRuntime group: 'org.jboss.jbossas', name: 'jboss-as-server', classifier: 'client', version: libraryVersions.jbossas, transitive: false
   jbossasRemoteTestRuntime group: 'org.jboss.jbossas', name: 'jboss-as-profileservice', classifier: 'client', version: libraryVersions.jbossas

   glassfishEmbeddedTestRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-glassfish-embedded-3', version: libraryVersions.arquillian
   glassfishEmbeddedTestRuntime group: 'org.glassfish.extras', name: 'glassfish-embedded-all', version: libraryVersions.glassfish
}

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

task weldEmbeddedTest(type: Test) {
   testClassesDir = sourceSets.test.classesDir
   classpath = sourceSets.test.classes + sourceSets.main.classes + configurations.weldEmbeddedTestRuntime
}

task jbossasRemoteTest(type: Test) {
   testClassesDir = sourceSets.test.classesDir
   classpath = sourceSets.test.classes + sourceSets.main.classes + files('src/test/resources-jbossas') + configurations.jbossasRemoteTestRuntime
}

task glassfishEmbeddedTest(type: Test) {
   testClassesDir = sourceSets.test.classesDir
   classpath = sourceSets.test.classes + sourceSets.main.classes + configurations.glassfishEmbeddedTestRuntime
}

Notice we’ve added an extra resources directory for remote JBoss AS 6 to include the required jndi.properties file. That’s a special configuration for the remote JBoss AS containers, though won’t be required after Arquillian 1.0.0.Alpha4.

It’s now possible to run the Arquillian tests against each of the three containers in sequence using this Gradle command (make sure a JBoss AS is started in the background):

gradle weldEmbeddedTest jbossasRemoteTest glassfishEmbeddedTest

Pretty cool, huh?

Now let’s look at another way to solve this problem.

Strategy #2: Test Profiles

Another way to approach integrating Arquillian into a Gradle build is to emulate the behavior of Maven profiles. In this case, we won’t be adding any extra tasks, rather overriding the Java plugin configuration and provided tasks.

A Maven profile effectively overrides portions of the build configuration and is activated using a command option (or some other profile activation setting).

Once again, let’s assume that we want to run the tests against the following three Arquillian-supported containers:

  • Weld EE Embedded 1.1

  • Remote JBoss AS 6

  • Embedded GlassFish 3

All we need to do is customize the test runtime classpath for each container. First, let’s setup the common compile-time dependencies in the main build file:

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha3', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

configurations {
   compileOnly
}

dependencies {
   group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec
}

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

We then need to create a partial Gradle build file for each container that contains the container-specific dependencies and configuration. Let’s start with Weld EE Embedded.

Create a file named weld-ee-embedded-profile.gradle and populate it with the following contents:

dependencies {
   // temporarily downgrade the weld-ee-embedded-1.1 container
   testRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-weld-ee-embedded-1.1', version: '1.0.0.Alpha3'
   testRuntime group: 'org.jboss.spec', name: 'jboss-javaee-6.0', version: libraryVersions.jbossJavaeeSpec
   testRuntime group: 'org.jboss.weld', name: 'weld-core', version: libraryVersions.weld
   testRuntime group: 'org.slf4j', name: 'slf4j-log4j12', version: libraryVersions.slf4j
   testRuntime group: 'log4j', name: 'log4j', version: libraryVersions.log4j
}

Here’s the partial build file for Remote JBoss AS, named jbossas-remote-profile.gradle:

dependencies {
   testRuntime group: 'javax.enterprise', name: 'cdi-api', version: libraryVersions.cdi
   testRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-jbossas-remote-6', version: libraryVersions.arquillian
   testRuntime group: 'org.jboss.jbossas', name: 'jboss-as-server', classifier: 'client', version: libraryVersions.jbossas, transitive: false
   testRuntime group: 'org.jboss.jbossas', name: 'jboss-as-profileservice', classifier: 'client', version: libraryVersions.jbossas
}

test {
   classpath = sourceSets.test.classes + sourceSets.main.classes + files('src/test/resources-jbossas') + configurations.testRuntime
}

And finally the one for Embedded GlassFish, named glassfish-embedded-profile.gradle:

dependencies {
   testRuntime group: 'org.jboss.arquillian.container', name: 'arquillian-glassfish-embedded-3', version: libraryVersions.arquillian
   testRuntime group: 'org.glassfish.extras', name: 'glassfish-embedded-all', version: libraryVersions.glassfish
}

Now we need to import the appropriate partial Gradle build into the main build. The file will be selected based on the value of the project property named profile.

apply plugin: JavaPlugin

buildDir = 'target/gradle-build'

libraryVersions = [
   junit: '4.8.1', arquillian: '1.0.0.Alpha4', jbossJavaeeSpec: '1.0.0.Beta7', weld: '1.0.1-Final',
   slf4j: '1.5.8', log4j: '1.2.14', jbossas: '6.0.0.Final', glassfish: '3.0.1-b20', cdi: '1.0-SP1'
]

apply from: profile + '-profile.gradle'

repositories {
   mavenCentral()
   mavenRepo urls: 'http://repository.jboss.org/nexus/content/groups/public'
}

configurations {
   compileOnly
}

dependencies {
   compileOnly group: 'javax.enterprise', name: 'cdi-api', version: libraryVersions.cdi

   testCompile group: 'junit', name: 'junit', version: libraryVersions.junit
   testCompile group: 'org.jboss.arquillian', name: 'arquillian-junit', version: libraryVersions.arquillian
}

sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}

Tests are run in the Weld EE Embedded runtime using this command:

gradle test -Pprofile=weld-ee-embedded

That’s pretty much the same experience you get when you use Maven (and a whole heck of a lot simpler).

While the configuration is much simpler using the profiles strategy, there are two things to keep in mind:

  1. It crosses over into more than one build file

  2. You cannot run the tests in each container in a single build execution

If you have a better idea of how to integrate an Arquillian test suite into a Gradle build, we’d love to hear it on the Arquillian discussion forums.

2.10.4. Ant + Ivy

WRITE ME

2.10.5. Ant

This guide will detail how to use Arquillian using ant. We will use maven to download all the required jars.

Overview of Steps

  1. Setup Example Maven project

  2. Get All Arquillian dependency jars

  3. configure ant scripts

Work in progress. Please return.

3. Advanced Topics

3.1. Debugging

If you are struggling with running your Arquillian test and you need more info about what is going on underneath, then you can specify -Darquillian.debug=true. Arquillian will print out its lifecycle so you will know exactly where it got stuck. The output has four types of information - you can distinguish them by their prefix:

  • (E) Arquillian event that was fired

  • (I) Arquillian interceptor that observed the related event context

  • (O) Arquillian observer that observed the related event

  • (X) Arquillian extension that was registered

3.2. Test Observer

In case you need to add an additional logic to the whole test suite, you can use Arquillian SPI and create your own Arquillian extension. But this extension is applied to all test classes. In case you want to add an additional observer that will be applied only to one specific test class, then you can use an annotation @Observer at the test class level. This will use the specified class(es) as Arquillian observer(s) and observe any Arquillian event in the context of the related test class that you need (starting with BeforeClass and ending with AfterClass):

@RunWith(Arquillian.class)
@Observer(MyObserver.class)
public class MyTestCase {

The Arquillian observer class has to have a non-parametric constructor and the observer method should be defined by @Observes annotation:

public void observeBeforeClass(@Observes BeforeClass event) {
    ...
}

4. Useful URLs