8

I'd like to wrap standard golang test functions, such as t.Errorf from the testing package.

I tried this:

// AssertEqual tests that the expected and actual values match
func AssertEqual(t *testing.T, expected interface{}, actual interface{}) {
    switch expected.(type) {
    case string:
        if expected != actual {
            t.Errorf("Error:\nexpected: %s\nactual: %s", expected, actual)
        }
    default:
        t.Errorf("Unsupported type")
    }
}

However, when a test fails, I get the function and line number of my helper function:

test_asserts.go:12: Error:
    expected: 
    actual: TestValue

Is there a way to error at the line number of the caller?

1
  • One year later, with Go 1.9, adding t.Helper() will make the line number to be the correct one. See my answer below Commented Aug 26, 2017 at 16:40

3 Answers 3

17

With the recent Go 1.9 (August 2017), all you need to do is adding one line to your function:

t.Helper()

That will silence this function in error report, and your actual error line will be the one you expect (ie the one calling this function)

See pkg/testing/#T.Helper (also available for Benchmark test, but... not for the TB interface, where it was forgotten! Feb. 2021: this is available, see below)

// AssertEqual tests that the expected and actual values match
func AssertEqual(t *testing.T, expected interface{}, actual interface{}) {
    t.Helper()
    switch expected.(type) {
    case string:
        if expected != actual {
            t.Errorf("Error:\nexpected: %s\nactual: %s", expected, actual)
        }
    default:
        t.Errorf("Unsupported type")
    }
}

xuiqzy mentions in the comments in Feb. 2021 the interface testing.TB which now has Helper().
See commit bc29313, Apr. 2017, go1.9beta1, CL 38796 for implementing proposal 4899.

We propose to add a new testing.TB method, Helper, which marks the calling function as a test helper.

When logging test messages, package testing ignores frames that are inside marked helper functions.
It prints the first stack position inside a non-helper function.

Sign up to request clarification or add additional context in comments.

2 Comments

Now also available in TB interface: golang.org/pkg/testing/#TB
@xuiqzy Thank you. I have included your comment in the answer for more visibility.
2

This is how the testing library does it: https://golang.org/src/testing/testing.go?h=Errorf#L285

By using runtime.Caller.

You can borrow this code for your own error function that would look one deeper into the stack. You can replace the entirety of Errorf (which is log + fail) or a bit less pretty but less code would be to just print the entire stack using something like debug.PrintStack() before calling Errorf.

Comments

0

You can see Fail function in assert package: https://github.com/stretchr/testify/blob/master/assert/assertions.go#L207

Example:

package main_test

import (
        "fmt"
        "github.com/stretchr/testify/assert"
        "strings"
        "testing"
)

// AssertEqual tests that the expected and actual values match
func AssertEqual(t *testing.T, expected interface{}, actual interface{}) {
        switch expected.(type) {
        case string:
                if expected != actual {
                        callInfo := assert.CallerInfo()
                        errorTrace := strings.Join(callInfo, "\n\r\t\t\t")
                        t.Errorf("\r%s\r\tError Trace:\t%s\n"+
                                "\r\tError:%s\n\r",
                                "",
                                errorTrace,
                                fmt.Sprintf("Error:\nexpected: %s\nactual: %s", expected, actual),
                        )
                }
        default:
                t.Errorf("Unsupported type")
        }
}                                                                                                                                                                                            

func TestFoo(t *testing.T) {                                                                                                                                                                 
        AssertEqual(t, "hello", 21)                                                                                                                                                          
}

Result:

$ go test main_test.go 
--- FAIL: TestFoo (0.00s)
        Error Trace::22:main_test.go:15
                        main_test.go:30
        Error:Error:
                expected: hello
                actual: %!s(int=21)

FAIL
FAIL    command-line-arguments  0.002s

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.