-
-
Save aslakknutsen/3975179 to your computer and use it in GitHub Desktop.
| <?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); | |
| } | |
| } |
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 !
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.
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.executeInClassScopeCould you please help me how should I configure my env properly ?
I just created my fork out of ITCrowd one.
I added extra Annotation for selecting global deployment.
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?
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.
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.
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
Hello Aslak. Does this have to use a war? I want to run tests in Karaf, so I need to deploy bundles.
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 !!