Same dict variable value updated between tests in pytest

I have 2 tests that use the same dict for data. But when I update something in 1 test that will affect the second test. I want them to be independent.

data.py

a = {"data": {'data1': 'mydata',
              'data2': 'mydata2'
              }
     }

test_mytest.py

from data import a
import pytest

def test_1():
    test_data = a['data']
    test_data['data1'] = 'new data'


def test_2():
    test_data = a['data']
    assert test_data['data1'] == 'mydata'

When I run test_2 only it passes. But when I run both using pytest, test_2 is failing.
I want them to be passed when running together. Also, what can be the best way of doing this?

>Solution :

Global mutable state is something best avoided in testing. There are no guarantees about the order in which your tests will be executed, and sharing state between tests can prevent speeding up the test suite by using a plugin like pytest-xdist (which executes tests in parallel).

Instead, I would do it like this, giving each test a copy of the data by using a fixture

import pytest

@pytest.fixture
def a():
    return {
        "data": {
            "data1": "mydata",
            "data2": "mydata2",
        }
    }

def test_1(a):
    test_data = a['data']
    test_data['data1'] = 'new data'

def test_2(a):
    test_data = a['data']
    assert test_data['data1'] == 'mydata'

If the data must be externally available:

# in conftest.py

import pytest
import copy

from data import a as a_source

@pytest.fixture
def a():
    return copy.deepcopy(a_source)

Note that if tests need to modify data.a itself, rather than providing a modified copy of a when calling a function for example, then you may prefer to simply patch the object in each test using pytest’s monkeypatch fixture or using pytest-mock plugin, e.g.:

def test_2(mocker):
    mocker.patch("data.a", {"k": "v"})
    ...

This kind of runtime patching only works if the contents of data.a are accessed by the code under test (i.e. not at import time). If it was already accessed before your test runs, then you’re too late to patch.

Leave a Reply