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

assert: introducing no field is empty assertion function #1591

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions assert/assertion_format.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions assert/assertion_forward.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions assert/assertions.go
Expand Up @@ -2107,3 +2107,38 @@ func buildErrorChainString(err error) string {
}
return chain
}

// NoFieldIsEmpty asserts that object, which must be a struct or eventually reference to one, has no empty exported fields.
func NoFieldIsEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
if reflect.TypeOf(object).Kind() == reflect.Ptr {
return NoFieldIsEmpty(t, reflect.ValueOf(object).Elem().Interface(), msgAndArgs)
}

if h, ok := t.(tHelper); ok {
h.Helper()
}

objectType := reflect.TypeOf(object)
if objectType.Kind() != reflect.Struct {
return Fail(t, "Input must be a struct or eventually reference one", msgAndArgs...)
}

var emptyFields []string
objectValue := reflect.ValueOf(object)
for i := 0; i < objectType.NumField(); i++ {
field := objectType.Field(i)
if !field.IsExported() {
continue
}

if isEmpty(objectValue.Field(i).Interface()) {
emptyFields = append(emptyFields, field.Name)
}
}

if len(emptyFields) > 0 {
return Fail(t, fmt.Sprintf("Object contained empty fields: %s", strings.Join(emptyFields, ", ")), msgAndArgs...)
}

return true
}
85 changes: 85 additions & 0 deletions assert/assertions_test.go
Expand Up @@ -3228,3 +3228,88 @@ func TestErrorAs(t *testing.T) {
})
}
}

func TestNoFieldIsEmpty(t *testing.T) {
str := "a string"
tests := []struct {
name string
input interface{}
result bool
resultErrMsg string
}{
{
name: "success",
input: struct {
Float64 float64
Func func()
Int int
Interface interface{}
Pointer *string
Slice []string
String string
Struct struct{ String string }
}{
Float64: 1.5,
Func: func() {},
Int: 1,
Interface: "interface",
Pointer: &str,
Slice: []string{"a", "b"},
String: "a string",
Struct: struct{ String string }{String: "a nested string"},
},
result: true,
},
{
name: "success_pointer",
input: &struct {
String string
}{
String: "a string",
},
result: true,
},
{
name: "success_unexported",
input: struct{ unexported string }{},
result: true,
},
{
name: "failure",
input: struct {
Float64 float64
Func func()
Int int
Interface interface{}
Pointer *string
Slice []string
String string
Struct struct{ String string }
}{},
result: false,
resultErrMsg: "Object contained empty fields: Float64, Func, Int, Interface, Pointer, Slice, String, Struct\n",
},
{
name: "failure_partial",
input: struct {
StringA string
StringB string
}{StringA: "not_empty"},
result: false,
resultErrMsg: "Object contained empty fields: StringB\n",
},
{
name: "failure_wrong_type",
input: "a string is not a struct",
result: false,
resultErrMsg: "Input must be a struct or eventually reference one\n",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockT := new(captureTestingT)
result := NoFieldIsEmpty(mockT, tt.input)
mockT.checkResultAndErrMsg(t, tt.result, result, tt.resultErrMsg)
})
}
}
22 changes: 22 additions & 0 deletions require/require.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions require/require_forward.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.