kiran
kiran

Reputation: 243

Reusing Cucumber SpringBoot Tests for local and remote integration tests

I have below setup

I am able to run cucumber test with below configuration to test SpringBoot Application running locally using maven failsafe plugin.

Note: The configuration uses @SpringBootTest annotation to start the SubjectUnderTest(SUT) before the running the Test.

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.example.bdd.stepdefs")
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME,
    value = "pretty," +
     "html:target/tests-reports/report.html," +
     "json:target/tests-reports/report.json," +
     "junit:target/tests-reports/cucumber-junit.xml,")
@CucumberContextConfiguration
@ActiveProfiles("local")
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class FunctionalIT {
} 

My Requirements:

  1. Reuse the same cucumber tests to validate the springboot application started using the @SpringBootTest during the maven integration test, as well as testing the deployed application on remote environments (e.g. qa, prod)
  2. Leverage Spring application-env.properties files and profiles for the environment specific configuration.
  3. Only start the minimum required Spring ApplicationContext depending on the test to be run against the local app (@SpringBootTest) vs remote app (No @SpringBootTest annotation).
  4. Specify the active profile as needed e.g. -Dspring.profiles.active=local or -Dspring.profile.active=qa. And only that profile should be used by the Spring.

I tried few options without much success so far, I faced below issues:

  1. Tried createing another test class for remote environments without @SpringBootTest annotation, but @CucumberContextConfiguration is only allowed on single class.
  2. If I separate all cucumber config in its own class, the junit is not running the cucumber tests. Aparently @CucumberContextConfiguration needs to be applied on @SpringBootTest or @ContextConfiguration only.

Any idea how to get the setup working for the above requirements ?

Upvotes: 1

Views: 1114

Answers (1)

kiran
kiran

Reputation: 243

I solved the problem with the below changes.

  1. Custom Annotation for common cucumber configuration
package com.example.bdd.config;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features")
@CucumberContextConfiguration
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME,
    value = "pretty," +
     "html:target/tests-reports/report.html," +
     "json:target/tests-reports/report.json," +
     "junit:target/tests-reports/cucumber-junit.xml")
public @interface CucumberTestSuite {
    
}
  1. Test runner for testing SUT (setup using @SpringBootTest) for local/ci builds.
package com.example.bdd.env.test;

@CucumberTestSuite
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, 
    value = "com.example.bdd.stepdefs," + 
            "com.example.bdd.env.test")
@ContextConfiguration(initializers = ApplicationInitializer.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
public class ComponentIT {
}

# Note: ApplicationInitializer takes care of spinning up required dependencies (mocks/stubs) for the Component Testing. 
  1. Test runner for testing SUT in a remote QA environment
package com.example.bdd.env.acceptance;

@CucumberTestSuite
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, 
    value = "com.example.bdd.stepdefs," + 
            "com.example.bdd.env.acceptance")
@ContextConfiguration
@TestPropertySource("classpath:application-${env}.properties")
@ActiveProfiles("${env}")
public class AcceptanceIT {
}
  1. different maven profiles in pom.xml
  <profiles>
    <profile>
      <id>default</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <configuration>
              <excludes>
                <exclude>**/*AcceptanceIT.java</exclude>
              </excludes>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
    <profile>
      <id>acceptance-tests</id>
      <properties>
        <skip.surefire.tests>true</skip.surefire.tests>
      </properties>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <configuration>
              <includes>
                <include>**/*AcceptanceIT.java</include>
              </includes>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>

Now for running

  1. mvn clean verify runs unit tests and ComponentIT by default (for local and CI environment)
  2. mvn clean verify -P acceptance-tests -Denv=qa runs AcceptanceIT tests on qa environment, like wise -Denv=stage or -Denv=prod to run tests against the stage and prod environments respectively.

Upvotes: 0

Related Questions