为何Pytest中一个测试实例会影响另一个新创建的实例?
问题:新建类实例却残留旧数据的原因与解决
问题场景
测试处理性能计数器的S3Db类时,每个测试用例都会新建S3Db实例,但第二个测试中却出现了第一个测试的计数器数据,导致断言失败。
S3Db类代码
class S3Db: data = {} fs = None s3_path = None def __init__(self, s3_api_key, s3_api_secret, bucket_name, filename, bucket_path='/'): if s3_api_key != 'test': self.fs = s3fs.S3FileSystem(s3_api_key, secret=s3_api_secret) self.s3_path = f's3://{bucket_name}{bucket_path}{filename}' self.data = read_json_s3_path(self.fs, self.s3_path) pass def increment_timed_counter(self, counter_name: str): ...
Pytest测试用例
def test_can_increment_timed_counter(): s3db = S3Db('test', 'testsecret', 'bucket', 'filename') s3db.init_timed_counter('Test Counter 1', 1000) val = s3db.increment_timed_counter('Test Counter 1') assert val == 1 assert s3db.get_timed_counter('Test Counter 1') == 1 def test_can_init_timed_counters(): # NOTE I CREATE A NEW INSTANCE HERE, SHOULD BE BRAND NEW? s3db = S3Db('test', 'testsecret', 'bucket', 'filename') s3db.init_timed_counter('Test Counter 2', 1000) assert s3db.data == { 'timed_counters': { 'Test Counter 2': { 'name': 'Test Counter 2', 'expiration_ms': 1000, 'values': [] } } }
报错信息
E 'timed_counters': {'Test Counter 2': {'expiration_ms': 1000, E 'name': 'Test Counter 2', E - 'values': []}}, E ? - E + 'values': []}, E + 'Test Counter 1': {'expiration_ms': 1000, E + 'name': 'Test Counter 1', E + 'values': [854055045839803]}}, E }
原因分析
data被定义成了类属性,而非实例属性。类属性属于整个类,所有实例会共享同一个data字典。- 测试时使用的
s3_api_key是'test',不会走__init__中self.data = read_json_s3_path(...)的分支,导致新建实例时不会重新初始化data,第一个测试修改的共享数据会被保留到第二个测试中。
解决方案
将data从类属性改为实例属性,在__init__方法中初始化每个实例的独立data:
class S3Db: fs = None s3_path = None def __init__(self, s3_api_key, s3_api_secret, bucket_name, filename, bucket_path='/'): # 初始化实例专属的data字典 self.data = {} if s3_api_key != 'test': self.fs = s3fs.S3FileSystem(s3_api_key, secret=s3_api_secret) self.s3_path = f's3://{bucket_name}{bucket_path}{filename}' self.data = read_json_s3_path(self.fs, self.s3_path) pass def increment_timed_counter(self, counter_name: str): ...
修改后每个S3Db实例都会拥有独立的data字典,测试之间不会再互相影响。
内容的提问来源于stack exchange,提问作者Edy Bourne
相关产品推荐
相关产品推荐

