3

I try to add Cucumber to test my Java project, I wrote a feature file:

Feature: I visit the website

    Scenario: I read the home page
        Given I am on the "home" page

I wrote a class to run the cukes

import cucumber.api.CucumberOptions;

/**
 *  See https://cucumber.io/docs/reference/jvm#junit-runner
 */
@RunWith(Cucumber.class)
@CucumberOptions(glue = {"classpath:stepdefinitions"},features = {"src/test/features"})
public class RunCukesTest {
}

And the step definition: (I've the feeling that I'm missing annotations here)

package com.myproject.test.stepdefinitions;

import cucumber.api.PendingException;
import cucumber.api.java8.En;

public class WebSteps implements En {

    public WebSteps() {
        Given("^I am on the \"([^\"]*)\" page$", (String page) -> {
            System.out.println(page);
        });
    }
}

So whatever I put in glue = {}, the step is not found. With glue = {"classpath:stepdefinitions"} or glue = {"stepdefinitions"} the test is green and I have the "You can implement missing steps with the snippets below" message (the step is not found). If I put the full package path, either glue = {"com.myproject.test.stepdefinitions"} or glue = {"classpath:com.myproject.test.stepdefinitions"}

I have a stack trace:

java.lang.NoClassDefFoundError: org/springframework/test/context/ContextHierarchy
    at cucumber.runtime.java.spring.SpringFactory.annotatedWithSupportedSpringRootTestAnnotations(SpringFactory.java:198)
    at cucumber.runtime.java.spring.SpringFactory.dependsOnSpringContext(SpringFactory.java:187)
    at cucumber.runtime.java.spring.SpringFactory.addClass(SpringFactory.java:61)
    at cucumber.runtime.java.JavaBackend.loadGlue(JavaBackend.java:96)
    at cucumber.runtime.Runtime.<init>(Runtime.java:91)
    at cucumber.runtime.Runtime.<init>(Runtime.java:69)
    at cucumber.runtime.Runtime.<init>(Runtime.java:65)
    at cucumber.api.junit.Cucumber.createRuntime(Cucumber.java:78)
    at cucumber.api.junit.Cucumber.<init>(Cucumber.java:58)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:29)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:21)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:26)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createUnfilteredTest(JUnit4TestLoader.java:84)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:70)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:43)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.ClassNotFoundException: org.springframework.test.context.ContextHierarchy
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 26 more

Here is what I added in my pom.xml:

    <!-- Tests with cucumber -->
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-java8</artifactId>
        <version>1.2.3</version>
        <scope>test</scope>
    </dependency>
    <!-- Dependency Injection with Spring https://cucumber.io/docs/reference/java-di#spring -->
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-spring</artifactId>
        <version>1.2.3</version>
        <scope>test</scope>
    </dependency>
    <!-- JUnit Runner : https://cucumber.io/docs/reference/jvm#running -->
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>1.2.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

My project uses Spring 4.

Fla
  • 536
  • 6
  • 23

3 Answers3

3

You are not missing an annotation. You are missing content in your classpath.

I would start with simplifying the setup bit. You are using Maven and therefore I would place the sample feature file in the same package as the RunCukesTest class. If RunCukesTest lives in the package com.myproject.test, then would this mean:

src/test/resources/com/myproject/test

I think you currently are using src/test/features for your feature files. That is not a path that is included in your classpath by Maven. Not unless you explicit adds it, which you don't show us if you do or not.

Moving the feature file should allow you to remove the @CucumberOptions and remove one potential source of problems.

I would then implement the step in a class in the same package as RunCukesTest. I would use the snippets provided when you run your build, mvn test. And finally do the system.out.println() you have to really know that the expected method indeed is executed. The snippets are probably the pre Java 8 way of doing things.

With this working, I would try to get the Java 8 steps working.

More details can be seen in the source code for Cucumber: https://github.com/cucumber/cucumber-jvm/tree/master/java8/src/test/java/cucumber/runtime/java8/test

Thomas Sundberg
  • 4,098
  • 3
  • 18
  • 25
  • Hi Thomas and thank you for your answer. I moved the feature file to avoid to specify feature={}. I also moved the WebSteps from `test.stepdefinitions` to `test` to be in the same package than `RunCukesTest`. The `@CucumberOptions` is now dropped, and I'm back with my `java.lang.NoClassDefFoundError: org/springframework/test/context/ContextHierarchy` stack trace. – Fla Jan 27 '16 at 08:59
  • The snippets provided are the Java 8 one, because I include `cucumber-java8` in my `pom.xml`, not `cucumber-java`. I want to precise I run the test with right click inside `RunCukesTest` and `Run as JUnit Test` – Fla Jan 27 '16 at 09:01
  • The class def not found exception is due to a missing dependency in your Maven project. I don't use Spring so I don't know which dependency you need to add, but the problem is clear. Your classpath doesn't contain a needed class. – Thomas Sundberg Jan 30 '16 at 10:24
0

The error suggests you are missing Spring dependencies; you must address this before looking into why the step definitions are not found. You haven't posted the full list of deps in your project, but you should at least have these dependencies in your pom:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>4.1.6.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>4.1.6.RELEASE</version>
</dependency>

You may need to update the version.

Sébastien Le Callonnec
  • 26,254
  • 8
  • 67
  • 80
  • I already had `spring-core` (of course) and `spring-context`. I added `spring-context-support`, ran Maven Update and clean the project, but I still have the stack trace. I think I'll try to remove `cucumber-spring` at the moment, to see if it solves the problem. – Fla Jan 27 '16 at 09:19
0

Add a plugin to Runnerclass plugin={"pretty","html:format"}. I use as below:

@RunWith(Cucumber.class)
@CucumberOptions(
  plugin={"pretty","html:format"},      
  features = "Features/name.feature",glue={"stepdefinitions path in eclipse"})

public class RunnerClass {
}

also when you want to parametrise HOME variable, it should be like < Home > instead of Home. Also not sure why did you add String parameter in step definition, please delete and try.

cbuchart
  • 10,847
  • 9
  • 53
  • 93
vijay
  • 11
  • 3