Behave BDD测试如何在测试结束时正确终止独立运行的客户端服务端线程
问题根因
你当前的写法报错的核心原因是:client、server是@given步骤函数内的局部变量,离开该函数作用域后就无法被其他步骤访问,你在@then步骤中直接调用这两个变量属于未定义变量,自然无法运行。
可行解决方案
1. 用Behave内置的context对象传递实例
Behave的context对象是贯穿整个测试场景生命周期的全局共享对象,你可以把客户端、服务端实例绑定到context上,所有步骤都可以直接读取:
修改后的@given步骤:
@given(u'Client and server are ran concurrently') def step_imp(context): # 将实例绑定到context上 context.client = cl.Client() context.server = srv.Server() context.server.start() context.client.start()
修改后的@then终止步骤:
@then(u'The client-server dies after some time.') def step_imp(context): import time time.sleep(5) # 从context中读取实例调用终止方法 context.server.terminate() context.client.terminate()
2. 补充线程终止的可靠性优化
Python标准库的threading.Thread没有原生的terminate()方法,你自定义的该方法要确保是通过退出标志位实现软终止,避免出现线程僵死、资源泄漏的问题,示例实现参考:
import threading class Server(threading.Thread): def __init__(self): super().__init__() self.running = False def run(self): self.running = True while self.running: # 你的服务逻辑 pass def terminate(self): self.running = False # 等待线程完全退出 self.join(timeout=3)
3. 可选:自动清理线程避免遗漏
如果不想每次手动写终止步骤,可以在测试根目录的environment.py文件中添加after_scenario钩子,场景跑完后会自动清理线程,无需手动写终止步骤:
# environment.py def after_scenario(context, scenario): # 先判断属性是否存在,避免未初始化的场景报错 if hasattr(context, 'server'): context.server.terminate() if hasattr(context, 'client'): context.client.terminate()
额外注意
你原来的代码把time.sleep(5)和终止逻辑都写在@given步骤里,会导致后续的@when、@then步骤还没执行,服务就被终止了,拆分到独立步骤后测试执行顺序符合预期:启动服务 -> 执行测试操作 -> 验证结果 -> 终止服务。
内容的提问来源于stack exchange,提问作者bleuj
相关产品推荐
相关产品推荐

