Got a pre-commit hook that runs JUnit 5 tests? Add “Greencently” to your build. Your workflow doesn’t change. Nobody needs to learn anything. Commits finish faster.
Your intention is to commit only code that passes tests. The purpose of the pre-commit hook is to help you carry out your intention. Greencently updates a timestamp file on each green and complete test run. If the timestamp isn’t recent enough, you forgot to run the tests; the pre-commit hook will catch the mistake. If the timestamp is recent enough, the pre-commit hook might have other important jobs, but running the same tests on the same code isn’t one of them.
With friction reduced, maybe you’ll find yourselves committing more often. With time and energy saved, maybe you’ll invest in further test speedups.
All tests green? Commit now, quickly, with Greencently.
Endorsements
Completely antithetical to test-driven development.
Please do not use and do not advertise that extension. It’s going to cause damage to your teams and others’.
— Andrea L. on LinkedIn
I’m as yet unable to imagine why or how, but if anything happens to prove him right, do let us all know.
When not to try
No appreciable benefit if…
- You’re not using JUnit 5 (for now — other integrations are very desired), and/or
- You don’t have or want a pre-commit hook that runs the tests, and/or
- Your complete test suite runs in microseconds (nice!), and/or
- You commit 2-3 times per day and that’s totally fine
Bad tradeoff if…
- In your context it somehow adds more risk than it mitigates, and/or
- The behavior change you want to see first is something other than “smaller, more frequent commits”, and/or
- You were hoping to introduce something revolutionary, or at least challenging for people to adjust to
How to try
- Add to your
build.gradle.kts
(see Maven Central for more details):dependencies { testRuntimeOnly("com.schmonz:junit-greencently:LATEST_VERSION_HERE") } tasks.withType<Test> { jvmArgs("-Djunit.jupiter.extensions.autodetection.enabled=true") maxParallelForks = 1 // until we know how to combine results from Gradle's Test Executors }
- Add to your
.gitignore
:*when-all-tests-were-green*
- Run all your tests greenly
- Watch
.when-all-tests-were-green-junit5
appear at the top level of your repo (while not appearing ingit status
) - Check its modification time in your pre-commit hook, perhaps like so:
#!/bin/sh all_tests_were_recently_green() { thenstamp=$(date -r .when-all-tests-were-green-junit5 '+%s' 2>/dev/null || echo 0) nowstamp=$(date '+%s') secondsago=$(expr ${nowstamp} - ${thenstamp}) [ ${secondsago} -lt 30 ] } if all_tests_were_recently_green; then ./gradlew clean build -x test else ./gradlew clean build fi