Description
Python Version
3.9.0
pytest Version
7.2.2
Package Version
3.12.0
Description
In our tests, we regularly create mocked AWS S3 buckets with random 16 character names. e.g.
bucket_name = ''.join(random.choice(string.ascii_letters) for i in range(16))
Those buckets are created via a fixture that yields a function called create_mock_bucket()
and the scope of that fixture is set to the default (per function).
@pytest.fixture
def mock_s3_context():
"""Everything under/inherited by this runs in the mock_s3 context manager"""
with mock_s3():
# Yield the (mocked) s3 Resource object
# (see boto3 docs: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html)
yield boto3.resource('s3')
@pytest.fixture
def create_mock_bucket(mock_s3_context):
"""Returns a function that allows dynamic creation of s3 buckets with option to specify the name.
Note: if the bucket already exists, this doesn't overwrite it. Previous contents will remain.
Caution: If you create multiple objects at the same location, you may get conflicts"""
s3 = mock_s3_context
def _create_bucket(bucket_name: str = None):
"""Creates a mock bucket, optionally with a custom name.
"""
if not bucket_name:
bucket_name = ''.join(random.choice(string.ascii_letters) for i in range(16))
print(f"Generated random bucket name: {bucket_name}")
bucket = s3.Bucket(bucket_name)
if not bucket.creation_date: # If bucket doesn't already exist
bucket.create()
print(f"Created mock S3 bucket {bucket}.")
return bucket
yield _create_bucket
When pytest-randomly is enabled, those bucket names all end up being exactly the same string for a given pytest execution. When run with -p no:randomly
, the bucket names appear random as expected and all the tests pass. I suspect that the random seed for pytest-randomly is somehow leaking over into seeding our call to random.choice but that is purely speculation.
NB: This has exposed another weakness in our testing, namely that our mocked buckets are persisting between tests. I'm running that down separately but the behavior described above seems unintentional.