类测试中的小黄瓜语言.测试套件蓝图

bdd-coder的Python项目详细描述


bdd编码器

一个致力于基于类的行为测试的敏捷实现的包。它包括:

tox测试-见tox.ini。

有关应用程序,请参见mastermind

故事

这个包是作为行为驱动开发的一个研究而诞生的;并且是为了在基于类的测试中方便地实现gherkin语言,以便开发周期从编写包含测试用例方法__doc__s-as bdd_coder.tester中的场景规范的行为测试套件开始的。

结合bdd_coder.coder,开发周期start使用:

  1. 已商定并制作了一套山药规范

  2. 从中自动创建或修补测试套件

  3. 新的测试步骤方法经过精心设计,可有效实现100%的行为覆盖率

用户情景(功能)规范

每个测试套件(测试仪包)都有一个结构

├─ __init__.py
├─ aliases.py
├─ base.py
└─ test_stories.py

对应于规范目录

├─ aliases.yml
└─ features/
   ├─ some-story.yml
   ├─ another-story.yml
   ├─ ...
   └─ this-story.yml

story yaml文件(features/下的文件)对应于声明为test_stories.py的测试用例类,主要由场景声明组成:

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__
    - Step "1" with "A" gives `x` and `y`
      # ...
    - Last step with "B" gives `result`
  # ...

# Extra class atributes - ignored in patching
Extra name:
  <yaml-attribute-coded-with-str(yaml.load)>
...

所以只有键TitleStoryScenarios被保留。

如果bdd_coder.tester.decorators.Steps采用validate=True(默认值),则方案名称是唯一的,这也验证了类层次结构。

步骤声明

  • 从一个完整的单词开始-通常是“给定”、“何时”或“然后”-测试人员会忽略这个单词(仅限订单)

  • 可能包含:

    • 输入*args双引号中的值序列-传递给step方法

    • 使用反勾号输出变量名称序列-如果非空,则方法应将输出值作为元组返回,这些值由bdd_coder.tester.decorators.Steps装饰器实例收集,并按名称返回到其序列的outputs映射中

  • 可能是指场景名称,属于同一个类(story)或继承的类

别名

声明为

Alias sentence:  # --> method to call
  - Step sentence  # from scenario __doc__s
  - Another step sentence
  # ...
# ...

对应于aliases.py

MAP = {
    'step_sentence': 'alias_sentence',
    'another_step_sentence': 'alias_sentence',
    # ...
}

测试仪

每个测试套件的核心由其base.py模块中的以下必需类声明组成:

from test.case.module import MyTestCase

from bdd_coder.tester import decorators
from bdd_coder.tester import tester

from . import aliases

steps = decorators.Steps(aliases.MAP, logs_parent='example/tests')


@steps
class BddTester(tester.BddTester):
    """
    The decorated BddTester subclass of this suite - manages scenario runs
    """


class BaseTestCase(tester.BaseTestCase, MyTestCase):
    """
    The base test case of this suite - manages test runs
    """

然后,在test_stories.py中声明故事测试用例,并使用

from . import base
from bdd_coder.tester import decorators

作为

class StoryTitle(BddTesterSubclass, AnotherBddTesterSubclass, ...[, base.BaseTestCase]):

使用场景声明

  @decorators.Scenario(base.steps):
  def [test_]scenario_name(self):
      """
      Step "1" with "A" gives `x` and `y`
      ...
      Last step with "B" gives `result`
      """

它将根据它们的__doc__和必要的步骤方法定义运行。

测试运行日志

已实现的行为测试步骤运行由bdd_coder.tester记录为

1 ✅ ClearBoard.even_boards:
  1.1 - 2019-03-18 17:30:13.071420 ✅ i_request_a_new_game_with_an_even_number_of_boards [] ↦ ('Even Game',)
  1.2 - 2019-03-18 17:30:13.071420 ✅ a_game_is_created_with_boards_of__guesses ['12'] ↦ ()

2 ✅ ClearBoard.test_start_board:
  2.1 - 2019-03-18 17:30:13.071420 ✅ even_boards [] ↦ ()
  2.2 - 2019-03-18 17:30:13.071420 ✅ i_request_a_clear_board_in_my_new_game [] ↦ ('Board',)
  2.3 - 2019-03-18 17:30:13.071420 ✅ board__is_added_to_the_game [] ↦ ()

3 ❌ ClearBoard.test_odd_boards:
  3.1 - 2019-03-18 17:30:13.071420 ❌ i_request_a_new_game_with_an_odd_number_of_boards [] ↦ Traceback (most recent call last):
  File "/usr/lib/python3.6/unittest/mock.py", line 939, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "/usr/lib/python3.6/unittest/mock.py", line 995, in _mock_call
    raise effect
AssertionError: FAKE

Scenario runs {
    "1✅": "even_boards",
    "2✅": "test_start_board"
    "3❌": "test_odd_boards"
}
Pending []

All scenarios ran ▌ 2 ✅ ▌ 1 ❌

in to $logs_parent/.bdd-run-logs/(git忽略),按日期拆分成文件YYYY-MM-DD.log,并将logs_parent值传递给bdd_coder.tester.decorators.Steps,后者也有一个max_history_length参数-在数天内,旧的历史记录将被删除。

在ubuntu中,我使用bash函数

function bdd-log-tab() {
  gnome-terminal --tab -- tail -f $(pwd)/$1/.bdd-run-logs/$(ls $(pwd)/$1/.bdd-run-logs | tail -1)
}

打开一个终端标签,当测试运行时将输出日志流(如果存在{{}目录)。

命令

检查是否有挂起的方案

可能发生的情况是,运行的所有步骤(以及所有测试)都成功了,但有些场景没有达到。在pytest之后运行bdd-pending-scenarios,将其视为错误(推荐)

❌ Some scenarios did not run! Check the logs in [...]/.bdd-run-logs
usage: bdd-pending-scenarios [-h] logs_parent

positional arguments:
  logs_parent  Parent directory of .bdd-run-logs/

将测试套件文档导出为yaml
usage: bdd-make-yaml-specs [-h] [--overwrite] [--validate]
                           test_module specs_path

positional arguments:
  test_module      passed to importlib.import_module
  specs_path       will try to write the YAML files in here

optional arguments:
  --overwrite, -w

另外,根据生成的规范验证代码。

编码器命令

制作测试套件蓝图

usage: bdd-blueprint [-h] [--base-class BASE_CLASS]
                     [--specs-path SPECS_PATH] [--tests-path TESTS_PATH]
                     [--test-module-name TEST_MODULE_NAME] [--overwrite]

optional arguments:
  --base-class BASE_CLASS, -c BASE_CLASS
                        default: unittest.TestCase
  --specs-path SPECS_PATH, -i SPECS_PATH
                        default: behaviour/specs
  --tests-path TESTS_PATH, -o TESTS_PATH
                        default: next to specs
  --test-module-name TEST_MODULE_NAME, -n TEST_MODULE_NAME
                        Name for test_<name>.py. default: stories
  --overwrite

T型他跟着:

bdd-coder$ bdd-blueprint -i example/specs -o example/tests --overwrite

将重写example/tests(如果example/specs未修改,则不做任何更改),并在生成输出的蓝图上运行pytest,如

============================= test session starts ==============================
platform [...]
collecting ... collected 2 items

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

=========================== 2 passed in 0.04 seconds ===========================

使用新规范修补测试套件

使用此命令可使用新的yaml规范更新测试程序包-仅删除场景声明only,更改场景集,这可能意味着新的测试类层次结构包含新的场景和场景,添加必要的步骤方法,并添加新的别名(如果有)。

usage: bdd-patch [-h] test_module [specs_path]

positional arguments:
  test_module  passed to importlib.import_module
  specs_path   Directory to take new specs from. default: specs/ next to test package

optional arguments:
  --scenario-delimiter SCENARIO_DELIMITER, -d SCENARIO_DELIMITER
                        default: @decorators.Scenario(base.steps)

以下内容:

bdd-coder$ bdd-patch example.tests.test_stories example/new_specs

example/tests转换为example/new_tests,并在套件上运行pytest,生成类似

============================= test session starts ==============================
platform [...]
collecting ... collected 3 items

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

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

和一个日志

1 ✅ NewGame.new_player_joins:
  1.1 - 2019-04-01 00:30:50.164042 ✅ a_user_signs_in [] ↦ ()
  1.2 - 2019-04-01 00:30:50.164059 ✅ a_new_player_is_added [] ↦ ()

2 ✅ NewGame.test_even_boards:
  2.1 - 2019-04-01 00:30:50.164178 ✅ new_player_joins [] ↦ ()
  2.2 - 2019-04-01 00:30:50.164188 ✅ i_request_a_new_game_with_an_even_number_of_boards [] ↦ ('game',)
  2.3 - 2019-04-01 00:30:50.164193 ✅ a_game_is_created_with_boards_of__guesses ['12'] ↦ ()

3 ✅ NewGame.new_player_joins:
  3.1 - 2019-04-01 00:30:50.165339 ✅ a_user_signs_in [] ↦ ()
  3.2 - 2019-04-01 00:30:50.165348 ✅ a_new_player_is_added [] ↦ ()

4 ✅ NewGame.test_funny_boards:
  4.1 - 2019-04-01 00:30:50.165422 ✅ new_player_joins [] ↦ ()
  4.2 - 2019-04-01 00:30:50.165429 ✅ class_hierarchy_has_changed [] ↦ ()

5 ✅ NewGame.new_player_joins:
  5.1 - 2019-04-01 00:30:50.166458 ✅ a_user_signs_in [] ↦ ()
  5.2 - 2019-04-01 00:30:50.166466 ✅ a_new_player_is_added [] ↦ ()

6 ✅ NewGame.test_more_boards:
  6.1 - 2019-04-01 00:30:50.166535 ✅ new_player_joins [] ↦ ()
  6.2 - 2019-04-01 00:30:50.166541 ✅ user_is_welcome [] ↦ ()

Scenario runs {
    "1✅-3✅-5✅": "new_player_joins",
    "2✅": "test_even_boards",
    "4✅": "test_funny_boards",
    "6✅": "test_more_boards"
}
Pending []

All scenarios ran ▌ 6 ✅

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java jgrapht SimpleDirectedWeightedGraph规范化权重   java安卓使用CFB   java如何从javaclass警告浏览器?可能吗?   javagson结构难点   java使用jbossclient的最佳方式是什么。Wildfly 10应用程序中的jar?   JAVA:socket重写以使用CipherInputStream和CipherOutputStream   java Android UI测试长时间点击并拖动   java如何在Android中重置AtomicInteger唯一Id?   多线程客户端/服务器应用程序上的java客户端断开连接   GAE Memcache中的java损坏值   java如何使用变量作为资源的路径?   爪哇?(三向)操作员