pytest-bdd测试时报TypeError: 'NoneType'不可迭代问题求助
报错根因与修复方案
根因分析
- 核心触发原因:你调用的
full_retirement_age.main()函数没有返回值,默认返回None。assert语句中使用目标字符串 in main(参数)的写法,相当于尝试在None对象中查找子串,Python不支持对None做包含判断,因此抛出TypeError: argument of type 'NoneType' is not iterable。你提到业务程序运行正常,是因为该main函数仅通过print将结果输出到控制台,没有显式return输出内容,代码调用时无法拿到需要判断的字符串。 - 潜在隐患:两个
@then装饰的步骤函数都命名为check_return,Python同一作用域内后定义的同名函数会覆盖前一个,即使main函数返回值正常,第一个场景的测试用例也会因为找不到对应步骤实现报错。
修复方案
第一步:修改业务代码的main函数
调整full_retirement_age.py中的main函数逻辑,将打印的内容先拼接为完整字符串,打印后再return该字符串,示例如下:
def main(birth_year, birth_month): # 原有退休年龄、时间计算逻辑保留 # 把原来直接print的内容改为先存入变量 output_lines = [ f'Your full retirement age is {retire_years} and {retire_months} months.', f'This will be in {month_name} of {retire_year}.' ] full_output = '\n'.join(output_lines) # 保留打印逻辑,不影响原有手动运行的效果 print(full_output) # 新增返回语句,供测试用例读取判断 return full_output
第二步:修改测试步骤的函数名,避免重名覆盖
调整test_basic_functionality_steps.py中两个then步骤的函数名称,保证唯一:
# 第一个校验退休年龄的步骤修改函数名 @then(parsers.parse("the text the program returns should include 'Your full retirement age is {retire_years} and {retire_months} months.'"), converters=CONVERTERS) def check_retirement_age_output(user_inputs, retire_years, retire_months): assert f'Your full retirement age is {retire_years} and {retire_months} months.' in main(user_inputs["user_birthyear"], user_inputs["user_birthmonth"]) # 第二个校验退休时间的步骤修改函数名 @then(parsers.parse("the text the program returns should include 'This will be in {month_name} of {retire_year}.'"), converters=CONVERTERS) def check_retirement_time_output(user_inputs, retire_year, month_name): assert f'This will be in {month_name} of {retire_year}.' in main(user_inputs["user_birthyear"], user_inputs["user_birthmonth"])
完成以上两处修改后即可正常运行测试。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

