很多做开发或测试的朋友都有过这样的经历:产品经理说“这个功能要能正常登录”,非技术测试人员可能会纠结怎么转化成机器能执行的测试用例,开发要拆解需求还要写测试代码,中间沟通成本极高——要么产品说的模糊不清,要么非技术测试写的用例技术人员看不懂,最后导致测试用例与实际需求脱节,上线后出问题。这时候,BDD行为驱动测试就能解决这类问题,而pytest-bdd作为Python生态中轻量好用的工具,能让非技术人员也参与到用例编写中来,让测试环节的协作更顺畅。
一、为什么要让非技术人员参与测试用例编写
1.1 传统测试流程的痛点
传统的测试流程中,测试用例通常由技术人员(比如自动化测试工程师)编写,而非技术测试人员(比如功能测试)更多做的是手动执行、bug反馈的工作。但实际情况是,很多功能的实际使用场景,非技术人员最清楚——比如用户怎么点按钮、会在什么场景下出错,这些细节如果全靠技术人员猜,很容易漏掉关键的用例,导致测试覆盖不全。而且,当产品需求变化时,需要同步修改的测试用例如果只有技术人员能写,就会出现响应慢、出错的情况,甚至出现“技术写的用例和产品说的需求完全不匹配”的尴尬。
1.2 BDD的核心:用自然语言统一沟通语言
BDD的核心思想是“用自然语言描述功能行为,让所有角色(产品、测试、开发)都能读懂”。它把测试用例拆成了Given-When-Then三个部分,分别对应前置条件、操作步骤、预期结果。这三个部分的描述都是用自然语言,没有技术术语,非技术人员只要理解功能就能写出用例,不需要懂代码。
二、认识pytest-bdd:实现BDD的轻量工具
2.1 BDD不是新技术,是协作方式
很多人以为BDD是复杂的技术,其实它是一种思维方式——把“做什么”和“怎么做”分开,让不同角色对齐需求。而pytest-bdd就是把这种思维落地到Python测试中的工具,它是pytest的一个插件,不需要复杂的配置,就能把自然语言的用例(.feature文件)和实际的测试代码关联起来。
2.2 为什么选pytest-bdd?
相比于其他BDD框架,比如Cucumber,pytest-bdd的优势在于:一是它依托Python生态,容易上手,不需要额外安装复杂的环境;二是它的胶水代码(连接自然语言和测试代码的部分)编写简单,调试方便;三是能直接复用pytest的所有功能,比如断言、fixture,扩展性强。对于中小团队来说,它足够轻量化,不需要 heavyweight 的流程,就能快速落地BDD。
三、用pytest-bdd实现非技术人员写用例
3.1 本次示例的技术栈统一说明
为了避免混淆,本次示例使用单一技术栈:Python 3.9 + pytest 7.4 + pytest-bdd 6.1。所有代码和用例都基于这个栈编写,不需要其他额外工具。
3.2 完整示例:登录功能的用例编写
首先,非技术人员(比如产品测试)需要编写自然语言的用例文件,命名为login.feature,内容如下:
# login.feature:由非技术人员编写的用例,完全用自然语言描述操作和结果
功能: 用户登录功能
场景: 输入正确的用户名和密码,成功登录首页
Given 我在登录页面(前置条件:已进入登录界面)
When 我输入用户名"test_user"和密码"test_pass"(操作:输入账号信息)
点击登录按钮(操作:触发登录请求)
Then 我应该能看到"首页欢迎你"的提示(预期结果:登录成功后的反馈)
然后,技术人员只需要编写对应的胶水代码(连接自然语言和实际操作的代码),即可执行这个用例:
# test_login.py:技术人员编写的胶水代码,负责把自然语言翻译成实际的测试逻辑
from pytest_bdd import scenario, given, when, then
import time
# 关联.feature文件中的目标场景,确定要执行的用例
@scenario('login.feature', '输入正确的用户名和密码,成功登录首页')
def test_login_success():
pass
# 对应Given步骤:我在登录页面,实现前置条件的代码逻辑
@given('我在登录页面')
def open_login_page():
# 这里实际项目中会打开Web或App的登录入口,示例简化为模拟延迟
print("执行:打开登录页面,等待加载")
time.sleep(0.5)
# 对应When步骤:输入用户名和密码,实现输入操作的逻辑
@when('我输入用户名"<username>"和密码"<password>"')
def input_credentials(username, password):
print(f"执行:输入用户名【{username}】,输入密码【{password}】")
# 对应When步骤:点击登录按钮,实现触发登录的逻辑
@when('点击登录按钮')
def click_login_btn():
# 实际项目中会发送登录请求,示例简化为模拟网络延迟
print("执行:点击登录按钮,等待服务器响应")
time.sleep(0.5)
# 对应Then步骤:验证提示信息,实现预期结果的断言逻辑
@then('我应该能看到"<tip>"的提示')
def check_success_tip(tip):
# 实际项目中会断言UI元素的文本,示例简化为逻辑判断
print(f"执行:校验返回的提示信息是否为【{tip}】")
assert tip == "首页欢迎你", f"提示信息校验失败,预期为{tip}"
如果要运行这个用例,只需要在命令行执行:
pytest test_login.py -v
执行后会输出用例的执行结果,非技术人员写的用例可以直接被执行,不需要懂代码。这里的<username>、<password>、<tip>是用例中的变量,非技术人员可以直接修改这些变量的值,实现用例的参数化,比如添加另一个场景验证错误密码的情况,只需要在.feature文件中新增一个场景,不需要修改胶水代码。
四、pytest-bdd的应用场景
4.1 前后端协作的功能测试
当团队有前端和后端开发,产品经理、测试人员协同的场景,BDD用例让所有人都能看懂。前端开发负责实现“登录页面输入用户名”的交互,后端负责验证密码逻辑,测试人员可以直接用BDD用例确认功能是否符合需求,不需要反复沟通“这个步骤的测试代码怎么写”。
4.2 产品需求转测试用例的环节
产品在写需求文档时,可以同步写BDD用例,把需求拆成Given-When-Then,这样的需求文档更清晰,非技术测试人员拿到手就能直接用,不需要技术人员转化。比如产品写“用户下单时地址不能为空”,对应的BDD用例可以直接写:Given 我在下单页面,When 我不填地址就提交订单,Then 应该提示“地址不能为空”,测试人员可以直接拿去执行。
4.3 跨团队需求验证
当有外部合作伙伴或者甲方需要确认功能时,BDD用例是通用的文档,不需要把代码打包给对方,只需要给他们看.feature文件,就能验证功能是否符合要求,避免了技术门槛带来的沟通障碍,让需求验证的效率大幅提升。
五、技术优缺点分析
5.1 核心优势
第一,降低测试门槛,非技术人员不需要懂代码就能编写用例,参与到测试流程中,让测试覆盖更全面,不会漏掉用户实际操作的细节;第二,统一沟通语言,所有角色都用自然语言的用例对齐需求,减少因理解偏差导致的问题,比如产品说的需求,测试和开发都能准确理解;第三,复用pytest的生态,支持fixture、参数化、断言等功能,扩展性强,能满足不同规模的测试需求;第四,用例可维护性高,自然语言的用例更容易理解,修改需求时只需要调整对应的步骤描述,不需要改大量代码,维护成本低。
5.2 主要不足
第一,胶水代码需要技术人员维护,如果团队没有专门的自动化测试人员,对开发的要求会更高,需要投入一定的精力编写和维护;第二,对于极度复杂的业务场景(比如有大量分支逻辑的支付流程),BDD用例可能会变得冗长,不如代码灵活,难以处理复杂的分支;第三,.feature文件的格式有严格要求,比如缩进、步骤描述的规范,非技术人员初期可能需要一点学习成本,但这个成本很低,只要按照示例仿写就能快速上手;第四,对于性能测试、单元测试这种细分测试,BDD的优势不明显,更适合功能测试和集成测试。
六、注意事项
6.1 非技术人员编写用例的规范
非技术人员写用例时,要避免用太抽象的描述,比如不要写“我操作登录”,要写清楚每个步骤的具体动作,比如“我在登录页面输入正确的用户名test_user和密码test_pass,然后点击登录按钮”。同时,每个场景只验证一个功能点,不要把多个场景混在一起,比如不要同时验证登录和注册的逻辑,这样用例更清晰,执行时也更容易排查问题。
6.2 胶水代码的维护规范
技术人员编写胶水代码时,要尽量复用步骤,比如“输入用户名”这个步骤,在其他用例(比如注册)中也可以复用,避免重复代码,提高维护效率。同时,要给步骤加清晰的注释,方便非技术人员后续查看,比如步骤对应的操作是什么,需要的变量是什么,减少沟通成本。
6.3 版本控制的配合
BDD用例(.feature文件)和胶水代码都要加入版本控制,和其他代码一起维护,这样当需求变化时,能追踪到用例的修改历史,避免出现“测试用例和代码版本不一致”的问题,保证测试的准确性。
七、总结
pytest-bdd是让非技术人员参与测试用例编写的优秀工具,它依托BDD的核心思想,把自然语言和测试代码结合,降低了协作成本,解决了传统测试流程中的沟通痛点。对于中小团队,尤其是有很多非技术测试人员的团队,用它快速落地BDD,能有效提升测试效率,减少因需求理解偏差导致的问题,让测试环节更顺畅。当然,它也有适用场景,需要根据团队的实际情况选择,适合中小团队的功能测试和集成测试场景。
Comments