Gocheck: A rich testing library for Go

It’s time to release my “side project” which has been evolving over the last several months: Gocheck. I’ve been watching Go for some time, and have been getting more and more interested in the language. My first attempt to write something interesting in it made it obvious that there would be benefit in having a richer testing platform than what is available in the standard library. That said, I do understand why the standard one is slim: it’s pretty minimalist, because it’s used by itself to test the rest of the platform. With Gocheck, though, I don’t have that requirement. I’m able to trust that the standard library works well, and focus on having features which will make me more productive while writing tests, including features such as:

  • Better error reporting
  • Richer test helpers: assertions which interrupt the test immediately, deep multi-type comparisons, string matching, etc
  • Suite-based grouping of tests
  • Fixtures: per suite and/or per test set up and tear down
  • Management of temporary directories
  • Panic-catching logic, with proper error reporting
  • Proper counting of successes, failures, panics, missed tests, skips, etc
  • Support for expected failures
  • Fully tested (yes, it manages to test itself reliably!)

That last point was actually quite fun to get right. It’s the first time I wrote a testing framework from the ground up, and of course I wanted to have it fully tested by itself, but I didn’t want to simply use a foreign testing framework to test it. So what it does is basically to have a “bootstrapping” phase, which ensures that the very basic parts of the library work, without trusting on pretty much any internal functionality (e.g. it verifies the number of executed functions, and works with low-level panics). Then, once the lower layers are trusted, tests for higher functionality was introduced by building on the trusted bits.

Gocheck is actually mostly ready for some time now, but I’ve been polishing edges with some real world usage before releasing it. Since both the real world usage and Gocheck itself are side projects, you can imagine that took a bit of time. Today, though, I’ve managed to fix the last few things which were bothering me, so it’s up for world consumption.

I hope you enjoy it, and make some good use of it so that we can all have more reliable software. ;-)

This entry was posted in Architecture, Go, Project, Test. Bookmark the permalink.

4 Responses to Gocheck: A rich testing library for Go

  1. “My first attempt to write something interesting in it made it obvious that there would be benefit in having a richer testing platform than what is available in the standard library. ”

    I had exactly the same thoughts when Go was released, so a testing framework was the first thing I made. You might be interested in it https://github.com/orfjackal/gospec

  2. Hi Esko,

    As you can imagine, I’ve now got my needs quite well covered with Gocheck, but I appreciated having a look at the documentation and example usage. One thing that I quite enjoyed in your approach, actually, is the way you’ve used matchers as arguments rather than individual helper functions. I was struggling a bit with the explosion of helper functions that was about to happen, and was also quite unhappy about having to test the output of these functions together with the actual matching logic. Separating those out will simplify considerably the design, so I’ll migrate into something close to that. Thanks for pointing it out!

  3. Another benefit of having matchers as arguments is that it’s easy to add more custom matchers. The users of the testing library can create their own application-specific matchers.

  4. I wrote a simple test library for GoLightly to beef up gotest. It’s closure-driven for simplicity with the main innovation being the inclusion of table-driven testing so I can succinctly express boundary value tests etc. Gotest is surprisingly forgiving of this sort of abuse :)

Leave a Reply

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