The testing feature you’ve been missing in pure Go / Golang

Roman Sheremeta
3 min readNov 25, 2022

--

If you’ve started writing automation tests in Go after switching from another programming language like me, even there is no matter whether you’re an apologist of Java, C#, Python, JS etc — I bet you’ve been missing some test runner features here in Go like setting up pre-conditions before the entire Test Suite execution and cleaning up the data afterwards. Or performing the same setup/cleanup actions for each and every Test and avoiding of applying viral anti-pattern called Copy-paste programming.

I bet this article and the solution below that’s what you’ve been looking for so long!

TL;DR

All code snippets used in the article are in my Github gist here

Go has built-in test runner which is nothing but testing pkg, so there is no need to pull up a separate framework/library like in another programming languages.

Important! All code snippets should be put inside of the ~/tests dir!

BeforeSuite & AfterSuite

Let’s build the mechanism which will be invoked before and after the entire Test Suite execution.

Firstly, let’s create certain functions for needed actions:

beforeSuite() and afterSuite() funcs

For the invocation of functions implemented above we’ll be using the power of pure Go itself — TestMain() function. Create a func with the following signature:

func TestMain(m *testing.M) {}

Filling it up:

TestMain() func filled up

BeforeEach & AfterEach

As you might know, Go doesn’t have annotations mechanism at all, unlike Java, C# and others. So we’re restricted a bit, but that won’t prevent us from maturing the capabilities and power of the testing possibilities here in Go!

Let’s create some fake dummy functions (like we’ve created above) which will be invoked before and after each and every Test function aka Test scenario.

beforeTest() and afterTest() funcs

Now we gonna implement a crucial stuff over here — a function, which will take two params of a func type and will return a func with the func param inside. Sound a bit complicated, yeah? Nothing hard, just have a peek at the function below:

forEach() func

Now we need to declare a var to assign the forEach() func with passing created functions above into it:

var Run = forEach(beforeTest, afterTest)

Putting it all together

The last step is to create a handful test cases with usage of Run variable (with before&after each func wrapped inside) to check out the code. Let’s fail the TestC() function deliberately to get an evidence that the afterEach part will be invoked in case of failure as well.

test functions

Now we’re all set to run it via Terminal using go test command and see the results:

This function is invoked BEFORE the entire testing suite!
=== RUN TestA
This is a pre-condition executed BEFORE each Test!This is a TestA() test caseThis is a post-condition executed AFTER each Test!
--- PASS: TestA (0.00s)
=== RUN TestB
This is a pre-condition executed BEFORE each Test!This is a TestB() test caseThis is a post-condition executed AFTER each Test!
--- PASS: TestB (0.00s)
=== RUN TestC
This is a pre-condition executed BEFORE each Test!This is a TestC() test caseThis is a post-condition executed AFTER each Test!
--- FAIL: TestC (0.00s)
FAILThis function is invoked AFTER the entire testing suite!Process finished with the exit code 1

Awesome! Everything works as intended! We expected the exact output!

Again, source code demonstrated in the article is HERE

Thank you note

Thanks for the reading/viewing/listening the article, I hope my solution is a useful one and applicable for you.

Feedbacks and subscriptions are appreciated!

Also, I’d invite you to check out another articles from myself:

--

--