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?
It is actually quite simple once you know that there is a
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
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
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) #=> 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
puts scenario.location.file.split(File::SEPARATOR) #=> "mobile"