How do I skip a test in the behave python BDD framework?

Eric picture Eric · Apr 7, 2016 · Viewed 11.2k times · Source

I'm juggling code branches that were partly done a few months ago, with intertwined dependencies. So the easiest way to move forward is to mark failing tests on a particular branch as pending (the rspec way) or to be skipped, and deal with them after everything has been merged in.

In its final report, behave reports the number of tests that passed, the # failed, the # skipped, and the # untested (which are non-zero when I press Ctrl-C to abort a run). So behave as a concept of skipped tests. How do I access that?

Answer

Louis picture Louis · Mar 10, 2017

If you want to control things at the command line, then you do what Tymoteusz Paul suggested in another answer. In brief, you can use whatever tag you want to mark your features and scenarios and then use --tags to select or deselect features and scenarios based on the tags you used. The documentation gives the example of marking slow scenarios with @slow and then using behave --tags=slow to run just the slow tests, or using behave --tags=-slow to exclude the slow tests. Reading the documentation is recommended to learn what syntax --tags allows.

By the method above, you could use @skip and do behave --tags=-skip. This will exclude everything marked with @skip but it is annoying to have to include the extra argument with every invocation. Couldn't @skip just by itself tell Behave to skip, without requiring any arguments on the command line?

If you want a @skip tag that will skip features and scenarios marked with it, without requiring an additional argument, then, as of Behave 1.2.5, you must build the functionality into your environment.py file. Contrarily to what this answer suggests, it is not built-in. We add the functionality like this:

def before_feature(context, feature):
    if "skip" in feature.tags:
        feature.skip("Marked with @skip")
        return

    # Whatever other things you might want to do in this hook go here.

def before_scenario(context, scenario):
    if "skip" in scenario.effective_tags:
        scenario.skip("Marked with @skip")
        return

    # Whatever other things you might want to do in this hook go here.

The argument to the .skip methods is the reason for skipping.

I always use .effective_tags to perform tag testing in scenarios. The .effective_tags field inherits tags that were set on the feature. In the case at hand here it makes no difference because if the feature had @skip then forcibly the scenarios in it will be skipped already. However, I prefer to stick to the general principle that tag checks in scenarios should use .effective_tags so that tag inheritance works.


Wait! Doesn't the tutorial say that @skip is built-in?

No, the tutorial presents things a bit misleadingly because it gives a list that shows @skip next to @wip. @wip is built-in so @skip is built-in too right? No, they are in a list is of "Predefined or often used tags". @skip is merely "often used". It is often used because using the word "skip" in an informative way to mark something as skipped. It does not entail that the tag is built into Behave.