You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 18:32:51