May 15, 2014

Automatically test your dirty Grails classes

Summary

When refactoring code in bulk, I occasionally run into a scenario where it’s simpler to make the change all at once and run the tests afterwards than it is to test after every iteration of the change. Some examples include renaming method or variable names (or anything with an IDE’s find-and-replace feature), changing internationalized text, or adding/removing a method call. However, the full test suite for a project can take a very long time to run, so I initially test only the modified (and related) classes.  I figured it would be nice to have a script automatically test the modified files for me, so I tried my hand at writing one.

Granted, this is my first bash script so I may have missed some standards/conventions, but I did my best to keep up with best practices. The script will grab the list of modified files from git, parse their “base” file names, and then pass those names appended with the wildcard character (*) to grails test-app. It’s pretty simple, and I wasn’t able to find any scripts that already did this, so I figured it would be a good chance to brush up on my bash scripting skills.

Source code

Without further ado, here is the script itself:

Simply copy that into a .sh file, chmod +x permissions to it, and (optionally) add an alias (e.g. alias gitTestModified=’~/scripts/gitTestModified.sh’) in your .bashrc to easily invoke it. So with our example, we could call it with:

gitTestModified

Usage

By default the script takes no arguments and simply checks the following directories for modified .groovy files (as according to git diff HEAD):

grails-app src/groovy

This list can be appended simply by passing some bulk arguments to the script. For example, to check for tests that were modified as well, we can do:

gitTestModified test # Add 'test' to the directories to search for git changes

If there are modified files, the tests will be invoked.  If not, then a simple message will pop up saying so.

-r Remove default directories

gitTestModified also allows a -r flag to exclusively check the directories passed in, overriding the defaults in the script. So the following call would look ONLY in the ‘test’ directory:

gitTestModified -r test # Only check the 'test' directory for git changes

Once changed files are found and parsed, the filenames are appended with the wildcard (*) and passed to grails test-app. Since the typical Grails test naming convention is <filename>Spec.groovy or <filename>Tests.groovy, the wildcard will capture these test cases and automatically run them. Obviously if your project does not follow this convention, this script will not work.

-t Test options

If we want to pass additional arguments to grails test-app, so we can for example, run only tests that failed last time, we can do so using the -t option and then providing the arguments:

gitTestModified -t "-rerun" # Only run tests that failed last time we called test-app

Since these arguments are passed directly to grails test-app, it’s best to wrap them in quotes due to the dashes and potential spaces. This also means we can append additional tests to run:

gitTestModified -t "-unit MyExtraTests.groovy"

-h Help

Finally, the script has a -h flag to display its usage information:

gitTestModified also outputs each call to grails test-app both for easier debugging and for easy copying/pasting in case you want to run the tests independently.

Caveats

The script currently only checks for .groovy files, and relies on git diff HEAD to get its list of changed files, so committed changes may not show up in that list. It only checks .groovy files (not .java), but you can change the regex variable in the script if you need Java files too. It’s also my first major bash script, so it may be a little rough around the edges. If you’d like to fork it and/or improve on it, I’ve uploaded the code on GitHub.

Happy refactoring!

Igor Shults

About the Author

Object Partners profile.
Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Android Development for iOS Developers
Android development has greatly improved since the early days. Maybe you tried it out when Android development was done in Eclipse, emulators were slow and buggy, and Java was the required language. Things have changed […]
Add a custom object to your Liquibase diff
Adding a custom object to your liquibase diff is a pretty simple two step process. Create an implementation of DatabaseObject Create an implementation of SnapshotGenerator In my case I wanted to add tracking of Stored […]
Keeping Secrets Out of Terraform State
There are many instances where you will want to create resources via Terraform with secrets that you just don’t want anyone to see. These could be IAM credentials, certificates, RDS DB credentials, etc. One problem […]
Validating Terraform Plans using Open Policy Agent
When developing infrastructure as code using terraform, it can be difficult to test and validate changes without executing the code against a real environment. The feedback loop between writing a line of code and understanding […]