cmccarthyIrl / spring-cucumber-testng-parallel-test-harness

This project executes Cucumber tests sequentially or in parallel using TestNG, Spring, Cucumber, Java, Logback and Extent Reports to provide a basic test harness. Rest Assured and Selenium test examples are provided
MIT License
16 stars 6 forks source link
allure allure-reports cucumber extent-report extentreports github-actions io-cucumber java-17 logging parallel rest-api rest-assured rest-assured-framework selenium spark-reports spring-boot test-automation test-framework test-harness testng

Cucumber Automated Testing Framework

run

Index

Start | Maven | Quickstart |
Run | TestNG | Command Line | IDE Support | Java JDK | Troubleshooting |
Report | Configuration | Environment Switching | Spark HTML Reports | Logging |
Advanced | Before / After Hooks | JSON Transforms | Contributing |

Maven

The Framework uses Spring Boot Test, Cucumber , Rest Assured and Selenium client implementations.

Spring <dependencies>:


<dependecies>
    ...
    <dependency>
        <groupId>org.springframework.amqp</groupId>
        <artifactId>spring-rabbit</artifactId>
        <version>${spring-rabbit.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
    </dependency>
    ...
</dependecies>

Cucumber & Rest Assured <dependencies>:


<dependecies>
    ...
    <dependency>
        <groupId>io.rest-assured</groupId>
        <artifactId>rest-assured</artifactId>
        <version>${restassured.version}</version>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>${cucumber.version}</version>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-spring</artifactId>
        <version>${cucumber.version}</version>
    </dependency>
    <dependency>
        <groupId>io.cucumber</groupId>
        <artifactId>cucumber-testng</artifactId>
        <version>${cucumber.version}</version>
    </dependency>
    ...
</dependecies>

Selenium <dependencies>:


<dependecies>
    ...
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>${selenium-version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-server</artifactId>
        <version>${selenium-version}</version>
    </dependency>
    ...
</dependecies>

Quickstart

TestNG

By using the TestNG Framework we can utilize the Cucumber Framework and the @CucumberOptions Annotation Type to execute the *.feature file tests

Right click the WikipediParallelRunner class and select Run


@CucumberOptions(
        features = {
                "src/test/resources/feature"
        },
        plugin = {
                "pretty",
                "json:target/cucumber/report.json",
                "com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:"
        })
public class WikipediaParallelRunnerTest extends AbstractTestNGCucumberTests {

    @Override
    @DataProvider(parallel = true)
    public Object[][] scenarios() {
        return super.scenarios();
    }

}

Command Line

Normally you will use your IDE to run a *.feature file directly or via the *Test.java class. With the Test class, we can run tests from the command-line as well.

Note that the mvn test command only runs test classes that follow the *Test.java naming convention.

You can run a single test or a suite or tests like so :

mvn test -Dtest=WikipediaParallelRunnerTest

Note that the mvn clean install command runs all test Classes that follow the *Test.java naming convention

mvn clean install

IDE Support

To minimize the discrepancies between IDE versions and Locales the <sourceEncoding> is set to UTF-8


<properties>
    ...
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    ...
</properties>

Java JDK

The Java version to use is defined in the maven-compiler-plugin


<build>
    ...
    <pluginManagement>
        <plugins>
            ...
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
            ...
        </plugins>
    </pluginManagement>
    ...
</build>

Configuration

The AbstractTestDefinition class is responsible for specifying each Step class as @SpringBootTest and its @ContextConfiguration


@ContextConfiguration(classes = {FrameworkContextConfiguration.class})
@SpringBootTest
public class AbstractTestDefinition {
}

The FrameworkContextConfiguration class is responsible for specifying the Spring @Configuration, modules to scan, properties to use etc


@EnableRetry
@Configuration
@ComponentScan({
        "com.cmccarthy.api", "com.cmccarthy.common",
})
@PropertySource("application.properties")
public class FrameworkContextConfiguration {
}

Environment Switching

There is only one thing you need to do to switch the environment - which is to set <activeByDefault> property in the Master POM.

By default, the value of spring.profiles.active is defined in the application.properties file which inherits its value from the Master POM property <activeByDefault>


<profiles>
    ...
    <profile>
        <id>prod</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <activatedProperties>prod</activatedProperties>
        </properties>
    </profile>
    ...
</profiles>

You can then specify the profile to use when running Maven from the command line like so:

mvn clean install -DactiveProfile=github-headless

Below is an example of the application.properties file.

spring.profiles.active=@activatedProperties@

Extent Reports

The Framework uses Extent Reports Framework to generate the HTML Test Reports

The example below is a report generated automatically by Extent Reports open-source library.

Allure Reports

The Framework uses Allure Reports to generate the HTML Test Reports

The example below is a report generated by Allure Reports open-source library.

To generate the above report navigate to the root directory of the module under test and execute the following command

mvn allure:serve or mvn allure:generate (for an offline report)

Logging

The Framework uses Log4j2 You can instantiate the logging service in any Class like so

private final Logger logger=LoggerFactory.getLogger(WikipediaPageSteps.class);

you can then use the logger like so :

logger.info("This is a info message");
        logger.warn("This is a warning message");
        logger.debug("This is a info message");
        logger.error("This is a error message");

Before / After Hooks

The Logback logging service is initialized from the Hooks.class

As the Cucumber Hooks are implemented by all steps we can configure the @CucumberContextConfiguration like so :


@CucumberContextConfiguration
public class Hooks extends AbstractTestDefinition {

    private static boolean initialized = false;
    private static final Object lock = new Object();

    @Autowired
    private HookUtil hookUtil;
    @Autowired
    private DriverManager driverManager;

    @Before
    public void beforeScenario(Scenario scenario) {
        synchronized (lock) {
            if (!initialized) {
                if (!driverManager.isDriverExisting()) {
                    driverManager.downloadDriver();
                }
                initialized = true;
            }
        }
        driverManager.createDriver();
    }

    @After
    public void afterScenario(Scenario scenario) {
        hookUtil.endOfTest(scenario);
        WebDriverRunner.closeWebDriver();
    }
}

JSON Transforms

Rest Assured IO is used to map the Response Objects to their respective POJO Classes


<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>3.0.0</version>
</dependency>

Troubleshooting

Contributing

Spotted a mistake? Questions? Suggestions?

Open an Issue