Possible extension of the testing package

186 views
Skip to first unread message

mdwha...@gmail.com

unread,
Aug 13, 2015, 3:51:28 PM8/13/15
to golang-dev
The testing package establishes a simple convention for declaring tests for `go test` to find and run:


func TestFoo(*testing.T) {
    state = NewSomethingToTest()
    if !state.Foo() {
        t.Error(...)
    }
}

func TestBar(*testing.T) {
    state = NewSomethingToTest()
    if !state.Bar() {
        t.Error(...)
    }
}

func TestBaz(*testing.T) {
    state = NewSomethingToTest()
    if !state.Baz() {
        t.Error(...)
    }
}


Running the tests produces something akin to the following output:


$ go test -v
=== RUN TestFoo
--- PASS: TestFoo (0.01s)
=== RUN TestBar
--- PASS: TestBar (0.02s)
=== RUN TestBaz
--- PASS: TestBaz (0.03s)
PASS
ok  my/package/name  0.06s


I'd like to see the following convention also allowed:


type MyTests struct {
    *testing.T // embed all the goodness offered by *testing.T (t.Error(), t.Skip, etc...)

    state SomethingToTest
}

func (t *MyTests) Setup() {
t.state = NewSomethingToTest()
}

func (t *MyTests) TestFoo() {
    if !t.state.Foo() {
        t.Error(...)
    }
}

func (t *MyTests) TestBar() {
    if !t.state.Bar() {
        t.Error(...)
    }
}

func (t *MyTests) TestBaz() {
    if !t.state.Baz() {
        t.Error(...)
    }
}


Which could produce something like the following output:


$ go test -v
=== RUN Test_MyFixture_Foo
--- PASS: Test_MyFixture_Foo (0.01s)
=== RUN Test_MyFixture_Bar
--- PASS: Test_MyFixture_Bar (0.02s)
=== RUN Test_MyFixture_Baz
--- PASS: Test_MyFixture_Baz (0.03s)
PASS
ok  my/package/name  0.06s



Included in this extension could be the idea of optional setup and teardown methods to be run before and after (respectively) each test method. Ideally, each test method would be invoked on a unique instance of MyFixture which is created just for that test method.

I've already implemented something very close to this--it's call gunit (as in 'g'-unit). The only thing I don't like about my implementation is that in order for `go test` to find and run the test methods on the test structs, I have to run `go generate` first, which calls a command I've also written as part of the gunit project which generates compatible Test functions that instantiate the struct and then call the test methods (along with defined setups and teardowns). I'd like to be rid of the `go generate` step to achieve struct-scoped test methods. One benefit here is that you can trivially extract other useful methods on that struct that are called from the test methods. It is trivial because you don't have to pass in any local state to those methods--all the state is already declared on the struct as fields.

Here's an example of this style of fixture implemented using the gunit package. (Please pardon our non-idiomatic use of 'this' for receiver names and "assertion"-like helper functions.)

See the README of the gunit project for additional explanation as well as this gist for another example of what could be done with this addition.

Thanks for the testing package and thanks for reading!

Austin Clements

unread,
Aug 13, 2015, 4:26:56 PM8/13/15
to mdwha...@gmail.com, golang-dev
Hi Michael. This seems like a good candidate for the new proposal process: https://github.com/golang/proposal/blob/master/README.md

--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

mdwha...@gmail.com

unread,
Aug 13, 2015, 5:31:51 PM8/13/15
to golang-dev, mdwha...@gmail.com
Ok, I'll open a new github issue to start the process. Stay tuned...
Reply all
Reply to author
Forward
0 new messages