The recommended way by numpy to create random numbers is to create a np.random.Generator like this
import numpy as np
def foo():
# Some more complex logic here, this is the top level method that creates the rng
rng = np.random.default_rng()
return rng.random()
Now suppose I am writing tests for my code base, and I need to seed the rng for reproducible results.
Is it possible to tell numpy to use the same seed every time, regardless where default_rng() is called?
This is basically the old behavior of np.random.seed().
The reason I need this is because I have many such tests and would have to mock the default_rng call to use a seed for each of them since in pytest you have to mock at the location where something is being used, not where it is defined. Thus mocking it globally like in this answer does not work.
With the old way, one could define a fixture that sets the seed for each test automatically inside conftest.py like this:
# conftest.py
import pytest
import numpy as np
@pytest.fixture(autouse=True)
def set_random_seed():
# seeds any random state in the tests, regardless where is is defined
np.random.seed(0)
# test_foo.py
def test_foo():
assert np.isclose(foo(), 0.84123412) # That's not the right number, just an example
With the new way of using default_rng, this seems to no longer be possible.
Instead I would need to put a fixture like this in every test module that requires the rng to be seeded.
# inside test_foo.py, but also every other test file
import pytest
from unittest import mock
import numpy as np
@pytest.fixture()
def seed_default_rng():
seeded_rng = np.random.default_rng(seed=0)
with mock.patch("module.containing.foo.np.random.default_rng") as mocked:
mocked.return_value = seeded_rng
yield
def test_foo(seed_default_rng):
assert np.isclose(foo(), 0.84123412)