1. 目的与定义?
让我们先从整个showcase是如何run起来的来发现它的意义。
2. 什么是BDD?
**行为驱动开发(BDD,Behavior Driven Development)**是一种敏捷软件开发方法,通过使用自然语言编写验收标准/测试用例。
2.1 BDD的意义
也后面再讲,先看表达形式。最好的情况就是我们整个实现讲完了,大家能够推断出它的意义、它的 benefits.
示例工程结构:
root
|--CANoe project
|--features/
|--|--class_canoe_module.py
|--|--XXX.feature
|--|--test_XXX.py
2.2 Cucumber与Gherkin language
Cucumber作为BDD框架的工具,主要组成部分:
- Feature(功能): 描述需要实现的业务功能。
- Scenario(场景): 描述在特定功能下的具体测试场景。
- Steps(步骤): 描述场景中的具体操作和期望结果,通常使用Given-When-Then结构。
Gherkin langrage的结构正好符合我们的测试用例的几个必备元素:precondition, steps, expected results

3. 演示实例
3.1 Example 1:基础用例
Feature: Car Light Control
As a car driver
I want to be able to control my car lights
So that I can drive at night and let others know the status of my car
Scenario: example 1
Given I have my car started
When I turn on the Low Beam lights
Then the Low Beam lights should be on
Pytest解析示例
@when("I turn on the Low Beam lights")
def step_impl():
app.set_SigVal(channel_num=1,
msg_name="BCM_LIGHT",
sig_name="BCM_LowBeamSts",
bus_type="CAN",
set_value=1)
time.sleep(2)
@given("I have my car started")
def step_impl():
pass
@then("the Low Beam lights should be on")
def step_impl():
assert app.get_SigVal(channel_num=2,
msg_name="ADB_LightActiReq",
sig_name="ADB_LowBeamReq",
bus_type="CAN") == 1
3.2 Example 2: 参数化测试用例
Scenario: example 2
Given I have my car started
When I make the BCM send LB control signal "1"
Then the ADB LB lights requirement signal should be "1"
与Example 1不同的是,在这里我们需要解析这个scenario中的数字内容,所以我们需要稍微修改一下pytest中的内容:

假如我有不止一条的操作,或不止一条的expected results:
And the ADB Auxiliary LB lights requirement signal should be "1"
3.3 Example 3: 逻辑与数据分离
项目真实需求如下:

Scenario Outline: Low Beam Control
Given I have my car started
When I make the BCM send LB control signal "<bcm_lb>"
Then the ADB LB lights requirement signal should be "<adb_lb>"
And the ADB Auxiliary LB lights requirement signal should be "<adb_auxlb>"
Examples:
| bcm_lb | adb_lb | adb_auxlb |
| 3 | 0 | 0 |
| 1 | 1 | 1 |
| 3 | 1 | 1 |
| 0 | 0 | 0 |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
| 0 | 0 | 0 |
4. 我们到底为什么要这么做?/这么做有什么好处?
- BDD用于团队沟通中,尤其是敏捷团队中,解决不同角色之间信息传递失真问题。(speak the same language)
- pytest这个测试框架比较简单,且扩展丰富。例如pytest-bdd就可以认为是pytest装了bdd插件。
- 代码的复用性高/模块化好。
- 易维护。考虑到项目的大范围重构的可能性,比如说,突然信号矩阵改了,在我的程序中只需要修改一次。
- 可读性好。测试用例以自然语言编写,不需要高代码能力。
- 在敏捷团队中可能还意味着更高效率。需求中的验收标准直接写成BDD风格,减少了需求->测试用例->测试脚本的多传一手的时间。更激进一点可以认为直接与CI相连。
- 增强沟通。从上面理由6我们就可以看出,这个东西想要从需求直接变成测试,测试人员能不能接受?这就促进了前期需求、开发、测试共同对需求的深入讨论。