Closed dmoles closed 3 years ago
@dmoles - That's a good question. It's one I've tinkered with before, but haven't gone the distance to implement. Currently, the reflection code that instantiates new instances of the fixture doesn't look for types embedded on the fixture and so they don't get initialized (hence the panic). One way to sort of get what you're going for is to do something like this:
type MyFixture {
*gunit.Fixture // embed gunit fixture alongside your tempdirFixture.
tempdirFixture
}
func (this *MyFixture) Setup() {
this.tempdirFixture = & tempdirFixture{Fixture: this.Fixture}
this.tempdirFixture. SetupTempDir()
}
func (this *MyFixture) Teardown() {
this.tempdirFixture.TeardownTempDir()
}
In this case because of the simplicity of the embedded tempdirFixture
, this approach isn't a big win since you'd have to include the Setup()
and Teardown()
methods on any type that embeds tempdirFixture
.
I'm not opposed to exploring an implementation of your original use case of embedding a type that itself embeds the *gunit.Fixture
. Feel free to submit a PR or, I might experiment a bit, depending on available time for such tinkering. Surprisingly for us, the need for this kind of feature/approach hasn't come up much over the last few years so I haven't felt a strong need to extend the software.
@dmoles
As I can see it's no longer a problem with go 1.13.1
and github.com/smartystreets/gunit v1.1.1
Example:
func TestEmbeddedFixture(t *testing.T) {
gunit.Run(new(MyFixture), t)
}
// Embeddable sub-fixture for temporary directories
type tempdirFixture struct {
*gunit.Fixture
tempDir string
}
func (f *tempdirFixture) SetupTempDir() {
tempDir, err := ioutil.TempDir("", "tempdirFixture")
f.So(err, should.BeNil) // or assertions.ShouldBeNil(err)
f.tempDir = tempDir
}
func (f *tempdirFixture) TeardownTempDir() {
err := os.RemoveAll(f.tempDir)
f.So(err, should.BeNil) // or assertions.ShouldBeNil(err)
}
type MyFixture struct {
tempdirFixture
}
func (this *MyFixture) Test1() {
this.So(1, should.Equal, 1)
}
Output:
=== RUN TestEmbeddedFixture
=== PAUSE TestEmbeddedFixture
=== CONT TestEmbeddedFixture
=== RUN TestEmbeddedFixture/Test1
=== PAUSE TestEmbeddedFixture/Test1
=== CONT TestEmbeddedFixture/Test1
--- PASS: TestEmbeddedFixture (0.00s)
--- PASS: TestEmbeddedFixture/Test1 (0.00s)
test_case.go:67: Test definition:
PASS
Process finished with exit code 0
@dmoles - Are you saying it now works in go 1.13.1 and gunit v1.1.1? What versions were you using before? (What changed??)
I have a couple of tests that require temporary directories. I tried to set up a shared fixture along these lines:
However, when I try embedding this in my test fixture proper, e.g.
I inevitably get either
panic: reflect: indirection through nil pointer to embedded struct
orPANIC: runtime error: invalid memory address or nil pointer dereference
, sometimes in a test method, sometimes intempdirFixture.SetupTempDir()
, sometimes deep in reflection code where I can't follow what it's doing, depending on exactly how I set up the embeds and initialize the fixtures. (I've tried embedding*tempdirFixture
instead oftempdirFixture
; I've tried moving*gunit.Fixture
fromtempdirFixture
to the test fixture proper; I've tried various combinations ofnew()
and&Type{}
.)Is this a use case you've ever tried to cover with gunit? And if so, what's the right way to do it?
Obviously I can give up and manually initialize things, but I'd like to take advantage of gunit's reflection-based setup/teardown autodetection.