Determine the feature directory in Cucumber hooks

Problem

Today’s Stack Overflow question, “Is it possible to know from which folder cucumber scenario is running?” by Den Silver, was looking to apply hooks based on a feature file’s folder. While I can see the merit of this approach, using tags, as suggested by Jeff Price in a similar question, might be a better choice.

At any rate, I was curious. Can you determine a feature file’s location?

Solution

It is actually quite simple once you know that there is a #location method:

Before do |scenario|
  scenario.location.file
  #=> "features/mobile/test.feature"
end

Finding the Solution

Providing the solution is great, but sometimes I wonder if explaining how to find the solution would be useful. For those that are interested, here is how I got to the solution.

I knew that the basic form of a hook looked like:

Before do |scenario|
end

A scenario is part of a feature, so the first step was to see what methods scenario had. To do that, one needs to know its class:

puts scenario.class
#=> Cucumber::RunningTestCase::Scenario

Looking through the Scenario class documentation at RubyDoc.info, none of the methods seemed related to a feature. Then I noticed that the #name method, which I had used before, was not mentioned. The method still worked, so how was it defined?

Following the docs “Defined in”, the source code for the class can be found on GitHub. The Scenario is a SimpleDelegator, which means that undefined methods, such as #name, would be sent to another object – specifically @test_case:

class Scenario < SimpleDelegator
  def initialize(test_case, result = Core::Test::Result::Unknown.new)
    @test_case = test_case
    @result = result
    super test_case
  end

@test_case could provide other useful methods, so I needed to determine what class it was:

puts scenario.instance_variable_get(:@test_case).class
#=> Cucumber::Core::Test::Case

Unfortunately, this class was not defined in the Cucumber RubyDoc or in the source code pages previously used. Looking at the gems installed by Cucumber, I noticed that there was also a Cucumber-Core gem. Browsing the Cucumber-Core docs, I found the class. There was the #name method that I was looking for. As well, it had a potentially useful method called #location:

puts scenario.location
#=> "features/mobile/test.feature"

Great. I just needed to split the path to get the sub-directory (as the question just wanted “mobile”):

puts scenario.location.split(File::SEPARATOR)[1]
#=> NoMethodError: undefined method `split' for #<Cucumber::Core::Ast::Location::Precise>

Oh. Apparently the returned value was not just a String. Exploring the Ast::Location::Precise documentation, I found the needed #file method:

puts scenario.location.file.split(File::SEPARATOR)[1]	
#=> "mobile"
Advertisements
This entry was posted in Cucumber and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s