0

I have the following multi module project structure

root | | ---- project A with arquillian testcases | | ---- project B builds war and runs same tests with different deployment config

I want to run my testcases with two different deployment configurations.

In project A I run the testcases with Arquillian. Then, I run the same testcases with the testcontainers framework after the war is built in project B.

What is the best approach to achieve this? I see here basically two alternatives:

  1. Duplicate the same testcases in project A and project B
  2. Having a base class containing the testcases which is extended by the specific classes which override the deployment config methods

With method 2, which normally I would prefer, I see some issues:

  • The testcase base class needs to be shared across multiple projects and I read in different discussion that it is a bad practice to share test code across projects.

So what do you think? What would you guys do? If you know other ways to share the testcases except of duplicating the code or extending, please let me know.

Thanks in advance.

Example method 1:

Project A contains following testclass:

@RunWith(Arquillian.class)
public class YTest
{
@ArquillianResource
private URL webappUrl;

/**
 * @return {@link JavaArchive}
 */
@Deployment(name = "myservice")
public static Archive<?> createTestArchive()
{
    final WebArchive archive = ShrinkWrap
        .create(WebArchive.class, "myservice.war")
        .addClasses(X.class, Y.class);

    return archive;
}

private WebTarget webTarget()
{
    return ClientBuilder.newClient().target(webappUrl.toExternalForm());
}

@Test
public void whenPostServiceShouldReturn200() throws IOException
{
    final Response response = webTarget()
        .path("/myservice")
        .request()
        .header("Content-Type", "application/json")
        .post(Entity.entity(TestDataGeneration.generatePayload, MediaType.APPLICATION_JSON_TYPE));

    assertEquals(200, response.getStatus());
}
}

Project B contains following testclass:

public class Y2Test
{
private static final Logger LOGGER = LoggerFactory.getLogger(Y2Test.class);

@ClassRule
public static GenericContainer<?> webAppContainer = new GenericContainer<>(
    new ImageFromDockerfile().withFileFromPath("..", new File("..").toPath()))
        .withLogConsumer(new Slf4jLogConsumer(LOGGER))
        .withExposedPorts(9080);


private WebTarget webTarget()
{
    return ClientBuilder
        .newClient()
        .target(
            "http://"
                + webAppContainer.getContainerIpAddress()
                + ":"
                + webAppContainer.getMappedPort(9080)
                + "/provisioning-service");
}

@Test
public void whenPostServiceShouldReturn200() throws IOException
{
    final Response response = webTarget()
        .path("/myservice")
        .request()
        .header("Content-Type", "application/json")
        .post(Entity.entity(TestDataGeneration.generatePayload(), MediaType.APPLICATION_JSON_TYPE));

    assertEquals(200, response.getStatus());
}
}

Example method 2:

Project A contains following testclasses:

public abstract class YTestCases
{
abstract WebTarget webTarget();

@Test
public void whenPostMyServiceCorrectlyShouldReturn200() throws IOException
{
    final Response response = webTarget()
        .path("/registerphone")
        .request()
        .header("Content-Type", "application/json")
        .post(null);

    assertEquals(200, response.getStatus());
}
}

and

@RunWith(Arquillian.class)
public class YTest extends YTestCases
{
@ArquillianResource
private URL webappUrl;

/**
 * @return {@link JavaArchive}
 */
@Deployment(name = "myservice")
public static Archive<?> createTestArchive()
{
    final WebArchive archive = ShrinkWrap
        .create(WebArchive.class, "myservice.war")
        .addClasses(A.class, B.class);

    return archive;
}

@Override
WebTarget webTarget()
{
    return ClientBuilder.newClient().target(webappUrl.toExternalForm());
}
}

Project B contains following testclass which now only extends the basetestcases class

public class Y2T extends YTestCases
{
private static final Logger LOGGER = LoggerFactory.getLogger(Y2T.class);
@ClassRule
public static GenericContainer<?> webAppContainer = new GenericContainer<>(
    new ImageFromDockerfile().withFileFromPath("..", new File("..").toPath()))
        .withLogConsumer(new Slf4jLogConsumer(LOGGER))
        .withExposedPorts(9080);

@Override
WebTarget webTarget()
{
    // cassandra.getContainerIpAddress();
    // cassandra.getMappedPort(9042);
    return ClientBuilder
        .newClient()
        .target(
            "http://"
                + webAppContainer.getContainerIpAddress()
                + ":"
                + webAppContainer.getMappedPort(9080)
                + "/myservice");
}
}
finrod
  • 521
  • 8
  • 21
  • Not exactly sure about what your projects do, but you can export your tests as a dependency (a JAR) and then reference that in any number of places. If I were in your place I'd create a little sample project (with multiple modules) for this with a "dummy" test. – Kohányi Róbert Jul 10 '18 at 08:11
  • Since the code to be shared is in test, I would need to export them as test-jar, and then add it as test dependency in the other project which I read is bad practice. – finrod Jul 10 '18 at 08:13
  • Well, not sure if it's bad practice or not (I haven't done such a thing yet). It's hard to answer your question since you ask "how'd you guys do?". I'd advise you to produce a [Minimal Working Example](https://stackoverflow.com/help/mcve) (in this case an example with a sample project where you either implement your 1. or 2. idea). That would help me to answer it, because although it's an interesting question (for me) it supposes too many unknowns for me to seriously dive into. – Kohányi Róbert Jul 10 '18 at 08:29
  • I already tested both approaches, both are working. Its a little bit difficult to share it, but I will try. – finrod Jul 10 '18 at 08:30

0 Answers0