Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to organize the specs definition in Cucumber?

We are considering to use Cucumber on our project for acceptance testing.

When we write a scenario in a Cucumber feature, we write a list of Given, When and Then statements.

As we use cucumber-jvm project, the Given, When and Then statement are related to Java methods in (JUnit) classes.

I want to know what is the best organization for the code related to Given / When / Then in the project structure. My main concern is the maintenance of the cucumber tests on a big project, where the number of scenario is quite important, and especially regarding the items that are shared between features.

I can see at least 2 main approaches:

  1. Each feature is related to it's own JUnit class. So if I have a foo/bar/baz.feature cucumber file, I will find the releated foo.bar.Baz JUnit class with the adequate @Given, @When and @Then annotated methods.

  2. Separate @Given, @When and @Then methods into "thematic" classes and packages. For example, if in my cucumber scenario I have a statement Given user "foo" is logged, then the @Given("^user \"([^\"]*)\" is logged$") annotated method will be located in the foo.user.User class method, but potentially, the @When method used later in the same cucumber scenario will be in a different Java class and package (let say foo.car.RentCar).

For me, the first approach seems good in the way that I can easily do the relation between my cucumber features and my Java code. But the drawback is that I can have a lot of redundancies or code duplication. Also, it may be hard to find a possible existing @Given method, to avoid to recreate it (the IDE can help, but here we are using Eclipse, and it does not seem to give a list of existing Given statement?).

The other approach seems better essentially when you have Given conditions shared among several cucumber feature, and thus I want to avoid code duplication. The drawback here is that it can be hard to make the link between the @Given Java method and the Given cucumber statement (maybe, again, the IDE can help?).

I'm quite new to cucumber, so maybe that my question is not a good question, and with time and experience, the structure will be self-evident, but I want to get good feedbacks on its usage...

Thanks.

like image 862
Romain Linsolas Avatar asked Oct 17 '12 09:10

Romain Linsolas


People also ask

How do you organize step definitions?

We recommend arranging step definitions by domain concept or system interface, while arranging feature files by business functionality. This is more cohesive than arranging by feature, since the body of step definitions face towards the application itself and allows things to change naturally over time.

How do you define step definitions in cucumbers?

Add a Step Definition file 1) Create a new Class file in the 'stepDefinition' package and name it as 'Test_Steps', by right click on the Package and select New > Class. Do not check the option for 'public static void main' and click on Finish button. Take a look at the message in the console window.

How will you define both feature and step definition file in Cucumber?

Steps definition file stores the mapping between each step of the scenario defined in the feature file with a code of function to be executed. So, now when Cucumber executes a step of the scenario mentioned in the feature file, it scans the step definition file and figures out which function is to be called.


2 Answers

I would suggest grouping your code according to the objects it refers to, similar to option #2 you presented in your question. The reasons being:

  • Structuring your code based on how and where it's being used is a big no-no. It's actually creating coupling between your feature files and your code.
    Imagine such a thing in your product's code- the SendEmail() function wouldn't be in a class called NewEmailScreenCommands, would it? It would be in EmailActions or some such.
    So the same applies here; structure your code according to what it does, and not who uses it.

  • The first approach would make it difficult to re-organize your feature files; You'd have to change your code files whenever you change your feature files.

  • Keeping code grouped by theme makes DRYing it much easier; you know exactly where all the code dealing with the user entity is, so it's easier for you to reuse it.

On our project we use that approach (i.e BlogPostStepDefinitions class), with further separating the code, if the class gets too large, to types of steps (i.e BlogPostGivenStepDefinitions).

like image 198
J. Ed Avatar answered Oct 05 '22 23:10

J. Ed


We have also started using Cucumber-JVM for acceptance testing and have similar problems with organising code. We have opted to have 1 step definition class for each feature. At the moment this is fine as the features we are testing aren't very complex and quite separate, there is very little overlap in our features.

The second approach you mentioned would be better I think, but it is often challenging to tie together several different step definition classes for a single scenario. I think the best project structure will become clearer once you start adding more features and refactor as normal.

In the meantime here is an Eclipse plugin for cucumber,

https://github.com/matthewpietal/Eclipse-Plugin-for-Cucumber

it has syntax highlighting as well as a list of existing available steps when writing a feature.

like image 27
The Cat Avatar answered Oct 06 '22 01:10

The Cat