Your scenarios are not duplicates, they are similar. To reduce the cost of the similarity make the scenarios as simple as possible.
So with your example the only difference is the environment you login into so your scenarios could be
Scenario: Login into env1
Given I am an env 1 user
When I login
Then I should see my landing page
Scenario: Login into env1
Given I am an env 2 user
When I login
Then I should see my landing page
...
Note how my scenarios are equivalent but much simpler than your examples, and only the Given is different.
By taking this approach and using helper methods to do the work you can have a much reduced codebase to do this work.
module LoginStepHelper
def create_user(env: )
...
end
def login(user: )
visit user.homepage
fill_in_login_details(user: user)
submit_form
end
def fill_in_login_details
fill_in user.email
...
end
def should_see_landing_page
expect ...
end
end
Given 'I am an env 1 user' do
@i = create_user(env: 1)
end
Given 'I am an env 2 user' do
@i = create_user(env: 2)
end
When 'I login' do
visit @i.login_page
login(user: @i)
end
Then ...
...
and thats pretty much all you need. Note: the following
- no scenario outlines necessary
- no params for step defs
- no hard config of password/user ids in feature
- use of global @i variable to store the test user
- test user know their login page, password email, name etc
- the only thing we've specified is the login page (1,2 or 3)
Of course there is a bit more infrastructure to set up depending on how you configure your environments etc.. But the point holds. If your scenarios and step definitions are very simple and you delegate HOW things are done to helper methods, then step definition duplication and scenario duplication become almost none issues (apart from runtime cost).
All of the above code is ruby, I'm pretty sure you can translate this to other languages.
You have to do a bit of tricky stuff behind the scenes to get the test-user to work
Hope that helps
All best