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

add constructor to assertions object to smooth out subtests #603

Closed
wants to merge 1 commit into from

Conversation

ichiban
Copy link

@ichiban ichiban commented May 14, 2018

Currently, you can't redeclare assert := assert.New(t) in subtests.

This PR enables it by defining constructor method.

package main

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestAssertions_New(t *testing.T) {
	assert := assert.New(t)
	assert.True(true)
	t.Run("subtest", func(t *testing.T) {
		assert := assert.New(t) // this doesn't compile without `func (a *Assertions) New(t TestingT) *Assertions`
		assert.True(true)
	})
}

@devdinu
Copy link
Contributor

devdinu commented May 14, 2018

@ichiban The problem is you've overridden the assert package with variable assert := assert.New(t) hence, the New isn't available, as it's on *Assertions. Rename the variable and it should work fine.

@ichiban
Copy link
Author

ichiban commented May 15, 2018

Thank you for your reply, @devdinu!

I know that assert := assert.New(t) is an idiom that shadows the package name with the variable name. Though, I didn't want to rename the variable to other than assert because it required more changes than it should.

My original problem was applying t.Run() to tests predating subtests (Test_original). To do so, there're 2 options: rename the outer assert so that it doesn't shadow package (Test_rename), or don't declare the outer assert (Test_package). Both require changes to // lots of assertions and it would be great if I had another solution without breaking them. Adding a constructor method can keep lots of assertions intact (Test_new).

package main

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func Test_original(t *testing.T) {
	assert := assert.New(t)

	// lots of assertions
	assert.True(true)
	assert.True(true)
	assert.True(true)

	{ // subtest A
		assert.True(true)
	}

	{ // subtest B
		assert.True(true)
	}
}

func Test_rename(t *testing.T) {
	asser := assert.New(t)

	// lots of assertions
	asser.True(true)
	asser.True(true)
	asser.True(true)

	t.Run("subtest A", func(t *testing.T) {
		assert := assert.New(t)
		assert.True(true)
	})

	t.Run("subtest B", func(t *testing.T) {
		assert := assert.New(t)
		assert.True(true)
	})
}

func Test_package(t *testing.T) {
	// lots of assertions
	assert.True(t, true)
	assert.True(t, true)
	assert.True(t, true)

	t.Run("subtest A", func(t *testing.T) {
		assert := assert.New(t)
		assert.True(true)
	})

	t.Run("subtest B", func(t *testing.T) {
		assert := assert.New(t)
		assert.True(true)
	})
}

func Test_new(t *testing.T) {
	assert := assert.New(t)

	// lots of assertions
	assert.True(true)
	assert.True(true)
	assert.True(true)

	t.Run("subtest A", func(t *testing.T) {
		assert := assert.New(t)
		assert.True(true)
	})

	t.Run("subtest B", func(t *testing.T) {
		assert := assert.New(t)
		assert.True(true)
	})
}

@devdinu
Copy link
Contributor

devdinu commented May 15, 2018

I'm curious why do you need to do assert.New instead of using those method on packages directly.

@ichiban
Copy link
Author

ichiban commented May 15, 2018

@devdinu Good point! I'd do so if I wrote tests from scratch but I have existing assertions in the form of assert.True(true) to be wrapped in subtests. I need it to wrap them in subtests without changing the outer assertions and also the assertions in subtests. I don't want to waste others' time reviewing those nonessential changes.

@@ -13,4 +13,9 @@ func New(t TestingT) *Assertions {
}
}

// New makes a new Assertions object for the subtest TestingT.
func (a *Assertions) New(t TestingT) *Assertions {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems confusing to me.

how about:

func (a *Assertions) Run(name string, fn func(*Assertions)) {
 	a.t.Run(name, func(t *testing.T) {
 	 	a := New(t)
 	 	fn(a)
 	})
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ernesto-jimenez, thank you for the great idea! It looks compelling and I can easily imagine myself writing like:

func Test_run(t *testing.T) {
	assert := assert.New(t)

	assert.Run("subtest", func(assert *assert.Assertions) { // Wait, package `assert` is shadowed
		assert.True(true)
	})
}

Oh wait, *assert.Assertions will be shadowed if I keep declaring assert := assert.New(t). Also, a.t is a TestingT instead of *testing.T which doesn't have Run() method.

@dolmen
Copy link
Collaborator

dolmen commented Jul 31, 2023

👍 for func (a *Assertions) Run(name string, fn func(*Assertions)) as suggested by @ernesto-jimenez .

I'm closing this PR and I have opened #1446.

@dolmen dolmen closed this Jul 31, 2023
@dolmen dolmen added pkg-assert Change related to package testify/assert enhancement testing.T.Run About subtests and testing.T.Run. labels Jul 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement pkg-assert Change related to package testify/assert testing.T.Run About subtests and testing.T.Run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants