func (GTestTests) SubTestSubTestScopedFixture(t *testing.T, fixtures struct {
	Dir1 string `fixture:"TmpDir"`
	Dir2 string `fixture:"TmpDir"`
	Dir3 string `fixture:"TmpDir"`
}) {
	assert.Equal(t, fixtures.Dir1, fixtures.Dir2)
	assert.Equal(t, fixtures.Dir1, fixtures.Dir3)
	info, err := os.Stat(fixtures.Dir1)
	assert.NoError(t, err)
	assert.True(t, info.IsDir())
}
For subtest scoped fixture, fixture construct will only be called once
and result will be cached for subsequent calls within the subtest
package gtest_test
import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"strings"
	"testing"
	"time"
	"go.uber.org/goleak"
	"github.com/houqp/gtest"
	"github.com/stretchr/testify/assert"
)
type UserIdFixture struct {
	Count int64
	AllocatedCount int
}
func (s *UserIdFixture) Construct(t *testing.T, fixtures struct{}) (string, interface{}) {
	s.AllocatedCount += 1
	s.Count += 1
	return fmt.Sprintf("user_%d", s.Count), nil
}
func (s *UserIdFixture) Destruct(t *testing.T, ctx interface{}) {
	s.AllocatedCount -= 1
}
type MockUser struct {
	Id string
}
type MockUserFixture struct {
	AllocatedCount int
}
func (s *MockUserFixture) Construct(t *testing.T, fixtures struct {
	UserId string `fixture:"UserId"`
}) (MockUser, interface{}) {
	s.AllocatedCount += 1
	return MockUser{
		Id: fixtures.UserId,
	}, nil
}
func (s *MockUserFixture) Destruct(t *testing.T, ctx interface{}) {
	s.AllocatedCount -= 1
}
type MockComment struct {
	Creator MockUser
	Content string
	Created time.Time
}
type MockCommentFixture struct {
	AllocatedCount int
}
func (s *MockCommentFixture) Construct(t *testing.T, fixtures struct {
	User MockUser `fixture:"MockUser"`
}) (MockComment, interface{}) {
	s.AllocatedCount += 1
	return MockComment{
		Creator: fixtures.User,
		Content: "Hello GTest!",
		Created: time.Now(),
	}, nil
}
func (s *MockCommentFixture) Destruct(t *testing.T, ctx interface{}) {
	s.AllocatedCount -= 1
}
type TmpDirFixture struct{}
func (s TmpDirFixture) Construct(t *testing.T, fixtures struct{}) (string, string) {
	dir, err := ioutil.TempDir("", "gtest")
	assert.NoError(t, err)
	return dir, dir
}
func (s TmpDirFixture) Destruct(t *testing.T, dir string) {
	os.RemoveAll(dir)
}
type MockApiServerFixture struct{}
type ApiServerFixtureCtx struct {
	Server   *httptest.Server
	DataFile *os.File
}
func (s MockApiServerFixture) Construct(t *testing.T, fixtures struct{}) (*httptest.Server, ApiServerFixtureCtx) {
	fp, err := ioutil.TempFile("", "gtest-api-server-healthcheck")
	assert.NoError(t, err)
	_, err = fp.Write([]byte("GTest server"))
	assert.NoError(t, err)
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		data, err := ioutil.ReadFile(fp.Name())
		assert.NoError(t, err)
		fmt.Fprintln(w, "Hello, "+string(data))
	}))
	return ts, ApiServerFixtureCtx{
		Server:   ts,
		DataFile: fp,
	}
}
func (s MockApiServerFixture) Destruct(t *testing.T, ctx ApiServerFixtureCtx) {
	ctx.Server.Close()
	os.Remove(ctx.DataFile.Name())
}
func init() {
	gtest.MustRegisterFixture("UserId", &UserIdFixture{}, gtest.ScopeCall)
	gtest.MustRegisterFixture("MockUser", &MockUserFixture{}, gtest.ScopeCall)
	gtest.MustRegisterFixture("MockComment", &MockCommentFixture{}, gtest.ScopeCall)
	gtest.MustRegisterFixture("TmpDir", &TmpDirFixture{}, gtest.ScopeSubTest)
	gtest.MustRegisterFixture("MockApiServer", &MockApiServerFixture{}, gtest.ScopeSubTest)
}
type GTestTests struct {
	Initialized bool
}
func (s *GTestTests) Setup(t *testing.T) {
	s.Initialized = true
}
func (s *GTestTests) Teardown(t *testing.T) {
	s.Initialized = false
}
func (s *GTestTests) BeforeEach(t *testing.T) {
}
func (s *GTestTests) AfterEach(t *testing.T) {
	goleak.VerifyNone(t)
}
func (GTestTests) SubTestRunTest(t *testing.T) {
	assert.Equal(t, 2, 1+1)
}
func (GTestTests) SubTestCallScopedStringFixture(t *testing.T, fixtures struct {
	UserId1 string `fixture:"UserId"`
	UserId2 string `fixture:"UserId"`
	UserId3 string `fixture:"UserId"`
}) {
	assert.True(t, strings.HasPrefix(fixtures.UserId1, "user_"))
	assert.True(t, strings.HasPrefix(fixtures.UserId2, "user_"))
	assert.True(t, strings.HasPrefix(fixtures.UserId3, "user_"))
	assert.NotEqual(t, fixtures.UserId1, fixtures.UserId2)
	assert.NotEqual(t, fixtures.UserId1, fixtures.UserId3)
	assert.NotEqual(t, fixtures.UserId2, fixtures.UserId3)
}
func (GTestTests) SubTestNestedFixture(t *testing.T, fixtures struct {
	Comment MockComment `fixture:"MockComment"`
}) {
	assert.True(t, strings.HasPrefix(fixtures.Comment.Creator.Id, "user_"))
	assert.True(t, strings.HasPrefix(fixtures.Comment.Content, "Hello GTest!"))
	assert.True(t, time.Now().Sub(fixtures.Comment.Created) < time.Second)
}