diff --git a/README.md b/README.md index d6e146e..6b355ba 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,41 @@ func main() { 2023/12/12 18:27:27 ERROR asdf a=b ``` +#### Testing + +The `slogtest` package provides utilities to make it easy to create loggers that +will use the native testing logging. + +```go +func TestFoo(t *testing.T) { + ctx := slogtest.TestContextWithLogger(t) + + for _, tc := range []string{"a", "b"} { + t.Run(tc, func(t *testing.T) { + slogctx.FromContext(ctx).Infof("hello world") + }) + } +} +``` + +```sh +$ go test -v ./examples/logger +=== RUN TestLog +=== RUN TestLog/a +=== NAME TestLog + slogtest.go:20: time=2023-12-12T18:42:53.020-05:00 level=INFO msg="hello world" + +=== RUN TestLog/b +=== NAME TestLog + slogtest.go:20: time=2023-12-12T18:42:53.020-05:00 level=INFO msg="hello world" + +--- PASS: TestLog (0.00s) + --- PASS: TestLog/a (0.00s) + --- PASS: TestLog/b (0.00s) +PASS +ok github.com/wlynch/slogctx/examples/logger +``` + ### Context Handler The context Handler can be used to insert values from the context. diff --git a/examples/logger/main_test.go b/examples/logger/main_test.go new file mode 100644 index 0000000..14049da --- /dev/null +++ b/examples/logger/main_test.go @@ -0,0 +1,18 @@ +package main + +import ( + "testing" + + "github.com/wlynch/slogctx" + "github.com/wlynch/slogctx/slogtest" +) + +func TestFoo(t *testing.T) { + ctx := slogtest.TestContextWithLogger(t) + + for _, tc := range []string{"a", "b"} { + t.Run(tc, func(t *testing.T) { + slogctx.FromContext(ctx).Infof("hello world") + }) + } +} diff --git a/slogtest/slogtest.go b/slogtest/slogtest.go new file mode 100644 index 0000000..71367ed --- /dev/null +++ b/slogtest/slogtest.go @@ -0,0 +1,37 @@ +package slogtest + +import ( + "context" + "io" + "log/slog" + + "github.com/wlynch/slogctx" +) + +var ( + _ io.Writer = &logAdapter{} +) + +type logAdapter struct { + l Logger +} + +func (l *logAdapter) Write(b []byte) (int, error) { + l.l.Log(string(b)) + return len(b), nil +} + +type Logger interface { + Log(args ...any) + Logf(format string, args ...any) +} + +// TestLogger gets a logger to use in unit and end to end tests +func TestLogger(t Logger) *slogctx.Logger { + return slogctx.New(slog.NewTextHandler(&logAdapter{l: t}, nil)) +} + +// TestContextWithLogger returns a context with a logger to be used in tests +func TestContextWithLogger(t Logger) context.Context { + return slogctx.WithLogger(context.Background(), TestLogger(t)) +}