-
-
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); | |
} | |
} |
Perhaps stick this in the showcase for now?
sure, the showcase is a good location
Hi Aslak,
Is this a workaround for ARQ-567? If so can you please elaborate little bit on how to use this?
thank you,
raj
Hi Aslak,
Thanks for uploading this code. We have updated our framework to use this but we are running into issues with TestNG tests. The following example runs correctly when the class is not extending Arquillian(simple TestNG test class) and when is it extending Arquillian but ArquillianSuiteExtension is NOT used.
But when ArquillianSuiteExtension is used, testTwo() fails "expected [This is my updated message] but found [This is my message]".
I updated the example to print out the test instance. Without the ArquillianSuiteExtension, both tests print out is the same. But when ArquillianSuiteExtension is used, they are different.
import org.jboss.arquillian.testng.Arquillian;
import org.testng.Assert;
import org.testng.annotations.Test;
public class SimpleTestNGTest extends Arquillian
{
private String message= "This is my message";
@Test
public void testOne()
{
System.out.println(this);
Assert.assertEquals( "This is my message", message );
message = "This is my updated message";
}
@Test(dependsOnMethods = "testOne")
public void testTwo()
{
System.out.println(this);
Assert.assertNotNull( message );
Assert.assertEquals( message, "This is my updated message" );
}
}
@jaygarala this is not really related to the test suite or not. Arquillian will reexecute the whole test framework lifecycle incontainer for each @test on the client side.
@Before
@Test
-> @Before (in container)
-> @Test (in container)
-> @After (in container)
@After
As long as you don't define a @deployment method, the execution is not moved to the container, and 'everything' works as normal TestNG. By adding the ArquillianSuiteExtension, you're probably adding a Deployment (via the Deployments class), which then moves the default behavior to be incontainer execution.
Hi Aslak,
Thank you for responding. The test case I posted is to simplify the issue we are experiencing. Here is a more realistic in-container test.
The createUser() will created the User and verifyUser() will assert user is non null. In each test it will print out the object instance to sout.
import org.jboss.arquillian.testng.Arquillian;
import org.testng.Assert;
import org.testng.annotations.Test;
public class SimpleTestNGTest extends Arquillian
{
private User user;
@Test
public void createUser()
{
user = createUserInTheDb();
System.out.println( this );
}
@Test(dependsOnMethods = "createUser")
public void verifyUser()
{
System.out.println(this);
Assert.assertNotNull( user );
}
private User createUserInTheDb()
{
// pseudo create user
return new User( "123", "qwe" );
}
class User
{
private String userName, password;
User( String userName, String password )
{
this.userName = userName;
this.password = password;
}
}
}
When the test runs in container, here is the test output.
SimpleTestNGTest@7fa0898d
SimpleTestNGTest@2e68f296
java.lang.AssertionError: expected object to not be null
Note the instances are different. Under regular TestNG test and non-suite Arquillian test they are the same. Wondering what is causing the class instances to be different while in suite Arquillian test.
Hi Aslak,
Have you put this in the showcase area as has been suggested? - That way I think I can understand a little bit better. Right now I'm able to make the suite work but when I use it along with the Seam2 extension it runs into trouble.
Thanks in advance,
raj
@rajin there was a bug in the seam2 extension that caused some issues, this should be fixed in 1.0.0.Final-SNAPSHOT. Try fetching it from the JBoss nexus repo: https://repository.jboss.org/nexus/content/groups/public/
Hi Aslak,
Super! - that was it.
Thanks a bunch
raj
Hi Aslak,
I'm trying to use this extension along with the Seam2 extension but I seem to be running into trouble when starting the test. I am getting the following exception:
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:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:90)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:135)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:115)
at org.jboss.arquillian.core.impl.EventImpl.fire(EventImpl.java:67)
at org.drools.guvnor.arquilliansuite.ArquillianSuiteExtension$SuiteDeployer$1.call(ArquillianSuiteExtension.java:55)
at org.drools.guvnor.arquilliansuite.ArquillianSuiteExtension$SuiteDeployer$1.call(ArquillianSuiteExtension.java:53)
at org.drools.guvnor.arquilliansuite.ArquillianSuiteExtension$SuiteDeployer.executeInClassScope(ArquillianSuiteExtension.java:95)
My test is a TestNG test, but I've also tried with the JUnit runner and get the same results. Any ideas on what may be going wrong here?
Silly question : How can I get this extension running for my Arquillian tests ? How to compile the classes , and where to put them ?
I'm pretty new to Arquillian , and I can't find good guides about how to use Extensions ( other than the Persistence extension which is available as a maven dependency ).
What is the main difference between this extension and the JRebel one ?
Are they targeted to fulfill the same goal ? ( JRebel extension seems already available as a jar )
Thanks !
MaikeInait: JRebel extension is for development time (i.e. you should not use it on Jenkins). Suite extension is meant to run tests from several classes in single deployment (i.e. Jenkins could do 1 deployment with all tests instead of 100, not mentioning server start/stop)
Aslak: Does this run with Drone?
I've got it working with Drone! Check out my fork: https://gist.github.com/blabno/5387599
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 ?
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 !
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 !!
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.executeInClassScope
Could 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.
Call cycle: