odiszapc
odiszapc

Reputation: 4109

What is the best way to access Cucumber's instance variables form nested classes inside steps?

It's a simple question. I have Cucumber steps, for example:

Given /We have the test environment/ do
  @user = # Create User model instance
  @post = # Create Post model instance
  # etc...
end

In the Then step I'm using my own classes, they simplify the process of testing:

Then /all should be fine/ do
  # MyValidatorClass has been defined somwhere in features/support dir
  validator = MyValidatorClass.new
  validator.valid?.should be_true
end

Inside the MyValidatorClass instance, I deal with the above instance variables @user, @post, etc.

What is the best and simpliest way to access Cucumber variables from MyValidatorClass class instance?

class MyValidatorClass
  def valid?
    @post
    @user
  end
end

Now I have manually passed all arguments to MyValidatorClass instance:

validator = MyValidatorClass.new @user, @post

But I think this purpose is bad. I need something more transparent, because we are using Ruby, that why!

What is the best way to do this?

Upvotes: 5

Views: 4341

Answers (2)

Andrei Botalov
Andrei Botalov

Reputation: 21096

Instance variables that are defined in World scope are available only inside World. Step definitions belong to World. You should put MyValdatorClass inside World by World{MyValdatorClass.new}. After that instance variables defined previously in this scenario's stepdefs will become available in this class and other step definitions in the same scenario.

Some other thoughts that refer to your question:


If you have a step Given we have the test environment, then:

  • you will duplicate it in all feaures
  • your features are becoming longer and less pleasant to read because of those unnecessary for current feature's reading details
  • setting up not needed environment details will take some time

Easier way to create instances is to add helper method that will create them for you:

module InstanceCreator
  def user
    @user ||= # Create user instance in World
  end
  #etc
end
World(InstanceCreator)

Then you just use this user when you need it (without any @ or @@).

If you need something else besides creating instances, use hooks

Your scenarios should be natural reading. You shouldn't spoil them with steps that you need just to get your automation layer work.


It's better to have regex starting from ^ and ending with $. Without it step definition becomes too flexible. Your first step definition will match also Given We have the test environment with some specifics.

Upvotes: 2

odiszapc
odiszapc

Reputation: 4109

I have found the posible soultion. You just should migrate from instance variables to class variables:

Given /We have the test environment/ do
  @@user = # Create User model instance
  @@post = # Create Post model instance
  # etc...
end

Then /all should be fine/ do
  # MyValidatorClass has been defined somwhere in features/support dir
  validator = MyValidatorClass.new
  validator.valid?.should be_true
end

...    

class MyValidatorClass
  def valid?
    @@post
    @@user
  end
end

Upvotes: 0

Related Questions