Search code examples
spring-bootcucumber-serenity

Spring Boot + Serenity + Cucumber for Rest API Integration Test


I am using gradle project and I have followed the CucumberSerenity with Spring Boot integration approach by using this link: https://medium.com/@manu.me/bdd-simplified-with-springboot-b56ffdcadb2b When i run the gradle task cucumber, I get below error message

            SEVERE: Exception while executing pickle
            java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: org/openqa/selenium/internal/Killable
                    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
                    at java.util.concurrent.FutureTask.get(FutureTask.java:192)
                    at io.cucumber.core.runtime.Runtime.run(Runtime.java:108)
                    at net.serenitybdd.cucumber.cli.Main.run(Main.java:31)
                    at net.serenitybdd.cucumber.cli.Main.main(Main.java:19)
            Caused by: java.lang.NoClassDefFoundError: org/openqa/selenium/internal/Killable
                    at java.lang.ClassLoader.defineClass1(Native Method)
                    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
                    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
                    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
                    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
                    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
                    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
                    at java.security.AccessController.doPrivileged(Native Method)
                    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
                    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
                    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
                    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
                    at net.thucydides.core.webdriver.SupportedWebDriver.<clinit>(SupportedWebDriver.java:31)
                    at net.thucydides.core.configuration.WebDriverConfiguration.lookupSupportedDriverTypeFor(WebDriverConfiguration.java:49)
                    at net.thucydides.core.configuration.WebDriverConfiguration.getDriverType(WebDriverConfiguration.java:33)
                    at net.thucydides.core.webdriver.SerenityWebdriverManager.getDefaultDriverType(SerenityWebdriverManager.java:178)
                    at net.thucydides.core.webdriver.SerenityWebdriverManager.getWebdriver(SerenityWebdriverManager.java:116)
                    at net.thucydides.core.webdriver.ThucydidesWebDriverSupport.getDriver(ThucydidesWebDriverSupport.java:147)
                    at net.thucydides.core.webdriver.ThucydidesWebDriverSupport.getPages(ThucydidesWebDriverSupport.java:208)
                    at net.serenitybdd.core.Serenity.getPages(Serenity.java:188)
                    at net.serenitybdd.core.Serenity.getDefaultDependencyInjectors(Serenity.java:84)
                    at net.serenitybdd.core.Serenity.getDependencyInjectors(Serenity.java:74)
                    at net.serenitybdd.core.Serenity.resetDependencyInjectors(Serenity.java:67)
                    at net.serenitybdd.core.Serenity.done(Serenity.java:167)
                    at cucumber.runtime.SerenityObjectFactory.stop(SerenityObjectFactory.java:31)
                    at io.cucumber.core.runner.Runner.disposeBackendWorlds(Runner.java:175)
                    at io.cucumber.core.runner.Runner.runPickle(Runner.java:70)
                    at io.cucumber.core.runtime.Runtime.lambda$run$2(Runtime.java:100)
                    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
                    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
                    at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:243)
                    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
                    at io.cucumber.core.runtime.Runtime.lambda$run$3(Runtime.java:100)
                    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
                    at java.util.stream.SliceOps$1$1.accept(SliceOps.java:204)
                    at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359)
                    at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
                    at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
                    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
                    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
                    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
                    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
                    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
                    at io.cucumber.core.runtime.Runtime.run(Runtime.java:101)
                    ... 2 more
            Caused by: java.lang.ClassNotFoundException: org.openqa.selenium.internal.Killable
                    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
                    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
                    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
                    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
                    ... 46 more
            
            Aug 13, 2020 12:22:47 PM io.cucumber.core.runtime.Runtime run
            SEVERE: Exception while executing pickle
            java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: Could not initialize class net.thucydides.core.webdriver.SupportedWebDriver
                    at java.util.concurrent.FutureTask.report(FutureTask.java:122)
                    at java.util.concurrent.FutureTask.get(FutureTask.java:192)
                    at io.cucumber.core.runtime.Runtime.run(Runtime.java:108)
                    at net.serenitybdd.cucumber.cli.Main.run(Main.java:31)
                    at net.serenitybdd.cucumber.cli.Main.main(Main.java:19)

build.gradle

  • Please refer the task cucumber which i am trying to execute from command prompt/terminal

            buildscript {
                repositories {
                    mavenLocal()
                }
                dependencies{
                    classpath('net.serenity-bdd:serenity-gradle-plugin:2.2.9')
                }
            }
    
            // Apply Plugins & Custom Configurations
            apply plugin: 'java'
            apply plugin: 'maven'
            apply plugin: 'org.springframework.boot'
            apply plugin: 'net.serenity-bdd.aggregator'
    
            // Set values from properties
            processResources {
                filesMatching('**/*.properties') { expand(project.properties) }
            }
    
            // Following two block required for spring boot plugin as no main class
            bootRepackage {
                enabled = false
            }
    
            project.afterEvaluate {
                if (!project.plugins.hasPlugin(ApplicationPlugin)) {
                    project.plugins.apply(ApplicationPlugin)
                    project.tasks.withType(CreateStartScripts) { CreateStartScripts task ->
                        task.enabled = false
                    }
                }
            }
            // *************************************
    
            // Java Properties and Depenedencies
            sourceCompatibility = 1.8
            targetCompatibility = 1.8
    
    
            //Application Test Source Set and Dependencies
            configurations {
                //providedRuntime
                applicationTestCompile.extendsFrom testCompile {
                    all*.exclude group: 'com.assertthat', module: 'selenium-shutterbug'
                }
                applicationTestRuntime.extendsFrom testRuntime
            }
    
            ext {
                applicationTestBase= "src/applicationTest"
            }
    
            sourceSets {
                applicationTest {
                    java.srcDir "$projectDir/$applicationTestBase/java"
                    resources {
                        srcDirs = ["$applicationTestBase/resources"]
                    }
                    compileClasspath += sourceSets.main.compileClasspath //+ sourceSets.test.compileClasspath
                    runtimeClasspath += sourceSets.main.runtimeClasspath //+ sourceSets.test.runtimeClasspath
                }
            }
    
            dependencies {
    
                applicationTestCompile "org.springframework.boot:spring-boot-starter-test"
                applicationTestCompile "com.jayway.restassured:rest-assured"
                    //database dependencies
                applicationTestCompile "org.springframework.boot:spring-boot-starter-data-jpa"
                applicationTestCompile "com.oracle:ojdbc7"
    
                //Serenity & Cucumber Dependencies
                applicationTestCompile 'io.rest-assured:rest-assured:3.3.0'
                compile(group: 'com.jayway.jsonpath', name: 'json-path', version:'2.4.0') {
                    exclude(module: 'slf4j-api')
                }
                compile ('net.serenity-bdd:serenity-gradle-plugin:2.2.9') {
                    exclude group: 'com.google.inject', module:'guice'
                    exclude group: 'io.cucumber', module: 'cucumber-core'
                    exclude group: 'io.cucumber', module: 'cucumber-java'
                }
                compile ('net.serenity-bdd:serenity-core:2.2.9'){
                    exclude group: 'io.cucumber', module: 'cucumber-core'
                }
                applicationTestCompile ('net.serenity-bdd:serenity-cucumber5:2.2.5')
                applicationTestCompile 'net.serenity-bdd:serenity-single-page-report:2.2.9'
                applicationTestCompile 'net.serenity-bdd:serenity-model:2.2.9'
                applicationTestCompile 'net.serenity-bdd:serenity-junit:2.2.9'
                applicationTestCompile 'net.serenity-bdd:serenity-stats:2.2.9'
                applicationTestCompile 'net.serenity-bdd:serenity-screenplay:2.2.9'
                applicationTestCompile 'net.serenity-bdd:serenity-rest-assured:2.2.9'
                applicationTestCompile 'net.serenity-bdd:serenity-screenplay-webdriver:2.2.9'
                applicationTestCompile group: 'org.seleniumhq.selenium', name: 'selenium-api', version: '3.141.59'
            //    applicationTestCompile group: 'org.seleniumhq.selenium', name: 'selenium-api', version: '2.29.1' -- internal/killable
                applicationTestCompile group: 'org.seleniumhq.selenium', name: 'selenium-remote-driver', version: '3.14.0'
                applicationTestCompile group: 'org.seleniumhq.selenium', name: 'htmlunit-driver', version: '2.37.0'
                applicationTestCompile group: 'org.seleniumhq.selenium', name: 'selenium-chrome-driver', version: '3.141.59'
                applicationTestCompile group: 'org.seleniumhq.selenium', name: 'selenium-safari-driver', version: '3.141.59'
                applicationTestCompile group: 'org.seleniumhq.selenium', name: 'selenium-support', version: '3.141.59'
                applicationTestCompile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.14.0'
                applicationTestCompile 'org.seleniumhq.selenium:selenium-server:3.14.0'
                applicationTestCompile group: 'org.springframework', name: 'spring-jms', version: '5.1.6.RELEASE'
                applicationTestCompile "com.ibm.mq:com.ibm.mq.allclient:9.0.4.0"
                applicationTestCompile group: 'org.assertj', name: 'assertj-core', version:'3.6.2'
                applicationTestCompile group: 'org.apache.commons', name: 'commons-csv', version:'1.5'
                applicationTestCompile group: 'org.apache.maven.plugins', name: 'maven-failsafe-plugin', version: '3.0.0-M5'
    
    
            }
    
            task cucumber() {
                dependsOn assemble, testClasses
                doLast {
                    javaexec {
                        main = "net.serenitybdd.cucumber.cli.Main"
                        classpath = configurations.applicationTestRuntime + sourceSets.main.output + sourceSets.test.output
                        args = ['--plugin', 'pretty', '--glue', 'gradle.clean.aggregate', 'src/applicationTest/resources']
                    }
                }
            }
    
            // Application Test Runners
            task runApplicationTest(type: Test) {
                outputs.upToDateWhen { false }
                include '**/*Runner.java'
                systemProperties(System.getProperties())
    
                testClassesDir = project.sourceSets.applicationTest.output.classesDir
                classpath = project.sourceSets.applicationTest.runtimeClasspath
                reports.html.destination = project.file("$reports.html.destination/applicationTest")
                reports.junitXml.destination = project.file("$reports.junitXml.destination/applicationTest")
                maxHeapSize = "2G"
                jvmArgs '-XX:MaxPermSize=256m'
            }
    

Runner.java - I have used run with as "CucumberWithSerenity" and used @ActiveProfiles to link with my other

          import io.cucumber.junit.CucumberOptions;
          import net.serenitybdd.cucumber.CucumberWithSerenity;
          import org.junit.runner.RunWith;
          import org.springframework.test.context.ActiveProfiles;
          
          @RunWith(CucumberWithSerenity.class)
          @CucumberOptions(features="./src/applicationTest/resources/features/sample.feature", glue={"definitions"}, tags={"@test"},strict = true)
          @ActiveProfiles("test")
          public class Runner{
          }
  

Definition File

           @SpringBootTest
           public class SampleDefinitions{
           
            @Given("^user sends message\"([^\"]*)\"$")
               public void user_sends_message(String usermessage){
                   System.out.println("usermessage -->"+usermessage);
               }
           }

Solution

  • This happens when classes aren't available at runtime.

    You are using custom sourcesets i.e. applicationTest which is not configured properly to run cucumber task.

    One solution is to change your class path in cucumber task and include the main source sets to use applicationTest classes

    1. cucumber task
    classpath = sourceSets.applicationTest.runtimeClasspath
    
    1. sourcesets
    main {
        compileClasspath += applicationTest.output
        runtimeClasspath += applicationTest.output
    }
    

    This should work.