diff --git a/book.go b/book.go index c8ac22eb..50a0750a 100644 --- a/book.go +++ b/book.go @@ -45,6 +45,7 @@ type book struct { t *testing.T included bool force bool + trace bool failFast bool skipIncluded bool openApi3DocLocations []string @@ -538,6 +539,9 @@ func (bk *book) merge(loaded *book) error { if !bk.force { bk.force = loaded.force } + if !bk.trace { + bk.trace = loaded.trace + } bk.loop = loaded.loop bk.openApi3DocLocations = loaded.openApi3DocLocations bk.grpcNoTLS = loaded.grpcNoTLS diff --git a/db.go b/db.go index 5e090bcb..e396c3cd 100644 --- a/db.go +++ b/db.go @@ -109,7 +109,10 @@ func (rnr *dbRunner) run(ctx context.Context, q *dbQuery, s *step) error { return err } // Override trace - if q.trace == nil && rnr.trace != nil && *rnr.trace { + switch { + case q.trace == nil && rnr.trace == nil: + q.trace = &o.trace + case q.trace == nil && rnr.trace != nil: q.trace = rnr.trace } tc, err := q.generateTraceStmtComment(s) diff --git a/grpc.go b/grpc.go index 3abbc27b..6da7d61c 100644 --- a/grpc.go +++ b/grpc.go @@ -127,7 +127,10 @@ func (rnr *grpcRunner) run(ctx context.Context, r *grpcRequest, s *step) error { return fmt.Errorf("cannot find method: %s", key) } // Override trace - if r.trace == nil && rnr.trace != nil && *rnr.trace { + switch { + case r.trace == nil && rnr.trace == nil: + r.trace = &o.trace + case r.trace == nil && rnr.trace != nil: r.trace = rnr.trace } if err := r.setTraceHeader(s); err != nil { diff --git a/http.go b/http.go index 2e144243..f8540ec0 100644 --- a/http.go +++ b/http.go @@ -367,7 +367,10 @@ func (rnr *httpRunner) run(ctx context.Context, r *httpRequest, s *step) error { } // Override trace - if r.trace == nil && rnr.trace != nil && *rnr.trace { + switch { + case r.trace == nil && rnr.trace == nil: + r.trace = &o.trace + case r.trace == nil && rnr.trace != nil: r.trace = rnr.trace } if err := r.setTraceHeader(s); err != nil { diff --git a/include.go b/include.go index 063e32a8..ee882276 100644 --- a/include.go +++ b/include.go @@ -131,6 +131,7 @@ func (o *operator) newNestedOperator(parent *step, opts ...Option) (*operator, e popts = append(popts, Profile(o.profile)) popts = append(popts, SkipTest(o.skipTest)) popts = append(popts, Force(o.force)) + popts = append(popts, Trace(o.trace)) for k, f := range o.store.funcs { popts = append(popts, Func(k, f)) } diff --git a/operator.go b/operator.go index 24102c8a..9a553938 100644 --- a/operator.go +++ b/operator.go @@ -52,6 +52,7 @@ type operator struct { thisT *testing.T parent *step force bool + trace bool failFast bool included bool ifCond string @@ -443,6 +444,7 @@ func New(opts ...Option) (*operator, error) { t: bk.t, thisT: bk.t, force: bk.force, + trace: bk.trace, failFast: bk.failFast, included: bk.included, ifCond: bk.ifCond, diff --git a/operator_test.go b/operator_test.go index bda83592..8106f666 100644 --- a/operator_test.go +++ b/operator_test.go @@ -890,6 +890,47 @@ func TestStoreKeys(t *testing.T) { } } +func TestTrace(t *testing.T) { + tests := []struct { + book string + }{ + {"testdata/book/http.yml"}, + {"testdata/book/grpc.yml"}, + {"testdata/book/db.yml"}, + } + ctx := context.Background() + t.Setenv("DEBUG", "false") + for _, tt := range tests { + tt := tt + t.Run(tt.book, func(t *testing.T) { + buf := new(bytes.Buffer) + ts := testutil.HTTPServer(t) + t.Setenv("TEST_HTTP_END_POINT", ts.URL) + _, dsn := testutil.SQLite(t) + t.Setenv("TEST_DB_DSN", dsn) + tg := testutil.GRPCServer(t, false, false) + id := "1234567890" + opts := []Option{ + Book(tt.book), + GrpcRunner("greq", tg.Conn()), + Capture(NewDebugger(buf)), + Trace(true), + } + o, err := New(opts...) + if err != nil { + t.Fatal(err) + } + o.id = id + if err := o.Run(ctx); err != nil { + t.Error(err) + } + if !strings.Contains(buf.String(), id) { + t.Error("no trace") + } + }) + } +} + func TestLoop(t *testing.T) { tests := []struct { book string diff --git a/option.go b/option.go index 9414a096..b0ac7335 100644 --- a/option.go +++ b/option.go @@ -655,6 +655,16 @@ func Force(enable bool) Option { } } +// Trace - Trace all steps by default. +func Trace(enable bool) Option { + return func(bk *book) error { + if !bk.trace { + bk.trace = enable + } + return nil + } +} + // HTTPOpenApi3 - Set the path of OpenAPI Document for HTTP runners. // Deprecated: Use HTTPOpenApi3s instead. func HTTPOpenApi3(l string) Option { diff --git a/runbook.go b/runbook.go index c94076ee..b4500a86 100644 --- a/runbook.go +++ b/runbook.go @@ -49,6 +49,7 @@ type runbook struct { Loop any `yaml:"loop,omitempty"` Concurrency string `yaml:"concurrency,omitempty"` Force bool `yaml:"force,omitempty"` + Trace bool `yaml:"trace,omitempty"` useMap bool stepKeys []string @@ -66,6 +67,7 @@ type runbookMapped struct { Loop any `yaml:"loop,omitempty"` Concurrency string `yaml:"concurrency,omitempty"` Force bool `yaml:"force,omitempty"` + Trace bool `yaml:"trace,omitempty"` } func NewRunbook(desc string) *runbook { @@ -122,6 +124,7 @@ func parseRunbookMapped(b []byte, rb *runbook) error { rb.If = m.If rb.SkipTest = m.SkipTest rb.Force = m.Force + rb.Trace = m.Trace keys := map[string]struct{}{} for _, s := range m.Steps { @@ -183,6 +186,7 @@ func (rb *runbook) MarshalYAML() (any, error) { m.If = rb.If m.SkipTest = rb.SkipTest m.Force = rb.Force + m.Trace = rb.Trace ms := yaml.MapSlice{} for i, k := range rb.stepKeys { ms = append(ms, yaml.MapItem{ @@ -371,6 +375,7 @@ func (rb *runbook) toBook() (*book, error) { bk.ifCond = rb.If bk.skipTest = rb.SkipTest bk.force = rb.Force + bk.trace = rb.Trace if rb.Loop != nil { bk.loop, err = newLoop(rb.Loop) if err != nil { diff --git a/runner_option_test.go b/runner_option_test.go index 5ba2a793..d7a8d28e 100644 --- a/runner_option_test.go +++ b/runner_option_test.go @@ -91,7 +91,7 @@ func TestUseCookie(t *testing.T) { } } -func TestTrace(t *testing.T) { +func TestHTTPTrace(t *testing.T) { c := &httpRunnerConfig{} want := true opt := HTTPTrace(want)