pythoncucumberpython-behave

Python Behave optional argument


I am trying to write a test using Cucumber (Behave). The 'given' statement needs to be able to take an optional parameter, it is for verifying the contents in a string.

An example feature syntax for both scenarios would be:

Given Verify text "this is a test string"
When String validation is "success"
Then Store form contents.

Given Verify text "this is a test string" exclude "test,trial,hello"
When String validation is "success"
Then Store form contents.

The step I tried to implement was:

# Verify text "this is a test string" exclude "test,trial,hello"

@given('Verify text "{text_to_clean}" {?: exclude "{excluded}')
def step_verify_text(context, text_to_clean, excluded):
    context.verified = verify_string(text_to_clean, excluded)

How do I do this? I tried using the optional symbol of ?, but I can't figure it out. What do I need to do to use optional parameters?

I am using a Mac on macOS Catalina.


Solution

  • Note: feature file name and file name inside steps folder should match.

    for eg: if feature file name is question_regex.feature then file name inside steps folder should be question_regex.py

    1. Option - Regex Parser

    features/question_regex.feature

    Feature: regex question
    
      Scenario: first question regex
        Given Verify text "this is a string"
        Then parameter "excluded" is ""
    
      Scenario: second question regex
        Given Verify text "this is a test string" exclude "test,trial,hello"
        Then parameter "excluded" is "test,trial,hello"
    

    features/steps/question_regex.py

    from behave import use_step_matcher, given, when, then
    use_step_matcher("re")
    
    @given('Verify text "(?P<text_to_clean>.*?)"((?: exclude )"(?P<excluded>.*?)")?')
    def step_verify_text(context, text_to_clean, excluded):
        context.myvar = excluded
    
    @then('parameter "(?P<name>.*?)" is "(?P<result>.*?)"')
    def step_verify_text(context, name, result):
        return getattr(context, name, None) == result
    

    2. Option - CFParse

    features/steps/question_cfparse.feature

    Feature: cfparse question
    
      Scenario: first question cfparse
        Given Verify text 2 "this is a test string"
        Then normal parameter "excluded" is ""
    
      Scenario: second question cfparse
        Given Verify text 2 "this is a test string" exclude "test,trial,hello"
        Then normal parameter "excluded" is "test,trial,hello"
    
      Scenario: second question cfparse
        Given Verify text 3 "this is a test string" exclude "hi,hello,I"
        Then normal parameter "excluded" is "hi,hello,I"
    

    features/steps/question_cfparse.py

    from behave import given, when, then, use_step_matcher, register_type
    import parse
    use_step_matcher("cfparse")
    
    @parse.with_pattern(r'(?: exclude )"(.*?)"')
    def parse_word_optional(text):
        print(text)
        return text.strip()
    
    @parse.with_pattern(r'(?: exclude )')
    def parse_exclude(text):
        return text.strip()
    
    @parse.with_pattern(r'"(.*?)"')
    def parse_word_between_quote(text):
        return text.strip()
    
    register_type(my1_=parse_exclude)
    register_type(quote_word=parse_word_between_quote)
    register_type(my_=parse_word_optional)
    
    @given('Verify text 2 "{text_to_clean}"{ignore1:my1_?}{excluded:quote_word?}')
    def step_verify_text(context, text_to_clean, ignore1, excluded):
        context.excluded = excluded
    
    @given('Verify text 3 "{text_to_clean}"{excluded:my_?}')
    def step_verify_text(context, text_to_clean, excluded):
        context.excluded = excluded
    
    @then('normal parameter "{name}" is {result:quote_word*}')
    def step_verify_text(context, name, result):
        return getattr(context, name, None) == result
    

    Note: cfparse parser is not a good option if you have more than one optional parameters which comes one after another