429 lines
11 KiB
Python
429 lines
11 KiB
Python
"""Test scenario decorator."""
|
|
|
|
import textwrap
|
|
|
|
from pytest_bdd.utils import collect_dumped_objects
|
|
|
|
|
|
def test_scenario_not_found(pytester, pytest_params):
|
|
"""Test the situation when scenario is not found."""
|
|
pytester.makefile(
|
|
".feature",
|
|
not_found=textwrap.dedent(
|
|
"""\
|
|
Feature: Scenario is not found
|
|
|
|
"""
|
|
),
|
|
)
|
|
pytester.makepyfile(
|
|
textwrap.dedent(
|
|
"""\
|
|
import re
|
|
import pytest
|
|
from pytest_bdd import parsers, given, then, scenario
|
|
|
|
@scenario("not_found.feature", "NOT FOUND")
|
|
def test_not_found():
|
|
pass
|
|
|
|
"""
|
|
)
|
|
)
|
|
result = pytester.runpytest_subprocess(*pytest_params)
|
|
|
|
result.assert_outcomes(errors=1)
|
|
result.stdout.fnmatch_lines('*Scenario "NOT FOUND" in feature "Scenario is not found" in*')
|
|
|
|
|
|
def test_scenario_comments(pytester):
|
|
"""Test comments inside scenario."""
|
|
pytester.makefile(
|
|
".feature",
|
|
comments=textwrap.dedent(
|
|
"""\
|
|
Feature: Comments
|
|
Scenario: Comments
|
|
# Comment
|
|
Given I have a bar
|
|
|
|
Scenario: Strings that are not #comments
|
|
Given comments should be at the start of words
|
|
Then this is not a#comment
|
|
And this is not a # comment
|
|
And this is not "#acomment"
|
|
|
|
"""
|
|
),
|
|
)
|
|
|
|
pytester.makepyfile(
|
|
textwrap.dedent(
|
|
"""\
|
|
import re
|
|
import pytest
|
|
from pytest_bdd import parsers, given, then, scenario
|
|
|
|
@scenario("comments.feature", "Comments")
|
|
def test_1():
|
|
pass
|
|
|
|
@scenario("comments.feature", "Strings that are not #comments")
|
|
def test_2():
|
|
pass
|
|
|
|
|
|
@given("I have a bar")
|
|
def _():
|
|
return "bar"
|
|
|
|
|
|
@given("comments should be at the start of words")
|
|
def _():
|
|
pass
|
|
|
|
|
|
@then("this is not a#comment")
|
|
@then("this is not a # comment")
|
|
@then('this is not "#acomment"')
|
|
def _():
|
|
pass
|
|
|
|
"""
|
|
)
|
|
)
|
|
|
|
result = pytester.runpytest()
|
|
|
|
result.assert_outcomes(passed=2)
|
|
|
|
|
|
def test_scenario_not_decorator(pytester, pytest_params):
|
|
"""Test scenario function is used not as decorator."""
|
|
pytester.makefile(
|
|
".feature",
|
|
foo="""
|
|
Feature: Test function is not a decorator
|
|
Scenario: Foo
|
|
Given I have a bar
|
|
""",
|
|
)
|
|
pytester.makepyfile(
|
|
"""
|
|
from pytest_bdd import scenario
|
|
|
|
test_foo = scenario('foo.feature', 'Foo')
|
|
"""
|
|
)
|
|
|
|
result = pytester.runpytest_subprocess(*pytest_params)
|
|
|
|
result.assert_outcomes(failed=1)
|
|
result.stdout.fnmatch_lines("*ScenarioIsDecoratorOnly: scenario function can only be used as a decorator*")
|
|
|
|
|
|
def test_simple(pytester, pytest_params):
|
|
"""Test scenario decorator with a standard usage."""
|
|
pytester.makefile(
|
|
".feature",
|
|
simple="""
|
|
Feature: Simple feature
|
|
Scenario: Simple scenario
|
|
Given I have a bar
|
|
""",
|
|
)
|
|
pytester.makepyfile(
|
|
"""
|
|
from pytest_bdd import scenario, given, then
|
|
|
|
@scenario("simple.feature", "Simple scenario")
|
|
def test_simple():
|
|
pass
|
|
|
|
@given("I have a bar")
|
|
def _():
|
|
return "bar"
|
|
|
|
@then("pass")
|
|
def _():
|
|
pass
|
|
"""
|
|
)
|
|
result = pytester.runpytest_subprocess(*pytest_params)
|
|
result.assert_outcomes(passed=1)
|
|
|
|
|
|
def test_angular_brackets_are_not_parsed(pytester):
|
|
"""Test that angular brackets are not parsed for "Scenario"s.
|
|
|
|
(They should be parsed only when used in "Scenario Outline")
|
|
|
|
"""
|
|
pytester.makefile(
|
|
".feature",
|
|
simple="""
|
|
Feature: Simple feature
|
|
Scenario: Simple scenario
|
|
Given I have a <tag>
|
|
Then pass
|
|
|
|
Scenario Outline: Outlined scenario
|
|
Given I have a templated <foo>
|
|
Then pass
|
|
|
|
Examples:
|
|
| foo |
|
|
| bar |
|
|
""",
|
|
)
|
|
pytester.makepyfile(
|
|
"""
|
|
from pytest_bdd import scenarios, given, then, parsers
|
|
|
|
scenarios("simple.feature")
|
|
|
|
@given("I have a <tag>")
|
|
def _():
|
|
return "tag"
|
|
|
|
@given(parsers.parse("I have a templated {foo}"))
|
|
def _(foo):
|
|
return "foo"
|
|
|
|
@then("pass")
|
|
def _():
|
|
pass
|
|
"""
|
|
)
|
|
result = pytester.runpytest()
|
|
result.assert_outcomes(passed=2)
|
|
|
|
|
|
def test_example_params(pytester):
|
|
"""Test example params are rendered where necessary:
|
|
* Step names
|
|
* Docstring
|
|
* Datatables
|
|
"""
|
|
pytester.makefile(
|
|
".feature",
|
|
example_params='''
|
|
Feature: Example params
|
|
Background:
|
|
Given I have a background <background>
|
|
And my background has:
|
|
"""
|
|
Background <background>
|
|
"""
|
|
|
|
Scenario Outline: Outlined scenario
|
|
Given I have a templated <foo>
|
|
When I have a templated datatable
|
|
| <data> |
|
|
| example |
|
|
And I have a templated docstring
|
|
"""
|
|
This is a <doc>
|
|
"""
|
|
Then pass
|
|
|
|
Examples:
|
|
| background | foo | data | doc |
|
|
| parameter | bar | table | string |
|
|
''',
|
|
)
|
|
pytester.makepyfile(
|
|
"""
|
|
from pytest_bdd import scenarios, given, when, then, parsers
|
|
from pytest_bdd.utils import dump_obj
|
|
|
|
scenarios("example_params.feature")
|
|
|
|
|
|
@given(parsers.parse("I have a background {background}"))
|
|
def _(background):
|
|
return dump_obj(("background", background))
|
|
|
|
|
|
@given(parsers.parse("I have a templated {foo}"))
|
|
def _(foo):
|
|
return "foo"
|
|
|
|
|
|
@given("my background has:")
|
|
def _(docstring):
|
|
return dump_obj(("background_docstring", docstring))
|
|
|
|
|
|
@given("I have a rule table:")
|
|
def _(datatable):
|
|
return dump_obj(("rule", datatable))
|
|
|
|
|
|
@when("I have a templated datatable")
|
|
def _(datatable):
|
|
return dump_obj(("datatable", datatable))
|
|
|
|
|
|
@when("I have a templated docstring")
|
|
def _(docstring):
|
|
return dump_obj(("docstring", docstring))
|
|
|
|
|
|
@then("pass")
|
|
def _():
|
|
pass
|
|
"""
|
|
)
|
|
result = pytester.runpytest("-s")
|
|
result.assert_outcomes(passed=1)
|
|
|
|
assert collect_dumped_objects(result) == [
|
|
("background", "parameter"),
|
|
("background_docstring", "Background parameter"),
|
|
("datatable", [["table"], ["example"]]),
|
|
("docstring", "This is a string"),
|
|
]
|
|
|
|
|
|
def test_step_parser_argument_not_in_function_signature_does_not_fail(pytester):
|
|
"""Test that if the step parser defines an argument, but step function does not accept it,
|
|
then it does not fail and the params is just not filled."""
|
|
|
|
pytester.makefile(
|
|
".feature",
|
|
simple="""
|
|
Feature: Simple feature
|
|
Scenario: Step with missing argument
|
|
Given a user with username "user1"
|
|
""",
|
|
)
|
|
pytester.makepyfile(
|
|
"""
|
|
from pytest_bdd import scenarios, given, parsers
|
|
|
|
scenarios("simple.feature")
|
|
|
|
@given(parsers.parse('a user with username "{username}"'))
|
|
def create_user():
|
|
pass
|
|
"""
|
|
)
|
|
result = pytester.runpytest()
|
|
result.assert_outcomes(passed=1)
|
|
|
|
|
|
def test_multilanguage_support(pytester):
|
|
"""Test multilanguage support."""
|
|
pytester.makefile(
|
|
".feature",
|
|
simple="""
|
|
# language: it
|
|
|
|
Funzionalità: Funzionalità semplice
|
|
|
|
Contesto:
|
|
Dato che uso uno step nel contesto
|
|
Allora va tutto bene
|
|
|
|
Scenario: Scenario semplice
|
|
Dato che uso uno step con "Dato"
|
|
E che uso uno step con "E"
|
|
Ma che uso uno step con "Ma"
|
|
* che uso uno step con "*"
|
|
Allora va tutto bene
|
|
|
|
Schema dello scenario: Scenario con schema
|
|
Dato che uso uno step con "<nome esempio>"
|
|
Allora va tutto bene
|
|
|
|
Esempi:
|
|
| nome esempio |
|
|
| esempio 1 |
|
|
| esempio 2 |
|
|
""",
|
|
)
|
|
pytester.makepyfile(
|
|
"""
|
|
from pytest_bdd import scenario, given, then, parsers
|
|
from pytest_bdd.utils import dump_obj
|
|
|
|
@scenario("simple.feature", "Scenario semplice")
|
|
def test_scenario_semplice():
|
|
pass
|
|
|
|
@scenario("simple.feature", "Scenario con schema")
|
|
def test_scenario_con_schema():
|
|
pass
|
|
|
|
@given("che uso uno step nel contesto")
|
|
def _():
|
|
return dump_obj(("given", "che uso uno step nel contesto"))
|
|
|
|
@given(parsers.parse('che uso uno step con "{step_name}"'))
|
|
def _(step_name):
|
|
return dump_obj(("given", "che uso uno step con ", step_name))
|
|
|
|
@then("va tutto bene")
|
|
def _():
|
|
dump_obj(("then", "va tutto bene"))
|
|
"""
|
|
)
|
|
result = pytester.runpytest("-s")
|
|
result.assert_outcomes(passed=3)
|
|
|
|
assert collect_dumped_objects(result) == [
|
|
# 1st scenario
|
|
("given", "che uso uno step nel contesto"),
|
|
("then", "va tutto bene"),
|
|
("given", "che uso uno step con ", "Dato"),
|
|
("given", "che uso uno step con ", "E"),
|
|
("given", "che uso uno step con ", "Ma"),
|
|
("given", "che uso uno step con ", "*"),
|
|
("then", "va tutto bene"),
|
|
# 2nd scenario
|
|
# 1st example
|
|
("given", "che uso uno step nel contesto"),
|
|
("then", "va tutto bene"),
|
|
("given", "che uso uno step con ", "esempio 1"),
|
|
("then", "va tutto bene"),
|
|
# 2nd example
|
|
("given", "che uso uno step nel contesto"),
|
|
("then", "va tutto bene"),
|
|
("given", "che uso uno step con ", "esempio 2"),
|
|
("then", "va tutto bene"),
|
|
]
|
|
|
|
|
|
def test_default_value_is_used_as_fallback(pytester):
|
|
"""Test that the default value for a step implementation is only used as a fallback."""
|
|
pytester.makefile(
|
|
".feature",
|
|
simple="""
|
|
Feature: Simple feature
|
|
Scenario: Step using default arg
|
|
Given a user with default username
|
|
|
|
Scenario: Step using explicit value
|
|
Given a user with username "user1"
|
|
""",
|
|
)
|
|
pytester.makepyfile(
|
|
"""
|
|
from pytest_bdd import scenarios, given, then, parsers
|
|
from pytest_bdd.utils import dump_obj
|
|
|
|
scenarios("simple.feature")
|
|
|
|
@given('a user with default username', target_fixture="user")
|
|
@given(parsers.parse('a user with username "{username}"'), target_fixture="user")
|
|
def create_user(username="defaultuser"):
|
|
dump_obj(username)
|
|
|
|
"""
|
|
)
|
|
result = pytester.runpytest("-s")
|
|
result.assert_outcomes(passed=2)
|
|
|
|
assert collect_dumped_objects(result) == ["defaultuser", "user1"]
|