从pytest.ini读取文件名遇错:AttributeError与TypeError问题排查
关于pytest.ini配置读取的问题解答
一、把文件名放在pytest.ini的做法是否合理?
完全合理。pytest.ini是pytest官方推荐的配置文件,用来存放测试相关的配置项,把硬编码的文件路径抽离到这里有几个明确的好处:
- 无需修改代码即可切换测试文件路径,适配不同环境(比如本地测试、CI流水线)
- 配置集中管理,便于团队统一维护
- 符合pytest的最佳实践,提升代码的可维护性
二、报错原因及解决办法
1. 第一个报错:AttributeError: module pytest has no attribute config
这是因为你用了pytest旧版本的写法。在pytest 6.0及以后的版本中,全局的pytest.config已经被移除,不能再直接通过这个路径访问配置实例。
2. 第二个报错:TypeError: Config.getini() missing 1 required positional argument: 'name'
Config是pytest的配置类,getini是它的实例方法,不是类方法。直接用Config.getini()调用时,Python不会自动传入实例本身(也就是self参数),导致方法误判你缺少了必要的name参数——实际上name指的是你要获取的配置项键名(比如这里的cards_file),但因为self没被自动传入,Python把你传的"cards_file"当成了self,进而报错。
正确的读取方式
要获取pytest的配置,必须拿到Config类的实例(即当前运行的config对象),通常有两种实用方式:
方式一:在测试函数/fixture中通过request对象获取
把读取逻辑改成fixture,或者在测试函数中通过request参数拿到config:
import pytest import csv import random # 改成fixture的示例 @pytest.fixture def random_card(request): # 通过request.config拿到配置实例 filename = request.config.getini("cards_file") with open(filename, 'r') as csvfile: reader = csv.reader(csvfile) # 跳过表头行 rows = list(reader)[1:] return random.choice(rows) # 在测试函数中直接使用这个fixture def test_card_valid(random_card): assert len(random_card) > 0
方式二:将config作为参数传入静态方法
如果要保留静态方法的结构,需要在调用时把config实例传进去:
import csv import random class CardHandler: @staticmethod def get_card_details(config): filename = config.getini("cards_file") with open(filename, 'r') as csvfile: reader = csv.reader(csvfile) rows = list(reader)[1:] return random.choice(rows) # 测试中调用时,通过request获取config传入 def test_get_card(request): card = CardHandler.get_card_details(request.config) # 编写你的测试逻辑
三、Config.getini()与config.getini()的差异
Config是pytest的配置类,它定义了配置的结构和可用方法(比如getini),getini是这个类的实例方法,必须基于Config类的实例才能调用,不能直接用类本身调用。config是Config类的实例对象,代表当前pytest运行时的具体配置(包含你在pytest.ini中定义的所有配置项)。调用config.getini("cards_file")时,实例会自动传入self参数,你只需要传入要获取的配置项名称(也就是name参数,对应pytest.ini里的键名)。
内容的提问来源于stack exchange,提问作者fdama
相关产品推荐
相关产品推荐

