Yes, you can set instance variables during any step type.
For example, given the the feature:
Feature: Instance variables
Scenario: Set instance variables during all steps
Given a given step sets the instance variable to "1"
Then the instance variable should be "1"
When a when step sets the instance variable to "2"
Then the instance variable should be "2"
Then a then step sets the instance variable to "3"
Then the instance variable should be "3"
And the step definitions:
Given /a given step sets the instance variable to "(.*)"/ do |value|
@your_variable = value
end
When /a when step sets the instance variable to "(.*)"/ do |value|
@your_variable = value
end
Then /a then step sets the instance variable to "(.*)"/ do |value|
@your_variable = value
end
Then /the instance variable should be "(.*)"/ do |value|
@your_variable.should == value
end
You will see that the scenario passes, which means that the when and then steps were successfully setting the instance variable.
In fact, the Given, When and Then are just aliases of each other. Just because you defined a step definition as a "Given", it can still be called as a "When" or "Then". For example, the above scenario will still pass if the step definitions used were:
Then /a (\w+) step sets the instance variable to "(.*)"/ do |type, value|
@your_variable = value
end
Then /the instance variable should be "(.*)"/ do |value|
@your_variable.should == value
end
Notice that the first "Then" step definition can be used by the "Given" and "When" in the scenario.
As to whether it is good practice to set instance variables in when and then steps, it is no worse than doing it in given steps. Ideally, none of your steps would use instance variables as they create step coupling. But, practically speaking, I have not run into significant issues by using the instance variables.