From 3203ea033d5d43c271786451a89610fac2572aa0 Mon Sep 17 00:00:00 2001 From: Timofey Koolin Date: Wed, 1 Mar 2023 15:08:00 +0300 Subject: [PATCH] Print name and position of failed fixture. --- env.go | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/env.go b/env.go index e8944fd..22bd6f0 100644 --- a/env.go +++ b/env.go @@ -58,8 +58,10 @@ func (e *EnvT) T() T { // Cache must be called direct from fixture - it use runtime stacktrace for // detect called method - it is part of cache key. // params - part of cache key. Usually - parameters, passed to fixture. -// it allow use parametrized fixtures with different results. -// params must be json serializable. +// +// it allow use parametrized fixtures with different results. +// params must be json serializable. +// // opt - fixture options, nil for default options. // f - callback - fixture body. // Cache guarantee for call f exactly once for same Cache called and params combination. @@ -71,8 +73,10 @@ func (e *EnvT) Cache(params interface{}, opt *FixtureOptions, f FixtureCallbackF // CacheWithCleanup must be called direct from fixture - it use runtime stacktrace for // detect called method - it is part of cache key. // params - part of cache key. Usually - parameters, passed to fixture. -// it allow use parametrized fixtures with different results. -// params must be json serializable. +// +// it allow use parametrized fixtures with different results. +// params must be json serializable. +// // opt - fixture options, nil for default options. // f - callback - fixture body. // cleanup, returned from f called while fixture cleanup @@ -107,13 +111,32 @@ func (e *EnvT) cache(params interface{}, opt *FixtureOptions, f FixtureCallbackF // return not reacheble after Fatalf return nil } + wrappedF := e.fixtureCallWrapper(key, f, opt) res, err := e.c.GetOrSet(key, wrappedF) if err != nil { if errors.Is(err, ErrSkipTest) { e.T().SkipNow() } else { - e.t.Fatalf("failed to call fixture func: %v", err) + // Get fixture name + externalCallerLevel := 4 + var pc = make([]uintptr, externalCallerLevel) + var extCallerFrame runtime.Frame + if externalCallerLevel == runtime.Callers(opt.additionlSkipExternalCalls, pc) { + frames := runtime.CallersFrames(pc) + frames.Next() // callers + frames.Next() // the function + frames.Next() // caller of the function (env private function) + extCallerFrame, _ = frames.Next() // external caller + } + + fixtureDesctiption := fmt.Sprintf( + "%v (%v:%v)", + extCallerFrame.Function, + extCallerFrame.File, + extCallerFrame.Line, + ) + e.t.Fatalf("failed to call fixture func \"%v\": %v", fixtureDesctiption, err) } // panic must be not reachable after SkipNow or Fatalf