How do I conditionally skip a scenario in Cucumber

2019-06-18 09:46发布

How do I conditionally skip a scenario?

For example, I wish to continue a scenario only if certain conditions are met, but I do not want it to register as a failure if it's not present.

标签: ruby cucumber
6条回答
三岁会撩人
2楼-- · 2019-06-18 10:26

I am tagging my scenarios, and then in my "step_definitions/hooks.rb" file, I have something like this:

Before('@proxy') do 
  skip_this_scenario unless proxy_running?
end

scenario.skip_invoke! which was mentioned in another answer seems to be deprecated.

查看更多
女痞
3楼-- · 2019-06-18 10:32

This is an issue I had. The tests I write are against a UI that has a constantly changing BE database that I am currently unable to have static data in. This means that some times it is possible that there is no data for the test. Not a pass not a fail, just unable to run.

The way that I found to work best was to invoke a cucumber pending.

example test:

Scenario: Test the application
  Given my application has data
  When I test something
  Then I get a result

example step def:

Given /^my application has data$/ do
  pending unless application.has_data?
end

These are the kind of results I can see:

201 scenarios (15 pending, 186 passed)
1151 steps (15 pending, 1136 passed)

It's worth noting that I have extra debugging and have these tests tagged so that at any time I can run these pending tests again.

Hope this helps, Ben.

查看更多
男人必须洒脱
4楼-- · 2019-06-18 10:37

Short answer: Why?

Long answer: Cucumber is meant to be used to model the requirements of an end-user (typically customer). The features are meant to detail the list of scenarios in which they are expected to be used in, and the expected results that the features should exhibit when exposed to those scenarios. Those requirements are not conditional - the customer will want them to work all of the time. If Y should not work when X is disabled, then you put that in the Given clause, because that is a Scenario of Y.

Given sets up the state of your Scenario to something known. You are saying, "Given" these known variables, When I do this, Then this should happen. By 'conditionally skipping' a Cucumber clause, you are saying a feature should only work when another feature works.. in which case, why don't you put that in your given clause?

As far as I know, it is possible to skip steps (although I can't remember why), I'm merely questioning why you would want to do that. The only reason I can see you wanting to do this is to say that module A shouldn't work when module B is disabled. But your modules rely on each other then your code is coupled - which is exactly what Cucumber / TDD / BDD encourages you to avoid.

Example I posted in the comments:

Feature: Slicing Bread
  As a hungry person
  I want to be able to slice bread
  so that I can eat smaller bits of my sandwich and enjoy it much more

Scenario: Slicing bread in half
  Given a knife and a piece of bread
  When I cut the bread in half
  Then I should have two pieces of bread

This scenario would not hold up if the 'Given' requirements failed. If the 'Given' requirements failed - for example, Given a spoon and some soup, you can't possibly expect to end up with two pieces of bread at the end of it. Therefore you are trying to test undefined behaviour. Are you trying to say that if you have a spoon and some soup that cutting bread should no longer work in this universe? No? Then why skip steps?

查看更多
Rolldiameter
5楼-- · 2019-06-18 10:38

Please see this solution which truly skips the scenario instead of trowing a pending error:

Before do |scenario|
      scenario.skip_invoke!
   end
查看更多
一纸荒年 Trace。
6楼-- · 2019-06-18 10:40

You could check the condition before you start cucumber, then use a profile that would skip the scenarios with certain tags. Put this in your cucumber.yml:

default: --tags ~@wip --tags ~@broken --no-source --color 
limited: --tags @core --tags ~@wip --tags ~@broken --no-source --color

Replace @core with whatever tag you use for the cukes you want to run (or use ~ to exclude cukes). Then run the limited profile from a shell script that checks the conditions:

cucumber -p limited
查看更多
太酷不给撩
7楼-- · 2019-06-18 10:41

For anyone still looking for an answer to this: Apart from using pending, or a specific profile to skip scenarios with certain tags, there are at least 2 more ways to achieve this.

I can understand why you would need this, as I had a similar problem and got a solution, hence worth sharing. In my case, I had a piece of functionality expected to be available on 3/10 devices, and expected to be not available on the remaining 7.

Caveats with using 'pending' to skip:

  • Since the tests and code were implemented, it didn't feel right to mark steps as pending.
  • It caused confusion, as it was difficult to distinguish really pending scenarios from skipped but marked pending scenarios at the end of a run
  • Some CI jobs (Jenkins/Hudson) might be configured to fail for pending scenarios, hence causing more trouble.

So, I rather wanted to just skip them during execution depending on the condition of which browser is being used. I also didn't want to have too many profiles specific to certain browsers/devices

Solution:

  1. Use cucumber.yml to skip tagged scenarios conditionally

Here's a known ignored interesting fact about cucumber (from https://github.com/cucumber/cucumber/wiki/cucumber.yml):

The cucumber.yml file is preprocessed by ERb; this allows you to use ruby code to generate values in the cucumber.yml file

  • Building on this, tag your scenarios with something unique, say @conditional

    • At the beginning of your cucumber config (cucumber.yml), apply your conditional logic outside of any profiles mentioned:

      <% included = (ENV['BROWSER'] =~ /chrome/) ? "-t @conditional" : "-t ~@conditional" %>

      included is just a variable, which will have a value of tags to include/exclude depending on the condition

    • Now use this conditional variable in the default profile default: <%= included %>

So now your default profile will use the included/excluded tests as identified by your conditional logic.

  1. (More complicated and not elegant) Use rake tasks for cucumber execution:

Conditionally choose tags to include/exclude within your rake task, and pass them to cucumber execution.

Hope this helps.

查看更多
登录 后发表回答