Question

I am used to test drive my code. Now that I am new to Go I am trying to get it right as fast as possible. I am using the testing package in the standard library which seem to be good enough. (I also like that it is not yet another external dependency. We are currently at 2 dependencies overall - compared to any Java- or Ruby project.....) Anyways - it looks like an assert in golang looks like this:

func TestSomething(t *testing.T) {
  something := false
  if something {
    t.Log("Oh noes - something is false")
    t.Fail()      
  }
}

I find this verbose and would like to do it on one line instead:

Assert( something, "Oh noes - something is false" )

or something like that. I hope that I have missed something obvious here. What is the best/idiomatic way to do it in go?

UPDATE: just to clarify. If I was to do something like this:

func AssertTrue(t *testing.T, value bool, message string) {
  if value {
    t.Log(message)
    t.Fail()
  }
}

and then write my test like this

func TestSomething(t *testing.T) {
  something := false
  AssertTrue(t, something, "Oh noes - something is false")
}

then it would not be the go way to do it?

Was it helpful?

Solution

There are external packages that can be integrated with the stock testing framework.

One of them I wrote long ago, gocheck, was intended to sort that kind of use case.

With it, the test case looks like this, for example:

func (s *Suite) TestFoo(c *gocheck.C) {
    // If this succeeds the world is doomed.
    c.Assert("line 1\nline 2", gocheck.Equals, "line 3")
}

You'd run that as usual, with go test, and the failure in that check would be reported as:

----------------------------------------------------------------------
FAIL: foo_test.go:34: Suite.TestFoo

all_test.go:34:
    // If this succeeds the world is doomed.
    c.Assert("line 1\nline 2", gocheck.Equals, "line 3")
... obtained string = "" +
...     "line 1\n" +
...     "line 2"
... expected string = "line 3"

Note how the comment right above the code was included in the reported failure.

There are also a number of other usual features, such as suite and test-specific set up and tear down routines, and so on. Please check out the web page for more details.

It's well maintained as I and other people use it in a number of active projects, so feel free to join on board, or follow up and check out the other similar projects that suit your taste more appropriately.

For examples of gocheck use, please have a look at packages such as mgo, goyaml, goamz, pipe, vclock, juju (massive code base), lpad, gozk, goetveld, tomb, etc. Also gocheck, manages to test itself. It was quite fun to bootstrap that.

OTHER TIPS

But when You try write test like Uncle Martin, with one assert in test and long function names, then simple assert library, like http://github.com/stretchr/testify/assert can make it much faster and easier

I discourage writing test in the way you seem to have desire for. It's not by chance that the whole stdlib uses the, as you call it, "verbose" way.

It is undeniably more lines, but there are several advantages to this approach.

If you read Why does Go not have assertions? and s/error handling/test failure reporting/g you can get a picture of why the several "assert" packages for Go testing are not a good idea to use,

Once again, the proof is the huge code base of the stdlib.

The idiomatic way is the way you have above. Also, you don't have to log any message if you don't desire.

As defined by the GO FAQ:

Why does Go not have assertions?

Go doesn't provide assertions. They are undeniably convenient, but our experience has been that programmers use them as a crutch to avoid thinking about proper error handling and reporting. Proper error handling means that servers continue operation after non-fatal errors instead of crashing. Proper error reporting means that errors are direct and to the point, saving the programmer from interpreting a large crash trace. Precise errors are particularly important when the programmer seeing the errors is not familiar with the code.

We understand that this is a point of contention. There are many things in the Go language and libraries that differ from modern practices, simply because we feel it's sometimes worth trying a different approach.

UPDATE
Based on your update, that is not idiomatic Go. What you are doing is in essence designing a test extension framework to mirror what you get in the XUnit frameworks. While there is nothing fundamentally wrong, from an engineering perspective, it does raise questions as to the value + cost of maintaining this extension library. Additionally, you are creating an in-house standard that will potentially ruffle feathers. The biggest thing about Go is it is not C or Java or C++ or Python and things should be done the way the language is constructed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top