I am new to Cucumber and I am using cucumber-java. The cucumber feature files look great. However, the reuse of step definitions really gets in the way about organizing the step definition code. The most intuitive way for me to organize the step definitions is just to follow the organization of the feature files, namely, one class for one feature. However, this way is screwed if there are two identical steps in two feature files, because you will miss one step in one of the classes, which breaks the coherence of the entire structure. However, I cannot convince myself to use other ways right now. So, what is a sensible way to organize step definitions when using cucumber-java?

Thank you very much.

No correct solution


Start with the way you are already doing and once you recognize that a step is reused, move it a class ReUsableSteps or something. This way, if a step does not exist in its class then it should be in ReUsableSteps. Just a thought.

You can have a separate package as placeholder for classes that defines common steps. Add that package as glue.

The best way to use cucumber is to minimize the duplication of step definition. What we should focus on while writing step definition is to avoid any code specific to a class or functionality in steps method of StepDefinition class because that way it can not be generalized, it should have common code which can be used for different steps and code for propagating to separate class for which step is meant and specific logic for each step should reside in separate class. This way we can avoid duplication.

Example:- Suppose we have component feature file which contains step "Component A has to receive responses", its implementation class is ComponentStepDefinition class, when we implement this in step definition we should not use any logic for iterating or calculating responses for component A there, rather pass the value to a class which performs A related task, in this way to you have to implement "Component B has to receive responses" then same step definition can be used and B's logic will be in another class.

Sort your step definitions by common functionality as related to your domain. They do not have to be linked to specific feature files.

For example, one of our features is to provide our partners with scores (how are they doing on our platform). We have several step definitions related to those scores in a ScoreSteps file. We might have other steps related to partners, those would be in a PartnerSteps file. This also makes it easier to use helper methods related to a certain domain object.

These files would be completely different for you, depending on your domain.

Also note that your IDE will know if a step has already been defined or not (at least, in IntelliJ steps that are undefined are marked in yellow).

Reusing steps is critical for maintenance reasons. That doesn't mean trying to shoehorn steps here and there, but finding a balance between reusability and understanding. As already said above, arranging them into a Common or Reusable package is a pretty good idea. This is something to be done as you go, because you don't always know whether a step is going to be reused or not. In this sense, frequent refactoring of step definitions will be quite normal. Actually it is an indicator of code aliveness, so don't hesitate to make any changes to get the test scenarios clear enough and the testing code as clean as possible. It is just the same well-known coding principles, applied to testing.

One thing that helped me with this task was a utility class (actually it was a set of classes) that allowed me to know which steps and steps definitions exist, the class in which the step definition is defined, the feature files and test scenarios that make use of them, etc. You can even implement advanced options such as searching for steps or steps definitions that contain such and such keywords, or getting to know the step definitions that are not used any longer, etc. Kind of a dictionary.

It can be achieved by either processing the java classes that belong into the 'glue' folder and gather all the regular expressions associated to the gherkin annotations, or by parsing the feature files with the help of a Gherkin parser. Although you may want to have both approaches implemented, as they are not mutually-exclusive; on the contrary, they complement each other.

This is something you may not need when having just a few test scenarios. But as this number grows bigger and bigger, you will find such a mechanism really valuable.

This can be done easily by using multiple test runner classes for multiple feature files.

You can create same steps for different features as long as you are specifying the glue code in your test runner. Glue will make sure the cucumber checks only in the path specified for the steps during execution.

Then you can maintain a suite xml configuration like TestNG.xml for running which all features I want.

@CucumberOptions(monochrome = true, features = "src/test/java/com/abc/batch/xyz/payout/bbq/monthly",
    plugin = { "pretty", "html:target/cucumber-html-reports" }, strict = true, glue = {"" })

The way I organize my cucumber tests are like I have a java package for a cucumber feature where I will have the steps definitions class, feature file, test data files for those tests and Hooks class.

The advantage is that when I try to look for the step definitions in the step class, I know where exactly to look at and the chances of getting a step definition conflict is zero unless you have added the same definition in that package twice.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top