Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suite: Subtests should also trigger SetupTest and TearDownTest #1031

Closed
odannyc opened this issue Dec 14, 2020 · 5 comments · Fixed by #1246
Closed

Suite: Subtests should also trigger SetupTest and TearDownTest #1031

odannyc opened this issue Dec 14, 2020 · 5 comments · Fixed by #1246

Comments

@odannyc
Copy link

odannyc commented Dec 14, 2020

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.

@kulti
Copy link

kulti commented Dec 18, 2020

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.

unknowntpo added a commit to unknowntpo/todos that referenced this issue Sep 29, 2021
Because subtests in suite.Run() doesn't trigger SetupTest() and TearDownTest(),
so we have to use a new user instead.
Or we will get 'duplicate email' error.
See this issue for more information:

stretchr/testify#1031
@ghost
Copy link

ghost commented Oct 12, 2021

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.

@azuk-bread
Copy link

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)

@masato-hi
Copy link

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

@oscarjd74
Copy link

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()
        })
    }
    ...
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants