Skip to content

Instantly share code, notes, and snippets.

@aslakknutsen
Last active September 20, 2016 09:12
Show Gist options
  • Save aslakknutsen/3975179 to your computer and use it in GitHub Desktop.
Save aslakknutsen/3975179 to your computer and use it in GitHub Desktop.
Brute Force Arquillian Suite
<?xml version="1.0" encoding="UTF-8"?>
<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">
<defaultProtocol type="Servlet 3.0"/>
<extension qualifier="suite">
<property name="deploymentClass">org.jboss.arquillian.extension.suite.Deployments</property>
</extension>
</arquillian>
package org.jboss.arquillian.extension.suite;
import java.util.concurrent.Callable;
import org.jboss.arquillian.config.descriptor.api.ArquillianDescriptor;
import org.jboss.arquillian.container.spi.Container;
import org.jboss.arquillian.container.spi.ContainerRegistry;
import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
import org.jboss.arquillian.container.spi.client.deployment.Deployment;
import org.jboss.arquillian.container.spi.client.deployment.DeploymentScenario;
import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
import org.jboss.arquillian.container.spi.event.DeployDeployment;
import org.jboss.arquillian.container.spi.event.DeployManagedDeployments;
import org.jboss.arquillian.container.spi.event.DeploymentEvent;
import org.jboss.arquillian.container.spi.event.UnDeployDeployment;
import org.jboss.arquillian.container.spi.event.UnDeployManagedDeployments;
import org.jboss.arquillian.container.spi.event.container.AfterStart;
import org.jboss.arquillian.container.spi.event.container.BeforeStop;
import org.jboss.arquillian.container.test.impl.client.deployment.event.GenerateDeployment;
import org.jboss.arquillian.core.api.Event;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.InstanceProducer;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.api.annotation.Observes;
import org.jboss.arquillian.core.api.event.ManagerStarted;
import org.jboss.arquillian.core.spi.EventContext;
import org.jboss.arquillian.core.spi.LoadableExtension;
import org.jboss.arquillian.test.spi.TestClass;
import org.jboss.arquillian.test.spi.annotation.ClassScoped;
import org.jboss.arquillian.test.spi.annotation.TestScoped;
import org.jboss.arquillian.test.spi.context.ClassContext;
import org.jboss.arquillian.test.spi.event.suite.Before;
import org.jboss.arquillian.test.spi.event.suite.BeforeClass;
public class ArquillianSuiteExtension implements LoadableExtension {
public void register(ExtensionBuilder builder) {
builder.observer(SuiteDeployer.class);
}
public static class SuiteDeployer {
private Class<?> deploymentClass;
private DeploymentScenario suiteDeploymentScenario;
@Inject
@ClassScoped
private InstanceProducer<DeploymentScenario> classDeploymentScenario;
@Inject
private Event<DeploymentEvent> deploymentEvent;
@Inject
private Event<GenerateDeployment> generateDeploymentEvent;
@Inject
// Active some form of ClassContext around our deployments due to assumption bug in AS7 extension.
private Instance<ClassContext> classContext;
private ProtocolMetaData cachedProtocolMetaData;
@TestScoped
@Inject
private InstanceProducer<ProtocolMetaData> testScopedProtocolMetaData;
public void startup(@Observes(precedence = -100) ManagerStarted event, ArquillianDescriptor descriptor) {
deploymentClass = getDeploymentClass(descriptor);
executeInClassScope(new Callable<Void>() {
public Void call() throws Exception {
generateDeploymentEvent.fire(new GenerateDeployment(new TestClass(deploymentClass)));
suiteDeploymentScenario = classDeploymentScenario.get();
return null;
}
});
}
public void deploy(@Observes final AfterStart event, final ContainerRegistry registry) {
executeInClassScope(new Callable<Void>() {
public Void call() throws Exception {
for (Deployment d : suiteDeploymentScenario.deployments()) {
deploymentEvent.fire(new DeployDeployment(findContainer(registry,
event.getDeployableContainer()), d));
}
return null;
}
});
}
public void undeploy(@Observes final BeforeStop event, final ContainerRegistry registry) {
executeInClassScope(new Callable<Void>() {
public Void call() throws Exception {
for (Deployment d : suiteDeploymentScenario.deployments()) {
deploymentEvent.fire(new UnDeployDeployment(findContainer(registry,
event.getDeployableContainer()), d));
}
return null;
}
});
}
public void blockDeployManagedDeployments(@Observes EventContext<DeployManagedDeployments> ignored) {
// We need to block DeployManagedDeployments event
}
public void storeProtocolMetaData(@Observes ProtocolMetaData protocolMetaData) {
cachedProtocolMetaData = protocolMetaData;
}
public void resotreProtocolMetaData(@Observes EventContext<Before> eventContext) {
testScopedProtocolMetaData.set(cachedProtocolMetaData);
eventContext.proceed();
}
public void restoreDeploymentScenario(@Observes EventContext<BeforeClass> event) {
// Setup the Suite level scenario as if it came from the TestClass
event.proceed();
classDeploymentScenario.set(suiteDeploymentScenario);
}
public void blockUnDeployManagedDeployments(@Observes EventContext<UnDeployManagedDeployments> ignored) {
// We need to block UnDeployManagedDeployments event
}
private void executeInClassScope(Callable<Void> call) {
try {
classContext.get().activate(deploymentClass);
call.call();
} catch (Exception e) {
throw new RuntimeException("Could not invoke operation", e);
} finally {
classContext.get().deactivate();
}
}
private Container findContainer(ContainerRegistry registry, DeployableContainer<?> deployable) {
for (Container container : registry.getContainers()) {
if (container.getDeployableContainer() == deployable) {
return container;
}
}
return null;
}
private Class<?> getDeploymentClass(ArquillianDescriptor descriptor) {
if (descriptor == null) {
throw new IllegalArgumentException("Descriptor must be specified");
}
String className = descriptor.extension("suite").getExtensionProperties().get("deploymentClass");
if (className == null) {
throw new IllegalArgumentException(
"A extension element with property deploymentClass must be specified in arquillian.xml");
}
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Could not load defined deploymentClass: " + className, e);
}
}
}
}
package org.jboss.arquillian.extension.suite;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.extension.suite.tests.Test1;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
public class Deployments {
@Deployment
public static WebArchive deploy() {
return ShrinkWrap.create(WebArchive.class)
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
.addPackage(Test1.class.getPackage());
}
}
org.jboss.arquillian.extension.suite.ArquillianSuiteExtension
package org.jboss.arquillian.extension.suite.tests;
import javax.enterprise.inject.spi.BeanManager;
import junit.framework.Assert;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(Arquillian.class)
public class Test1 {
@Test
public void shouldInject(BeanManager bm) {
System.out.println("Where are We?");
Assert.assertNotNull(bm);
}
}
@blabno
Copy link

blabno commented Apr 15, 2013

I've got it working with Drone! Check out my fork: https://gist.github.com/blabno/5387599

@blabno
Copy link

blabno commented Apr 25, 2013

@lynchmaniac
Copy link

Like MaikelNait i'm really newbie on Arquillian and i don't see how to launch all the test. I made a project with all the class, compilation is OK but in my Eclipse i didn't see how to launch all the test. With maven i have several deployements, one per test. So i do something wrong i think :-)
Is anyone can help me on this problem ?

@MaikelNait
Copy link

Thanks for the clarification blabno... the only thing I'm still missing is how to integrate this Suite plugin into my Arquillian configuration. I just need to copy all the source code into my project, and make it compile ?
Where to put the "LoadableExtension" file that refers to org.jboss.arquillian.extension.suite.ArquillianSuiteExtension ?
Thanks a lot in advance !

@MaikelNait
Copy link

Mmm... searching in Internet , looks like I may need to re-compile the whole Arquillian project , to get the Suite Extension registered in a file called /META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension ?!?!?

I can see this file inside arquillian-container-impl-base-1.0.3.Final.jar , and arquillian-config-impl-base-1.0.3.Final.jar,
with just one line : org.jboss.arquillian.container.impl.ContainerExtension

Can anyone just post a good documentation on how to get this Suit integrated into JBoss "for dummies" ???
Thanks a lot !!

@MaikelNait
Copy link

Ok, seems I just need to rename the "LoadableExtension" file as "org.jboss.arquillian.core.spi.LoadableExtension" , and place it under /src/main/resources/META-INF/services ( I'm using a Maven project )... Now the Suite if finally working ...!!! A good installation guide for this Extension would have been very nice .. but anyway, I finally figured it out ... phew !

@javaG
Copy link

javaG commented May 26, 2013

Hi Aslak,
I've managed to use the brute force suite solution, thank You for your well-done job. Everything works fine while one issue still exists: I see that when using the suite, arquillian deployment algorithm tries to instantiate ALL the singleton classes found on a classpath (WAR provided by the ShrinkWrap as part of @deployment). We have a large-scale project and classpath I'm trying to use is pretty big, but I'm not expecting this kind of eager loading during deployment.
My question is: is it supposed to work this way, or it's just a bug? BTW, when running arquillian tests without suite-extension, I don't see this problem at all, seems like lazy-loading model implemented then, as it supposed to be.
Thanks for your answer in advance.

@asceta
Copy link

asceta commented Jul 19, 2013

Welcome,

I am also using DBUnit extension configured as

    <extension qualifier="persistence-dbunit">
        <property name="datatypeFactory">org.dbunit.ext.h2.H2DataTypeFactory</property>
        <property name="excludePoi">true</property>
        <property name="caseSensitiveTableNames">false</property>
    </extension>

and I am facing problems during test execution:

Caused by: java.lang.NullPointerException
    at org.jboss.arquillian.persistence.core.deployment.PersistenceExtensionArchiveAppender.requiredLibraries(PersistenceExtensionArchiveAppender.java:81)
    at org.jboss.arquillian.persistence.core.deployment.PersistenceExtensionArchiveAppender.createAuxiliaryArchive(PersistenceExtensionArchiveAppender.java:58)
    at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.loadAuxiliaryArchives(DeploymentGenerator.java:209)
    at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.buildTestableDeployments(DeploymentGenerator.java:160)
    at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.createTestableDeployments(DeploymentGenerator.java:148)
    at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.generateDeployment(DeploymentGenerator.java:85)

...

at org.jboss.arquillian.extension.suite.ArquillianSuiteExtension$SuiteDeployer.executeInClassScope

Could you please help me how should I configure my env properly ?

@ingwarsw
Copy link

I just created my fork out of ITCrowd one.

I added extra Annotation for selecting global deployment.

https://github.com/ingwarsw/arquillian-suite-extension

@suikast42
Copy link

Hi Aslak,
if I run this extension with a single test ( for example mvn -Dtest=ATest test) then ARQ undeploy my app automatically. But if I run the suite with mvn test on my project everything works well but ARQ doesn't undeploy my app.

My environment:
ARQ version : 1.1.2.Final
App server: Jboss 7.2.0.Final

Did I miss something with the configuration?

@KrishnaKotari
Copy link

Hello Aslak,

I'm getting the following error while using this extension. I am using TestNG with Arrquillian

Caused by: java.lang.IllegalArgumentException: No active SuiteScoped Context to bind to
at org.jboss.arquillian.core.impl.ManagerImpl.bind(ManagerImpl.java:173)
at org.jboss.arquillian.core.impl.ManagerImpl.bindAndFire(ManagerImpl.java:235)
at org.jboss.arquillian.core.impl.InstanceImpl.set(InstanceImpl.java:74)
at org.jboss.as.arquillian.protocol.jmx.JMXProtocolAS7.getPackager(JMXProtocolAS7.java:45)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.buildTestableDeployments(DeploymentGenerator.java:169)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.createTestableDeployments(DeploymentGenerator.java:148)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.generateDeployment(DeploymentGenerator.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

Can you please help, what is it that I am missing. Configured the extension as shown above.

@KrishnaKotari
Copy link

Hello Asalak,

I have injected the suiteContext at the class level

@Inject
private Instance suiteContext;

and activated the contect in the method startup
suiteContext.activate();

With this it started working like a charm.

Thanks,
Krishna.

@perabello
Copy link

Hello Asceta,

I use Persistence and DBUnit extension too (defaultDataSource, defaultDataSeedStrategy, datatypeFactory, defaultDataSetLocation, etc) .
I do not find how to configure it integrated with ArquillianSuiteExtension.
Somebody is using it?

Thanks
Pere

@Steve973
Copy link

Steve973 commented Apr 6, 2016

Hello Aslak. Does this have to use a war? I want to run tests in Karaf, so I need to deploy bundles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment