Skip to content

Random seed appears to also seed other random() calls #531

Closed
@medley56

Description

@medley56

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions