Test Driven Development With Golang on OSX

How to do Test Driven Development with Go on OSX

You are looking to start using TDD, but you want a simple tool setup to automate running your tests and giving you the red green display. I have been trying out different setups for programming Go with TDD on OSX, and I am going to show you one that is easy to setup. This post will cover the setup you need to code in one screen and have your tests automatically run and output in another screen. By automatic, I mean when you save a file, it automatically triggers your tests to run in the other window with colorized output.

This same technique will work for other programming languages on OSX as well. I want to cover one possible setup that is not only simple but also flexible. It is flexible enough that you can also use it in linux or windows if you want a consistent development setup across all your environments. I use iTerm 2 as my terminal on OSX, and vim as my editor. I will assume you are using these, that you are using homebrew, and that you are familiar with the commandline. I also use tmux, but this technique is flexible and will work without tmux if you do not use it.

The first tool that you will need is called fswatch. This utility will allow you to watch a directory and trigger an event when files are changed. On linux, you would want to install a different utility for this purpose called inotify-tools. You can install fswatch on OSX with homebrew with the command:

brew install fswatch 

Next, you want to use a colorizer to color the output of your tests. To keep dependencies minimal, you could use the following command with sed to add color escape sequences to your testing output:

 go test | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/''

But, I wanted more flexibility with my color options, so I chose to use a utility called grc to colorize my test output. I am going to summerize a stackoverflow answer on how to set it up for Go testing. First, you will need Python 3 for this utility.

If you do not have Python 3, run the command:

brew install python3 

If you run the command:

which python3 

you should see a path returned. If you do not, you may want to create a symbolic link from where homebrew installed Python 3 in the /usr/local/Cellar/python/3.x.y/bin/ directory to the /usr/local/bin/python3 in my case the version of python in the Cellar area is 3.6.5 so I would run the command

ln -s /usr/local/Cellar/python/3.6.5/bin/python3 /usr/local/bin/python3 

Assuming you have /usr/local/bin in your environment path, you can now test it with the command

python3 --version

Once you have Python 3 installed, it is time to install grc. Run the command:

brew install grc

Next, you will have to setup a grc config file and a pattern file for go tests

Make the following directory ~/.grc

 mkdir ~/.grc 

Create a config file specific to your testing command, go test, called ~/.grc/grc.conf with the following contents:

\bgo.* test\b
conf.gotest

Next create a pattern matching file ~/.grc/conf.gotext with the following contents:

regexp==== RUN .*
colour=blue
-
regexp=--- PASS: .*
colour=green
-
regexp=^PASS$
colour=green
-
regexp=^(ok|\?) .*
colour=magenta
-
regexp=--- FAIL: .*
colour=red
-
regexp=[^\s]+\.go(:\d+)?
colour=cyan

To test this technique out without tmux, open a second iTerm 2 window with the Command + n buttons. If you are using tmux, split your window into two panes. In each window or pane, navigate to where your code and tests are. In the test window or test pane run the following command to monitor for source code changes:

fswatch -o . | (while read; do grc go test; done)

This will watch that current directory for any file changes and run the grc go test command each time it detects a change. The grc will colorize the output of the go test output.

Now try it out, if you are using tmux, go to your other pane and navigate to where the tests and code are. If you are using a separate iTerm 2 window, then open a new window and navigate to where your code and tests are. Open a code file with vim and then perform a save. You test window should show go test running with colorized output.

If you decided not to use the grc utility and wanted to stick with just color escape sequences, you would us the following command:

fswatch -o . | (while read; do go test | sed ''/PASS/s//$(printf "\033[32mPASS\033[0m")/'' | sed ''/FAIL/s//$(printf "\033[31mFAIL\033[0m")/''; done)

You can put either of these methods into a bash script in your path to save on having to type it each time. I put mine in a script called go-tdd. Now when ever I am about to begin a coding session, I will open my test pane, navigate to my tests, and run the command go-tdd.

This technique can also work in linux if you program in different environments. I use it in RedHat Enterprise Linux, but I use the inotify tools instead of fswatch. With these tools the command to watch your code would be:

inotifywait -mr . -e close_write | while read path action file; do
    if [[ "$file" =~ .*go$ ]]; then
        go test
    fi
done

The previous command will look for file changes to files ending in .go and will trigger the go test command.

As I mentioned previously, this technique is flexible and will work for other programming languages. For instance, say you wanted a version of this script to run Perl tests in a standard CPAN type module layout directory structure. You could change the command to:

inotifywait -mr ./lib -e close_write | while read path action file; do
    if [[ "$file" =~ .*pm$ ]]; then
        prove -l t/*.t
    fi
done

Or if your testing Python with pytest

inotifywait -mr . -e close_write | while read path action file; do
    if [[ "$file" =~ .*py$ ]]; then
        pytest
    fi
done