One option to consider is just using rspec and NOT using Cucumber.
This is obviously a fairly drastic step so let me give more detail and how to address your specific issues, as just "don't use it" isn't a very helpful or practical answer.
Some organizations use rspec, some use cucumber and some use both. I have observed several organization adopt Cucumber, only to abandon it within a year and just use rspec.
I have seen this happen for two principles reasons:
1) Cucumber takes maintenance. Just as with all software and testing. I have seen companies struggle to maintain their testing suites when they include cucumber. As the tests grow the amount of maintenance overhead also grows and becomes increasingly burdensome and slows down development.
2) Cucumber takes discipline. The idea is to involve business analysts (or at least business analysis) in describing the companies procedures. The problem here is that this still needs to be done using a disciplined programmatic approach that may not be clear to a non-programmer or someone not used to organizing the definition of functionality is this manner. When you need to start explaining concepts like DRY to them this shows the problem. Yes DRY isn't that hard - but it's part of the programming world. Next you'll be talking about dependency inversion - how it's simple, just parameters, and so it goes on.
My approach is to try and use the best of both.
I tend to use rspec and not use cucumber, however I use the following approach which lends itself heavily to Cucumber:
- Feature are written with Given, When, Then in mind, not the actual words but the meaning
- The above Given, When, Then sections[*1] are separated by a blank line
- One assertion per test[*2]
- Use rspecs
before :each and nested levels of tests to run shared setup for multiple tests
[*1] This is the Gherkin syntax.
[*2] This rule is intentionally broken for feature specs due to the slowness of using real browsers. Chrome headless (version 59) may change this.
Example for the login you mentioned:
describe "a set of tests" do
before :each do
it "test1" do
it test2" do
One final note: Even without this, I assume that you have created methods such as '
login_to_app' that at least DRYs up the login part so that you just call
login_to_app in all tests that require it, rather than duplicating the actual login steps themselves in each test.
My final comment is that in terms of being able to figure out which tests need which setup steps, there is no easy solution or tools to help with this currently. I feel this is mostly because this requires human knowledge and expertise to determine what tests need what setup and how best to organize tests, nested tests, shared setup, etc.