Package: bdd-coder
BDD CoderA package devoted to agile implementation ofclass-based behavior tests. It consists of (seeexample):codersmodule able tomake a tester package - test suite - blueprint from user story specifications in YAML filespatch such tester package with new YAML specificationstestermodule employed to run such blueprint tests, which also has the ability to export their docs as YAML specificationsAlthough this package is intended to be used withpytest, until version 2.0.0 the base test case class for all test suitsbdd_coder.tester.tester.BaseTestCasewas aunittest.TestCasesubclass. From version 2.0.0unittest.TestCaseis no longer supported, so thatpytest's setup and teardown functions - seepytest-xunit_setup- should be implemented instead. Seepytest-unitteston the benefits of droppingunittest.TestCase.Seemastermindfor an example testing a Django REST Framework API.Test this package withtox- see tox.ini.StoryThis package was born as a study of Behavior Driven Development; and from the wish of having a handy implementation of Gherkin language in class-based tests, to be employed so that development cycles start with coding a behavior test suite containing the scenario specifications in test case method__doc__s - asbdd_coder.testerachieves.In conjunction withbdd_coder.coder, development cyclesstartwith:A set of YAML specifications is agreed and craftedFrom these, a test suite is automatically created or patchedNewtest step methodsare crafted to efficiently achieve 100% behavior coverageUser Story (feature) specificationsEach test suite (tester package) has a structure├─ __init__.py
├─ base.py
└─ test_stories.pycorresponding to a specifications directory with story YAML files├─ some-story.yml
├─ another-story.yml
├─ ...
└─ this-story.ymlA story file corresponds to a test case class declared intotest_stories.py, consisting mainly of scenario declarations:Title: <Story title>  # --> class __name__

Story: |-  # free text --> class __doc__
  As a <user group>
  I want <feature>
  In order to/so that <goal>

Scenarios:
  Scenario name:  # --> scenario __doc__
    - Given an event $(1) with $(A) and $first_param that gives `x` and `y`
    - When it happens that...
    - And the parameters $second and $third enter
    - Then finally we assert that...
    # ...
  # ...Only the keysTitle,Story,Scenariosare required and mean something.Step declarationsA scenario declaration consists of a list of step declarations, which:Correspond to a test step method to be definedStart with a whole word - normally 'Given', 'When', or 'Then' - that is ignored by the tester (only order matters)May contain:Input string values as $(...), which are passed as Pytest fixture parameters to the step method, so that they are available from the Pytestrequestfixture as the tuplerequest.paramInput parameter names as $param_name, which are passed to Pytest's parametrizeOutput variable name sequence using backticks - if non-empty, the method should return the output values as a tuple, which are collected by thebdd_coder.tester.decorators.Gherkindecorator instance, by name into itsoutputsmap of sequencesMay refer to a scenario name, either belonging to the same class (story), or to an inherited classTesterThe core of each test suite consists of the following required class declaration in itsbase.pymodule:frombdd_coderimportdecoratorsfrombdd_coderimporttestergherkin=decorators.Gherkin(logs_path='example/tests/bdd_runs.log')@gherkinclassBddTester(tester.BddTester):"""The decorated BddTester subclass of this tester package.It manages scenario runs. All test classes inherit from this one,so generic test methods for this package are expected to be defined here"""Then, story test cases are declared intest_stories.py, with thebasemodule imported, scenario declarations such asclassStoryTitle(BddTesterSubclass,AnotherBddTesterSubclass):@base.gherkin.scenario(['param1_value1'],['param1_value2'])deftest_scenario_name(self):"""Given $(input1) and $param1 step one gives `x` and `y`...Last step with $(input2) gives `result`"""that will run according to their__doc__s, and the necessary step method definitions.CommandsExport test suite docs as YAMLusage: bdd-make-yaml-specs [-h] [--overwrite] test_module specs_path

positional arguments:
  test_module      str. Passed to `importlib.import_module`
  specs_path       str. Will try to write the YAML files in here

keyword arguments:
  --overwrite, -oAdditionally, validates code against generated specifications.Coder commandsMake a test suite blueprintusage: bdd-blueprint [-h] [--base-class BASE_CLASS]
                     [--specs-path SPECS_PATH] [--tests-path TESTS_PATH]
                     [--test-module-name TEST_MODULE_NAME] [--overwrite]

keyword arguments:
  --base-class BASE_CLASS, -b BASE_CLASS
                        str. Base test case class
  --specs-path SPECS_PATH, -s SPECS_PATH
                        str. Default: behaviour/specs. Directory containing the YAML specs
  --tests-path TESTS_PATH, -t TESTS_PATH
                        str. Default: next to specs
  --test-module-name TEST_MODULE_NAME, -tm TEST_MODULE_NAME
                        str. Default: stories. Name for test_<name>.py
  --overwrite, -oThe following:bdd-coder$ bdd-blueprint -s example/specs -t example/tests --overwritewill rewriteexample/tests(with no changes ifexample/specsis unmodified), and runpyteston the blueprint yielding the output, like============================= test session starts ==============================
platform [...]
collecting ... collected 2 items

example/tests/test_stories.py::TestClearBoard::test_odd_boards PASSED    [ 50%]
example/tests/test_stories.py::TestClearBoard::test_start_board PASSED   [100%]

=========================== 2 passed in 0.04 seconds ===========================Patch a test suite with new specificationsUse this command in order to update a tester package with new YAML specifications. It removes scenario declarationsonly; it changes the scenario set, which may imply a new test class hierarchy with new stories and scenarios; it adds the necessary step methods, and new aliases (if any).usage: bdd-patch [-h] test_module [specs_path]

positional arguments:
  test_module  str. Passed to `importlib.import_module`
  specs_path   str. Directory to take new specs from. Default: specs/ next to test packageThe following:bdd-coder$ bdd-patch example.tests.test_stories example/new_specswill turnexample/testsintoexample/new_tests, and runpyteston the suite yielding something like============================= test session starts ==============================
platform [...]
collecting ... collected 3 items

example/tests/test_stories.py::TestNewGame::test_even_boards PASSED      [ 33%]
example/tests/test_stories.py::TestNewGame::test_funny_boards PASSED     [ 66%]
example/tests/test_stories.py::TestNewGame::test_more_boards PASSED      [100%]

=========================== 3 passed in 0.04 seconds ===========================