Cucumber-jvm: CucumberOptions glue with two packages having the same start causing DuplicateStepDefinitionException

Created on 25 Apr 2016  ·  19Comments  ·  Source: cucumber/cucumber-jvm

We have general Cucumber steps in a shared Maven project that is defined as Maven dependency for the tested project where the Cucumber files reside.

When having a junit test definition similar to this:

package com.example;

import org.junit.runner.RunWith;

import cucumber.api.CucumberOptions;
import net.serenitybdd.cucumber.CucumberWithSerenity;

@RunWith(CucumberWithSerenity.class)
@CucumberOptions( plugin = { "json:target/Ok.json" },
features = "classpath:features/Ok.feature",
glue = {"com.example.ready",
"com.example.readymade"})
public class DuplicateOkIT
{
}

And running with the Maven dependency the test fails with:
cucumber.runtime.DuplicateStepDefinitionException: Duplicate step definitions in com.example.readymade.NotWorkingSteps.test_step(Integer,String,int) in ...

When I import the project to same Eclipse workspace the same works fine.

Could this be some problem in the clue code instantiation when running with Maven?

I have observed similar also when having package and subpackage defined in glue. Then both the subpackage and its parent causes subpackages steps to produce this same exception. That one I can overcome with not defining the subpackage.

In this case I need to define the glue differently when running in eclipse (e.g. when developing further steps) and when running in Maven build.

Dependency versions used:


net.serenity-bdd
serenity-core
1.1.31
test


net.serenity-bdd
serenity-junit
1.1.31
test


net.serenity-bdd
serenity-spring
1.1.31
test


net.serenity-bdd
serenity-cucumber
1.1.5
test


info.cukes
cucumber-junit
1.2.4
test


info.cukes
cucumber-java
1.2.4
test


info.cukes
cucumber-jvm
1.2.4
pom
test


info.cukes
gherkin-jvm-deps
1.0.3
test

Most helpful comment

The most fruitfull approach would be to create a PR that updates the documentation accordingly.

All 19 comments

Try to run your tests using the same Cucumber.options using cucumber.api.cli.Main class.

Hi,

having the same issue here. I am running cucumber tests with gradle and gradle-cucumber plugin that eventually executes cucumber.api.cli.Main with the following options:
--glue classpath:com.some.package.test.automation --glue classpath:com.some.package.test.automation.stepDefinitions

If only parent package is specified no exception is thrown.

Here is an executable example:
bug_995.zip

Run it with:
$ gradle cucumber --info

Cucumber command includes:
--glue classpath:a --glue classpath:a.b

And throws:
Exception in thread "main" cucumber.runtime.DuplicateStepDefinitionException: Duplicate step definitions in a.b.StepDefsB.b() in file:/home/ben/dev/bug_995/build/classes/cucumber/ and a.b.StepDefsB.b() in file:/home/ben/dev/bug_995/build/classes/cucumber/ at cucumber.runtime.RuntimeGlue.addStepDefinition(RuntimeGlue.java:33) at cucumber.runtime.java.JavaBackend.addStepDefinition(JavaBackend.java:153) at cucumber.runtime.java.MethodScanner.scan(MethodScanner.java:68) at cucumber.runtime.java.MethodScanner.scan(MethodScanner.java:41) at cucumber.runtime.java.JavaBackend.loadGlue(JavaBackend.java:89) at cucumber.runtime.Runtime.<init>(Runtime.java:90) at cucumber.runtime.Runtime.<init>(Runtime.java:68) at cucumber.runtime.Runtime.<init>(Runtime.java:64) at cucumber.api.cli.Main.run(Main.java:35) at cucumber.api.cli.Main.main(Main.java:18)

I'm having exactly same issue with Ben Smith

@bensmith87 I'm not sure if this is a bug, at least for me it doesn't looks like it.
As far as I understand the glue will retrieve all stepdefs below the package specified, so whe you use:
--glue classpath:com.package --glue classpath:com.package.subpackage
It would be redundant, as the first glue will already include the subpackages/stepsdefs on it.

From my understanding this is not a bug as I use this as an advantage on my tests, specifying a package to retrieve all subpackages/stepdefs to be included on my execution.

The few cases where I had to specify different packages as in your example I made something like:
--glue classpath:com.package.subpackageone --glue classpath:com.package.subpackagetwo
This assures that two different sets of stepdefs will be loaded, but it doesn't look fancy or anything.

I do not think it is a bug to recursively include packages, but I believe it is a bug to throw an exception if the same package is included twice.

Can you please try with the project from the following example.
https://drive.google.com/open?id=0B4SgyzyvwKhiN3NCeFVpdXlBcWc

Run from RunCukesTest.java

I am segregating my step definitions in to different packages:-

  • stepDefinition.bussiness
  • stepDefinition.generic

This is my runner class

@RunWith(Cucumber.class)
@CucumberOptions(
dryRun=true,
strict=true,
features={"src/test/resources/FeatureFiles/Sprint38.feature"},
glue={"stepDefinition"},
tags={"@Automated"},
plugin={"json:src/test/resources/Report/Automated_Test_Execution_Report.json"}
)
public class ScriptRunner {
}

it works fine.

@avikashg
Can you please check this comment: https://github.com/cucumber/cucumber-jvm/issues/1127#issuecomment-303681531

In case if the hooks file is outside of step definitions package, package of the hooks file needs to be mentioned in the glue code like
glue={"helpers","stepDefinitions"}

Here helpers have the hooks file. See if this helps

@avikashg
I tried to reproduce your scenario here and no error was displayed, could you please create a project with the error that you are having?
I believe that your stepDefinition package has more Steps files under it (beyond the two you mentioned), and this may be causing the duplicate step definition error.

Thanks @Jiwari and @nagarjun64
It was my mistake. It is perfectly fine now.

@avikashg How did you resolve it.

@bensmith87 Did you fix your issue?

@TuireHolappa Did you manage to fix this, or is it still an issue for you? If so, please let us know and create a minimal project that demonstrates the problem, or let us know that you're working on it. Otherwise if I don't hear back from you, I'll close this ticket in a week.

I'm observing the same behaviour as @bensmith87

I managed to work around it by making sure there were no Java files in the parent directories of the steps files, I moved them to a sibling directory.

For me the behaviour that glue={"a"} also includes the sibling packages (e.g. a.b) seems not wrong. But this recursive behaviour should be explicit mentioned in the documentation. Currently this point is missed.

  -g, --glue PATH                        Where glue code (step definitions, hooks
                                         and plugins) are loaded from.

Another solution could be to remove sibling packages from the glue property if a parent is found. But this might cover a misconfiguration/typo/... if this would not a be logged as a warning.

I totally agree with @SubOptimal. This behavior should be explicitly documented. I was just attempting to look through the documentation to see if the glue path was recursive and I'm finding out about that behavior here.

The most fruitfull approach would be to create a PR that updates the documentation accordingly.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings