Skip to content

Commit c519b79

Browse files
committed
assert.Empty: comprehensive doc of "Empty"-ness rules
Document the assert.Empty rules more comprehensively. This exposes our quirks to the user to avoid wrong expectations. Add many many many more test cases that document edges cases and will allow to catch breaking changes and avoid regressions.
1 parent 5d95b18 commit c519b79

File tree

6 files changed

+192
-33
lines changed

6 files changed

+192
-33
lines changed

assert/assertion_format.go

Lines changed: 12 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assert/assertion_forward.go

Lines changed: 24 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assert/assertions.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,10 +773,19 @@ func isEmpty(object interface{}) bool {
773773
}
774774
}
775775

776-
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
777-
// a slice or a channel with len == 0.
776+
// Empty asserts that the given value is "empty".
777+
//
778+
// [Zero values] are "empty".
779+
//
780+
// Arrays are "empty" if every element is the zero value of the type (stricter than "empty").
781+
//
782+
// Slices, maps and channels with zero length are "empty".
783+
//
784+
// Pointer values are "empty" if the pointer is nil or if the pointed value is "empty".
778785
//
779786
// assert.Empty(t, obj)
787+
//
788+
// [Zero values]: https://go.dev/ref/spec#The_zero_value
780789
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
781790
pass := isEmpty(object)
782791
if !pass {
@@ -789,8 +798,7 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
789798
return pass
790799
}
791800

792-
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
793-
// a slice or a channel with len == 0.
801+
// NotEmpty asserts that the specified object is NOT [Empty].
794802
//
795803
// if assert.NotEmpty(t, obj) {
796804
// assert.Equal(t, "two", obj[1])

assert/assertions_test.go

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1728,24 +1728,119 @@ func Test_isEmpty(t *testing.T) {
17281728

17291729
True(t, isEmpty(""))
17301730
True(t, isEmpty(nil))
1731+
True(t, isEmpty(error(nil)))
1732+
True(t, isEmpty((*int)(nil)))
1733+
True(t, isEmpty((*string)(nil)))
1734+
True(t, isEmpty(new(string)))
17311735
True(t, isEmpty([]string{}))
1736+
True(t, isEmpty([]string(nil)))
1737+
True(t, isEmpty([]byte(nil)))
1738+
True(t, isEmpty([]byte{}))
1739+
True(t, isEmpty([]byte("")))
1740+
True(t, isEmpty([]bool(nil)))
1741+
True(t, isEmpty([]bool{}))
1742+
True(t, isEmpty([]interface{}(nil)))
1743+
True(t, isEmpty([]interface{}{}))
1744+
True(t, isEmpty(struct{}{}))
1745+
True(t, isEmpty(&struct{}{}))
1746+
True(t, isEmpty(struct{ A int }{A: 0}))
1747+
True(t, isEmpty(struct{ a int }{a: 0}))
1748+
True(t, isEmpty(struct {
1749+
a int
1750+
B int
1751+
}{a: 0, B: 0}))
17321752
True(t, isEmpty(0))
1753+
True(t, isEmpty(int(0)))
1754+
True(t, isEmpty(int8(0)))
1755+
True(t, isEmpty(int16(0)))
1756+
True(t, isEmpty(uint16(0)))
17331757
True(t, isEmpty(int32(0)))
1758+
True(t, isEmpty(uint32(0)))
17341759
True(t, isEmpty(int64(0)))
1760+
True(t, isEmpty(uint64(0)))
1761+
True(t, isEmpty('\u0000')) // rune => int32
1762+
True(t, isEmpty(float32(0)))
1763+
True(t, isEmpty(float64(0)))
1764+
True(t, isEmpty(0i)) // complex
1765+
True(t, isEmpty(0.0i)) // complex
17351766
True(t, isEmpty(false))
1767+
True(t, isEmpty(new(bool)))
17361768
True(t, isEmpty(map[string]string{}))
1769+
True(t, isEmpty(map[string]string(nil)))
17371770
True(t, isEmpty(new(time.Time)))
17381771
True(t, isEmpty(time.Time{}))
17391772
True(t, isEmpty(make(chan struct{})))
1740-
True(t, isEmpty([1]int{}))
1773+
True(t, isEmpty(chan struct{}(nil)))
1774+
True(t, isEmpty(chan<- struct{}(nil)))
1775+
True(t, isEmpty(make(chan struct{})))
1776+
True(t, isEmpty(make(chan<- struct{})))
1777+
True(t, isEmpty(make(chan struct{}, 1)))
1778+
True(t, isEmpty(make(chan<- struct{}, 1)))
1779+
True(t, isEmpty([1]int{0}))
1780+
True(t, isEmpty([2]int{0, 0}))
1781+
True(t, isEmpty([8]int{}))
1782+
True(t, isEmpty([...]int{7: 0}))
1783+
True(t, isEmpty([...]bool{false, false}))
1784+
True(t, isEmpty(errors.New(""))) // BEWARE
1785+
True(t, isEmpty([]error{}))
1786+
True(t, isEmpty([]error(nil)))
1787+
True(t, isEmpty(&[1]int{0}))
1788+
True(t, isEmpty(&[2]int{0, 0}))
17411789
False(t, isEmpty("something"))
17421790
False(t, isEmpty(errors.New("something")))
17431791
False(t, isEmpty([]string{"something"}))
17441792
False(t, isEmpty(1))
1793+
False(t, isEmpty(int(1)))
1794+
False(t, isEmpty(uint(1)))
1795+
False(t, isEmpty(byte(1)))
1796+
False(t, isEmpty(int8(1)))
1797+
False(t, isEmpty(uint8(1)))
1798+
False(t, isEmpty(int16(1)))
1799+
False(t, isEmpty(uint16(1)))
1800+
False(t, isEmpty(int32(1)))
1801+
False(t, isEmpty(uint32(1)))
1802+
False(t, isEmpty(int64(1)))
1803+
False(t, isEmpty(uint64(1)))
1804+
False(t, isEmpty('A')) // rune => int32
17451805
False(t, isEmpty(true))
1806+
False(t, isEmpty(1.0))
1807+
False(t, isEmpty(1i)) // complex
1808+
False(t, isEmpty([]byte{0})) // elements values are ignored for slices
1809+
False(t, isEmpty([]byte{0, 0})) // elements values are ignored for slices
1810+
False(t, isEmpty([]string{""})) // elements values are ignored for slices
1811+
False(t, isEmpty([]string{"a"})) // elements values are ignored for slices
1812+
False(t, isEmpty([]bool{false})) // elements values are ignored for slices
1813+
False(t, isEmpty([]bool{true})) // elements values are ignored for slices
1814+
False(t, isEmpty([]error{errors.New("xxx")}))
1815+
False(t, isEmpty([]error{nil})) // BEWARE
1816+
False(t, isEmpty([]error{errors.New("")})) // BEWARE
17461817
False(t, isEmpty(map[string]string{"Hello": "World"}))
1818+
False(t, isEmpty(map[string]string{"": ""}))
1819+
False(t, isEmpty(map[string]string{"foo": ""}))
1820+
False(t, isEmpty(map[string]string{"": "foo"}))
17471821
False(t, isEmpty(chWithValue))
1822+
False(t, isEmpty([1]bool{true}))
1823+
False(t, isEmpty([2]bool{false, true}))
1824+
False(t, isEmpty([...]bool{10: true}))
1825+
False(t, isEmpty([]int{0}))
1826+
False(t, isEmpty([]int{42}))
17481827
False(t, isEmpty([1]int{42}))
1828+
False(t, isEmpty([2]int{0, 42}))
1829+
False(t, isEmpty(&[1]int{42}))
1830+
False(t, isEmpty(&[2]int{0, 42}))
1831+
False(t, isEmpty([1]*int{new(int)})) // array elements must be the zero value, not any Empty value
1832+
False(t, isEmpty(struct{ A int }{A: 42}))
1833+
False(t, isEmpty(struct{ a int }{a: 42}))
1834+
False(t, isEmpty(struct{ a *int }{a: new(int)})) // fields must be the zero value, not any Empty value
1835+
False(t, isEmpty(struct{ a []int }{a: []int{}})) // fields must be the zero value, not any Empty value
1836+
False(t, isEmpty(struct {
1837+
a int
1838+
B int
1839+
}{a: 0, B: 42}))
1840+
False(t, isEmpty(struct {
1841+
a int
1842+
B int
1843+
}{a: 42, B: 0}))
17491844
}
17501845

17511846
func TestEmpty(t *testing.T) {

require/require.go

Lines changed: 24 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

require/require_forward.go

Lines changed: 24 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)