arquillian / arquillian-container-chameleon

Chameleon container that dynamically loads correct container adapter versions for your tests
Apache License 2.0
36 stars 22 forks source link

== Arquillian Chameleon Container image:https://travis-ci.org/arquillian/arquillian-container-chameleon.svg?branch=master["Build Status", link="https://travis-ci.org/arquillian/arquillian-container-chameleon"]

[quote] Proxy Container for all JBoss AS / JBoss EAP / WildFly containers

Have you ever faced an issue that switching between container implementations isn't that easy?

Testing against several containers (JBoss AS / JBoss EAP / WildFly) or even switching between different modes (Managed, Remote, Embedded) may result in bloated pom.xml.

Chameleon Containers are able to quickly adopt to your needs without too much hassle.

==== Story

[quote] Chameleons are a tall, lizard-looking alien race that has (same as their earthling friends) ability to change colours when adopting to various environments. They are usually transported in spaceships called Containers.

=== Get Started

Do whatever you http://arquillian.org/guides/getting_started/[would do normally] and add Chameleon JUnit or TestNG Container starters instead of any application-server specific artifact:

[source, xml] .arquillian-chameleon-junit-container-starter

org.arquillian.container arquillian-chameleon-junit-container-starter 1.0.0.Final-SNAPSHOT test

[source, xml] .arquillian-chameleon-testng-container-starter

org.arquillian.container arquillian-chameleon-testng-container-starter 1.0.0.Final-SNAPSHOT test

Add this configuration to arquillian.xml:

[source, xml]

wildfly:8.0.0.Final:managed standalone-full.xml

Now, you can switch container implementation as simple as changing the chameleonTarget configuration option(e.g. wildfly:8.0.0.Final:remote or wildfly:9.0.0.CR1:managed).

And off course, you can still configure the underlying container by its specific configuration (e.g. change serverConfig).

Example chameleonTarget values:

=== Supported Containers

[NOTE] Chameleon will download and extract the target container if no distribution home is configured and target type is either embedded or managed.

[IMPORTANT] Glassfish versions prior to 3.1.2 are no longer supported due to issues with dependencies of the distribution

=== Configuration options

==== chameleonTarget

Define the underlying target in the format name:version[:type]. If no type is defined, the adapter type used depend on the underlying container configuration. Use no type if you just want 'something' up and running with as little extra configuration as possible.

==== chameleonDistributionDownloadFolder

Override the default download folder for container distributions. Could be defined as TMP to create a custom folder under java.io.tmpdir, else it will be read as a directory. Defaults to detect current build system, either target/ for Maven or build/ for Gradle.

==== chameleonContainerConfigurationFile

Define the container configuration file to use. Defaults to the containers.yaml file provided by Chameleon.

==== chameleonResolveCacheFolder

Define where Chameleon should store the resolver cache files. By default it will use 'chameleonDistributionDownloadFolder'/cache.

== Development

If you want to add your own container configurations or contribute to the ones shipped as default with Chameleon you can use the following format to describe them:

[source,yaml] .chameleon/default/containers.yaml

NOTE: If you want to help improve the configurations, you can find issues related to this configuration labeled as https://github.com/arquillian/arquillian-container-chameleon/labels/container[container] in the https://github.com/arquillian/arquillian-container-chameleon/issues[issue tracker].

==== WildFly Embedded If you want to run any of the versions of WildFly embedded, you need to add an additional dependency to your pom.xml file: [source,xml]

org.jboss.logmanager jboss-logmanager ${jboss.logmanager.version}

and set java.util.logging.manager variable to org.jboss.logmanager.LogManager using maven-surefire-plugin: [source,xml]

maven-surefire-plugin org.jboss.logmanager.LogManager

== Custom Maven setting

In case you need to specify your custom settings.xml file and you cannot put it at the default location ($HOME/.m2/settings.xml) then use the property org.apache.maven.user-settings to specify a user settings.xml file or org.apache.maven.global-settings to specify a global settings.xml file.

The standard Maven property -s doesn't work as Chameleon internally uses Shrinkwrap Resolver and the property is not supported there. But you can use any of the properties described here: https://github.com/shrinkwrap/resolver#system-properties

== Arquillian Chameleon Runner

Arquillian Chameleon Container is a special container that allows you to define which container and mode without having to remember any concrete dependency of the desired container. You've seen this at <>.

This approach is the most versatile one and has been here for a long time and offers a generic and global solution, but with Chameleon, you can use another approach where instead of configuring container using arquillian.xml, you can use an annotation to set up the test container.

The first thing to do is add next dependency:

[source, xml] .pom.xml

org.arquillian.container arquillian-container-chameleon-runner ${project.version} test

Then instead of using Arquillian runner, you need to use a new one provided by Chameleon called ArquillianChameleon.

Then you need to annotate your test with @ChameleonTarget("wildfly:9.0.0.Final:managed") where you set the container, version, and mode as you usually do withchameleonTargetinarquillian.xml`.

But this annotation also allows you to set each of the property (even custom properties) one by one, for example:

[source, java]

@ChameleonTarget(container = "tomcat", version = "7.0.0", customProperties = { @Property(name="a", value="b") })

Last important thing to take into consideration is that @ChameleonTarget can be used in meta-annotations and inherit properties form meta-annotations. For example, you can use next form to define Tomcat container:

[source, java] .Tomcat.java

@Target({ ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @ChameleonTarget("tomcat:7.0.0:managed") // <1> public @interface Tomcat { }

<1> Defines container, version and mode And then to define that the test needs to be run in `Tomcat`, you can simply do: [source, java] .Tomcat.java ---- @Tomcat public class TomcatTest { } ---- But you can even redefine meta-annotations, for example, to specify Tomcat 8 you only need to do: [source, java] .Tomcat8.java ---- @Target({ ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Tomcat // <1> @ChameleonTarget(version = "8.0.0") // <2> public @interface Tomcat8 { } ---- <1> Inherit properties from `Tomcat` meta-annotation <2> Override version number All fields accept expressions like `${property:defaultValue} where property is first resolved as environment variable, if not set as the system property and if not the default value is used. [IMPORTANT] ==== There are some limitations when using this approach. * The first one is that test execution that occurs in the same JVM must use the same container, you cannot run in the same JVM a set of tests that require different containers (i.e some with Wildfly and others with Payara). If you want to do this you need to isolate each of the tests in different JVMs. * The second one is that if you are configuring extensions with `arquillian.properties` *AND* `arquillian.xml files at the same time and you run tests in parallel *within* the same JVM, then you might find some unexpected results. Of course, this is a corner case, but a solution to this is just moving configuration of one of the files to either `arquillian.properties` or `arquillian.xml` file or run parallel tests in different JVMs. ==== == Test To run the whole test suite with the correct configuration use profile `all`: `mvn clean verify -Pall` To run Arquillian Container TCK test suite use profile `tck`: `mvn clean verify -Ptck` == Community * Chat: #arquillian channel @ http://webchat.freenode.net/[irc.freenode.net] * http://arquillian.org/blog/[Blogs] * http://discuss.arquillian.org/[Forums]