Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add flag to clean up postgres databases. #204

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

DanCardin
Copy link
Contributor

@DanCardin DanCardin commented Mar 7, 2024

Fixes #202.

  • Adds cleanup_databases=False argument. Default False to retain original behavior
  • Cleans up individual test databases during the natural fixture teardown phase, fairly straightforward
  • Cleaning up the template databases is a lot more involved and a majority of the refactor being done by this PR
    • Internally we now create 1 new (randomly named) session fixture per create_postgres_fixture call
    • that gets hackily injected into the calling code's global scope under a uniqified name
    • we then use the resultant fixture to provide us a scope from which we can perform tear-down logic to delete the template databases at exit.

It probably makes sense to follow this up with a pmr --cleanup or the like kind of CLI extension, that more directly just deletes all pmr_* named databases. If there's a hard test failure, you enter a debugger and exit uncleanly, you ctrl+c enough, or various other means: it's still fairly straightforward to end up with left over databases.

1 unresolved issue:

  • pytest-asyncio has all sorts of weird stuff going on in both prior versions that people claim works, and the new versions are just broken apparently. In either case, I wasn't able to find a way that seemed to work reliably in async code (at least, using pytest-asyncio). Only affecting template database cleanup.

    So unless/until there's a different plugin, or they resolve their stuff and we start requiring a much more recent minimum version bound for it after they do, template database cleanup will mean that async code wont share templates (and thus will be slower). Could be worse, but isn't ideal.

@josiah-lunit
Copy link

For issues regarding pytest-asyncio (which I agree is not in a good state now), I find using nest_asyncio resolved some of the issues I had with different scoped fixtures.

@DanCardin
Copy link
Contributor Author

A potentially good callout, although it'd mean it would mandate use of it for downstream users, not just our tests.

The current test failures seem to not be related at least...which makes sense, since i'm bypassing the new fixture for async code.

They're also not a failure I'm experiencing locally...

@DanCardin DanCardin force-pushed the dc/database-cleanup branch 10 times, most recently from fffe2ff to 459b8a8 Compare April 15, 2024 21:25
@DanCardin DanCardin force-pushed the dc/database-cleanup branch 12 times, most recently from 909dc5c to fc01609 Compare July 2, 2024 16:18
@coveralls
Copy link

coveralls commented Jul 2, 2024

Pull Request Test Coverage Report for Build 9764591739

Details

  • 155 of 157 (98.73%) changed or added relevant lines in 6 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+1.5%) to 90.894%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/pytest_mock_resources/fixture/postgresql.py 123 125 98.4%
Totals Coverage Status
Change from base Build 9589737334: 1.5%
Covered Lines: 1609
Relevant Lines: 1753

💛 - Coveralls

@DanCardin
Copy link
Contributor Author

Sigh, the moment I got passing CI, I've now realized that there's a pytest deficiency that seems not to allow me to dynamically create new fixtures with variable dependent fixtures. at least not ergonomically. What i assume must be happening is that this is now forcing unnecessary database creations due to that.

I suppose I'll have to revise this further...

@josiah-lunit
Copy link

Sigh, the moment I got passing CI, I've now realized that there's a pytest deficiency that seems not to allow me to dynamically create new fixtures with variable dependent fixtures. at least not ergonomically. What i assume must be happening is that this is now forcing unnecessary database creations due to that.

I suppose I'll have to revise this further...

I appreciate the effort! For now we are using something like the following to scan for pmr resources and drop them after the testing suite is complete:

async def clean_databases(engine: AsyncEngine):
    """
    Needed because `pytest-mock-resources` doesn't clean up after itself if you connect to an existing database.
    See https://github.com/schireson/pytest-mock-resources/issues/202
    """
    async with engine.connect() as conn:
        query = "SELECT datname FROM pg_database WHERE datname LIKE 'pytest_mock_resource%';"
        databases = await conn.scalars(text(query))
        for database in databases:
            try:
                query = f"DROP DATABASE {database}"
                await conn.execute(text(query))
            except Exception as e:
                logging.error(f"Could not drop database {database}: {e}")
                raise e
        query = "SELECT datname FROM pg_database WHERE datname LIKE 'pmr_template_pg_%';"
        templates = await conn.scalars(text(query))
        for template in templates:
            try:
                query = f"DROP DATABASE {template}"
                await conn.execute(text(query))
            except Exception as e:
                logging.error(f"Could not drop template {template}: {e}")

@pytest_asyncio.fixture(scope="session")
async def alembic_engine(postgres_async_alembic: AsyncEngine, postgres_async_teardown: AsyncEngine):
    yield postgres_async_alembic
    await postgres_async_alembic.dispose()
    await clean_databases(postgres_async_teardown)

@DanCardin
Copy link
Contributor Author

Well amusingly we recently ran into issues in CI related to this at $job, so it's now in our critical path 😆. I think the solution for vanilla test databases is a lot simpler, and will be my shorter term solution here. It's the template databases which are the complicated problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

create_postgres_fixture doesn't clean up after running tests.
3 participants