testify
testify copied to clipboard
Suite: Subtests should also trigger `SetupTest` and `TearDownTest`
I know this is probably a breaking change but I have some tests written using table driven design. I'd like for the tests ran with suite.Run(name string, func(){})
to also trigger SetupTest
and TearDownTest
for every instance of the subtest.
Is this currently possible?
If not then we can add a new func SetupSubtest
and TearDownSubtest
and run those for every subtest.
I'm not sure that makes sense. Probably you have a specific case and think you need a common solution. Probably you need to implement your sub-tests as separate tests. Or need a helper method in your suite to call it to setup subtests (if you use a table-driven test it will be clear and simple). If you can provide more details (or peace of code) I can suggest to you more detailed.
I recommend investigating the flow of test execution. Look at this example — https://play.golang.org/p/ePSLrrfuV5m. SetupTest already executed before sub-test with other parent test code. So, proposed changes are the way to a sequence of SetupTest execution. I think you want to execute it once for every sub-test.
SetupSubtest sounds better, but it is not clear what to do with a sub-sub-test.
I would also find SetupSubtest
and TearDownSubTest
very useful 😄 . I agree that is not clear what to do with a sub-sub-test though, don't know if there would be a way of limiting it to one level of depth only 🤔 I don't see why a deeper sub-test nesting would be useful anyway.
Honestly I'm just shocked this still isn't a feature. It's pretty basic functionality considering they're clearly trying to imitate some of the concepts other test frameworks use (having hooks for pre- and post-tests)
I needed a feature like BeforeSubtest
to initialize the data in the database test.
It's possible to split the test, but I wanted to use a subtest as the context.
func TestUserRepositoryTestSuite(t *testing.T) {
suite.Run(t, new(UserRepositoryTestSuite))
}
func (s TestUserRepositoryTestSuite) BeforeTest(_ string, _ string) {
testing_helper.CleanUpDB()
}
func NewUserRepositoryTestingContainer() *testing_helper.Container { # github.com/uber-go/dig.Container
c := testing_helper.NewDatabaseTestingContainer()
c.Provide(NewUserRepository)
return c
}
func (s *UserRepositoryTestSuite) TestUserRepository_FindById() {
id := 1
c := NewUserRepositoryTestingContainer()
c.RequireInvoke(func(repository repository.UserRepository) {
s.Run("When user data exists", func() {
testing_helper.CleanUpDB() # I want to call before each subtests.
testing_helper.DB.Create(&model.User{
ID: id,
})
user, err := repository.FindById(id)
s.NoError(err)
s.Equal(user.ID, id)
})
s.Run("When user data not exists", func() {
testing_helper.CleanUpDB()
_, err := repository.FindById(id)
s.ErrorIs(err, gorm.ErrRecordNotFound)
})
})
}
RSpec can be written as follows.
describe UserRepository do
describe '#find_by_id' do
before { DatabaseCleaner.clean } # Call before each it blocks.
subject { UserRepository.find_by_id(id) }
let(:id) { 1 }
context 'When user data exists' do
before { create(:user, id: id) }
it { is_expected.not_to raise_error(ActiveRecord::RecordNotFound) }
it { is_expected.to have_attriutes({id: id}) }
end
context 'When user data not exists' do
it { is_expected.to raise_error(ActiveRecord::RecordNotFound) }
end
end
end
I haven't tried this, but can't you just call suite.SetupTest()
and suite.TearDownTest()
yourself? Like so:
func (suite *MyTestSuite) TestSomeStuff() {
...
for _, testCase := range testCases {
suite.Run(testCase.name, func() {
suite.SetupTest()
...
suite.TearDownTest()
})
}
...
}