Skip to content

testing: t.Fail should report the line on which the failure occurred #26720

@nhooyr

Description

@nhooyr

I had some code that looked like this:

package main

import (
	"testing"
	"time"
)

func TestFoo(t *testing.T) {
	t.Run("fail", func(t *testing.T) {
		go func() {
			defer func() {
				r := recover()
				if r != nil {
					t.Logf("panic: %+v", r)
				}
			}()

			time.Sleep(time.Second)

			t.Error("meow")
		}()
	})

	time.Sleep(time.Second*2)
}

I know the above code is buggy because its calling t.Error from a goroutine that lasts longer than the test goroutine and so t.Error will panic in t.Fail. However, the original test was complex and no one saw this coming.

The issue I was having is that the error call is never reported. t.Error panics and then this is recovered and logged but the individual test within which this happened is not marked as failed. Only the parent test is marked as failed. This made the test very hard to debug as there would be no line on which the failure occurred.

So if you run this code, you'll get:

$ go test
--- FAIL: TestFoo (0.00s)
FAIL
FAIL	github.com/nhooyr/scratch	1.006s

Which made me scratch my head for quite a while.

I want to repeat that I know this is a violation of the docs and so maybe shouldn't be fixed but at the same time, I think that it would be much easier to detect such failures if t.Fail reported the line number at which it was called. This would have made the above issue easy to debug and I can imagine a line number reported by t.Fail to be useful in other scenarios as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions