Ok, maybe that was extreme, but testing is such an important process since it helps us verify the system works as intended. There are tons of information readily available on the internet - from books to blog posts - that describes the whys of testing.
Being a big fan of software testing, it was one of the first things i was eager to learn when i started learning Go. The Go team made this even much easier by providing a testing framework out of the box and a simple command to run them all go test. Coming from PHP, this is a relieve since PHPunit, the testing framework is userland code and you have to add this as a (dev)dependency to every project. But in Go, all i do is append _test to a file name and it’s content becomes a testsuite.
While testing handlers (or anything in general), all we want to do is :=
Arrange: Run some set up.
Act: Run the part of the code you want to test.
Assert: Compare your expected output to what was returned. Here, we would manually inspect the HTTP status code and the response body - we are returning JSON. Inspecting the persistence layer can also be a thing.
To put this idea through, we would be building a simple api for a dummy blog. To keep things extremely simple, the data would be held in-memory and it would have a very limited feature set ;
Posts can be created.
Posts can be deleted.
A single post can be viewed.
All posts can be viewed.
For this project, we would be making use of gorilla/mux for the routing. As we add one route and handler, we would write it’s equivalent tests
Nothing here, just yet another web server we created. So let’s implement the handlers.
You might want to comment out unimplemented handlers so an error shouldn’t occur.
Create a test file called main_test.go
I have laced the test with comments in other for it to be exlanatory but what we are basically doing here is making sure our handler returns the correct HTTP status code and correct JSON. If you are persisting stuffs to a store, you might as well want to check that to make sure all is well.
The main thing to note here is we made use of a ResponseRecorder, this is key to testing HTTP In Go since it allows us inspect the response.
We have a dependency on github.com/stretchr/testify/assert, it’s more like getting the xUnit test style and that is just my personal preference. You can achieve the same with reflect.DeepEqual.
Remember to tun go test.
To fetch a blog post via the link /posts/4, we would have an implementation like :
To test this, we have to verify the returned JSON is the same as what we have in the array.
This is quite diffferent from what we had in the previous test.
Why instantiate a gorilla/mux instance when we could have simply done http.HandlerFunc(handler).ServeHTTP(rr,req) ? This is because in the handler implementation, we had to retrieve the url param. Not instantiating mux would mean we wouldn’t be able to fetch the url parameter. Heck, we’d even get a nice panic. We don’t want that.
Apart from that, nothing changed. We still called mux’s ServeHTTP method with the response recorder, checked the status and asserted the return JSON.
Tests are supposed to cover both positive and negative inputs. In the articleHandler, we have a check that says If post cannot be found, throw a 404 error. How are we sure that works ?
That is going on fine, our tests are passing but we still have un covered feature sets. Our api cannot handle posts creation and deletion right now.
For this features, i have added only very little tests (positive input only). You might want to try out writing the tests with negative inputs. Just remember that the github repo has the test suite heavily covered with both positive and negative input if you need a place to look.
The following code block would include the production code for both features while the second one would contain the tests.
This isn’t diffferent from what we have done earlier on. We inspect everything that matters to us. For example, we took a peek into the in memory data store in other to truly confirm our handler was properly deleting the post.
For kicks, you can even check the store doesn’t have a post with the specified key.
I love testing. Testing is fun. Go even makes it much more fun by incorporating this tools into our workflow.
I hope this post helps someone confused about how to get started with testing.