Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require ability to skip a specific step only but continue with rest of the steps of the scenario #1057

Closed
govindasharma1986 opened this issue Sep 21, 2022 · 5 comments

Comments

@govindasharma1986
Copy link

Is it possible to provide a functionality to:

  1. skip a step from environment function "before_step"
    for eg:
def before_step(context, step):
    if 'skip' in step.tags:
        step.skip('Marked as skip')
  1. skip a step from within the step_impl() function?
    for eg:
@behave.step('A step that I would like to skip conditionally')
def step_impl(context):
    if condition_met:
        context.scenario.current_step.skip()
@jenisys
Copy link
Member

jenisys commented Sep 22, 2022

Could you explain why you need such a functionality?

NOTES:

  • A step is not a taggable statement in Gherkin.
    Therefore, the approach above with step.tags will not work at all.

@govindasharma1986
Copy link
Author

govindasharma1986 commented Sep 25, 2022

I am automating a highly dynamic application.
The order of pages, number of pages, fields of each page and number of fields in each page are never fixed.

Hence, I decided to test each fields in separate scenario so that I can skip tests using tags(scenario level) for those fields which need not be covered for current screen.

environment.py
------------------
def before_scenario(context, scenario):
    if 'skip' in scenario.tags:
        scenario.skip("Scenario was Skipped. Reason: Scenario was marked as @skip")

    tags_with_fields = [x for x in scenario.tags if 'field-' in x or 'fields-' in x]

    if len(tags_with_fields) > 1 and 'fields-all' in tags_with_fields:
        scenario.skip('Scenario was Skipped. Reason: Cannot use `fields-all` along with `field-{field_name}')

    count_match = 0
    for field_name in context.property.fields_under_test:  # context.property.fields_under_test is a list and setup in config.ini file
        for tag in tags_with_fields:
            if field_name in tag:
                count_match += 1
    
    if len(tags_with_fields) - count_match > 0 and 'fields-all' not in tags_with_fields:
        scenario.skip('Scenario was Skipped. Reason: Fields covered in the scenario are out of scope for the given template')
    @field-mobile
    Scenario: Testing a particular field of the page
        ...

However, there are some tests(scenarios) which test for all fields in the page. The test would not be meaningful if I segregated them field wise. Hence I thought, if I could skip steps inside a scenario then it would have been very flexible to impl. such case.

    @field-zipcode
    Scenario: To validate that when user enters valid zipcode then city and state are auto-fetched
        Then In Local Storage, key "city" should have value "<city_name>"
        And In Local Storage, key "stateCode" should have value "<state_name>"
        @field-city  # would like to skip this step if field city is not present in current page. (sometime a field would never be visible in any page)
        And field "city" should have value "<city_name>"
        @field-state  # would like to skip this step if field state is not present in current page. (sometime a field would never be visible in any page)
        And field "state" should have value "<state_name"

Otherwise, my coverage would be less.

Let me know if this helps.

Note: I am not looking to reverse target scenarios/features using tags applied in steps.
for eg:
I don't intent to use tags at step in command line.
python -m behave --tags=@field-name

All I need is data in context.scenario.current_step.tags (within step definition) and step.tags (within before_step) and a step.skip() function so that I can use the code used in "before_scenario" in "before_step" (with some modification)

I understand your point and have raised a isuse in gherkin repo too.
Ref: cucumber/common#1949 (comment)

Also, tags at step level is also supported in SpecFlow (https://docs.specflow.org/projects/specflow/en/latest/Bindings/Scoped-Step-Definitions.html)

@govindasharma1986
Copy link
Author

@jenisys just a humble reminder.

As requested, the details are added.

Kindly let us know the way forward.

@jenisys
Copy link
Member

jenisys commented Oct 2, 2022

Mmh, I do not think that you need tags for steps in Gherkin.

  • Use scenarios to test the business rules behaviour (instead of verifying the expected outcome after the fact)
    NOTE: This comment is based on the provided example above.
  • The example above looks at least like that you are doing inspections/verifications after the fact.
    You can do that but that is not really what BDD is about.
  • Example above has too many unnecessary technical details (related: "Local Storage")
    HINT: If this is (always) important for you, check these details in the step implementation (that all constraints are met).

BETTER EXAMPLE: That tests the business rule (that was mentioned above).
The scenario title indicates the intention of the business rule.

# -- FILE: features/better_example.feature
...
Scenario Outline: Valid ZIP code automatically resolves city and state info
   Given a valid ZIP code "<zip-code> was provided
   Then the field "city" should have the value "<city>"
   And  the field "state" should have the value "<state>"

  Examples:  # TODO: Valid zip-code must be provided in the following table.
     | zip-code | city          | state |
     | xxxxx_1  | Chicago       | IL |
     | xxxxx_2  | San Francisco | CA |

OTHER SOLUTION 1: Generate features for what you need

Use a template engine (like Jinja2) to generate feature files with scenarios what you really need.
Feature files are basically text files.

OTHER SOLUTION 2: Use active-tags (skip-if on scenario) if ZIP code is entered outside of the scenario

Note that can be a "smell" that you are probably using scenarios in a wrong way.

The active-tag allows you to check at runtime if a precondition is met.
The scenario with this active-tag is automatically skipped, if the precondition fails (skip-if (not) semantics).

# -- FILE: features/example_with_active-tag.feature
@use.with_page_contains_field="zip-code"
Scenario: Provided ZIP code automatically resolves city and state info
   # HINT: User entered ZIP code outside of this scenario.
   Then the field "city" should have the value "<zip-code.city>"
   And  the field "state" should have the value "<zip-code.state>"
   ...

SEE: active-tags

OTHER SOLUTION 3: Use better step semantics

Be more concise with your steps and provide steps that gracefully ignore something (a field is not present).

# -- FILE: features/example.feature
...
  Scenario: Provided ZIP code automatically resolves city and state info
    Given the ZIP code "12345" is provided
     ...
     Then the existing field "city" should have the value "<city>"
# -- FILE: features/steps/field_steps.py

@then(u'a field "{field_name}" should have the "{expected_value}"')
def step_then_field_should_have_value(ctx, field_name, expected_value):
    actual_value = ctx.data_access_provider.get_field(field_name)
    assert actual_value == expected_value

@then(u'an existing field "{field_name}" should have the "{expected_value}"')
def step_then_existing_field_should_have_value(ctx, field_name, expected_value):
    if not ctx.data_access_provider.has_field(field_name):
        # -- CASE: MISSING FIELD, skip further step processing.
        # BUT: Step.status is PASSED; step is gracefully ignored because precondition is not met.
        return

    # -- REUSE: Other existing step implementation
    step_then_field_should_have_value(ctx, field_name, expected_value)

NOTES: On SpecFlow tags for step implementations as scoping mechanism
The SpecFlow mechanism is used to provide multiple step definitions/implementations for the same step-text in a feature file. This is not helping you with your current problem (IMHO).

@govindasharma1986
Copy link
Author

Thanks @jenisys for elaborate explanation.

Use scenarios to test the business rules behavior

The example above looks at least like that you are doing inspections/verifications

I understand you made a right point here. This automation framework was intended to be used for functional testing. But later was extended to include frontend tests (verification tests)

The solutions 2 & 3 would not help in this case. Since, I need to continue with the rest of the steps. Also, I only wish to skip them when UI QA has specified that they don't expect a particular field to be present in the page. (provided in the config.ini)

I will try solution 1 but it would have been lot easier if I could get tags info at step level.

Thanks again!

@jenisys jenisys closed this as completed Oct 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants