Skip to content

feature - add @DatabaseCleanup test annoation to facilicate cleaning up after a test or tests#15436

Merged
jdaugherty merged 22 commits into7.0.xfrom
database-cleanup-feature
Feb 25, 2026
Merged

feature - add @DatabaseCleanup test annoation to facilicate cleaning up after a test or tests#15436
jdaugherty merged 22 commits into7.0.xfrom
database-cleanup-feature

Conversation

@jdaugherty
Copy link
Contributor

@jdaugherty jdaugherty commented Feb 22, 2026

After reviewing several of the grails-data PRs submitted by @jamesfredley I realized that a pattern we implemented in our Grails app would be beneficial for everyone: rather than use @Rollback, etc we use a clean up process that truncates all tables with data. I've extracted our internal logic into a generic spock extension & then enhanced it with the assistance of AI to be a little more generic. Only H2 & Postgres (AI did this one, while the H2 one was lifted from our internal implementation) are implemented for now.

There aren't really many dependencies with this feature. I intentionally did not depend on many grails projects to ensure it can be used to test in grails-core too. The spock extension requires @SpringBootTest to use the DefaultApplicationContextResolver to find the application context - this is added automatically by using @Integration. We could relax this requirement if a custom resolver is provided instead.

The annotation can be placed at the class level to clear all data after each test, or individually on each method - only the methods annotated will truncate the database after running. It should be rather performant since it issues truncates instead of iterating over every row (FK's etc are disabled during the cleanup process too). There's also some optional debug that can be turned on.

I'm adding this to 7.0.x since it doesn't impact any of the existing code & we can then make use of it in the various grails-data tests to be DRY. Simply annotate the test, and the database is always clean now at the start of every test - regardless of new transaction testing, etc. This also means with the combination of @Stepwise you can now test multi-transaction processes and roll back the data reliably.

Assisted-by: OpenCode <opencode@opencode.ai>
Assisted-by: Claude <claude@anthropic.com>

@jdaugherty jdaugherty force-pushed the database-cleanup-feature branch from bb469e5 to 6e7494d Compare February 22, 2026 17:50
@jdaugherty
Copy link
Contributor Author

The AI didn't do a great job on the postgres implementation. I've cleaned it up a lot and I think this should all be working / passing now. It should be ready for review.

@jamesfredley jamesfredley moved this to In Progress in Apache Grails Feb 24, 2026
jamesfredley

This comment was marked as outdated.

@bito-code-review
Copy link

Yes, that's a valid concern. The query filters tables based on row_count_estimate > 0, but since H2's row_count_estimate is an approximation, tables with actual rows might show 0 and be skipped, leaving test data behind. To address this, consider removing the row_count_estimate > 0 filter to truncate all tables in the schema, as truncating empty tables is harmless and ensures complete cleanup.

grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy

String query = "SELECT table_name, row_count_estimate FROM information_schema.tables WHERE table_schema = '${schemaName}'" as String
            sql.eachRow(query) { GroovyResultSet row ->
                String tableName = row['table_name'] as String
                stats.addTableRowCount(tableName, row['row_count_estimate'] as Long)
                log.debug('Truncating table: {}', tableName)
                sql.executeUpdate("TRUNCATE TABLE \"${tableName}\"" as String)
            }

@jdaugherty jdaugherty merged commit a0e1b37 into 7.0.x Feb 25, 2026
29 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in Apache Grails Feb 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants