ifdef::env-github,env-browser[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
:outfilesuffix: .adoc
endif::[]

=== Build Integration
:icons: font


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, Maven>> build, this
chapter is going to be about alternative build systems, namely <<gradle, Gradle>>
and <<ant, Ant>>.

==== 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.

[[maven]]
==== 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
http://arquillian.org/guides/[Arquillian Guides].

[[gradle]]
==== Gradle

http://gradle.org[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.

[source,java]
----
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.

[source,java]
----
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:

[source,java]
----
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:

[source,java]
----
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:

[source,java]
----
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.

[source,java]
----
configurations {
   compileOnly
}
----

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

[source,java]
----
sourceSets {
   main {
      compileClasspath = configurations.compile + configurations.compileOnly
   }
   test {
      compileClasspath = compileClasspath + configurations.compileOnly
   }
}
----

Here's the Gradle build all together now:

[source,java]
----
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.

[source,java]
----
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:

[source,java]
----
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:

[source,java]
----
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:

[source,java]
----
gradle weldEmbeddedTest
----

Or, more simply:

[source,java]
----
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:

[source,java]
----
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):

[source,java]
----
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:

[source,java]
----
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:

[source,java]
----
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:

[source,java]
----
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:

[source,java]
----
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.

[source,java]
----
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:

[source,java]
----
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
http://community.jboss.org/en/arquillian[Arquillian discussion forums].

[[ant-ivy]]
==== Ant + Ivy

WRITE ME

[[ant]]
==== 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.
