Skip to content

Commit

Permalink
Add GinkgoLogr (#1067)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuckal777 authored Oct 23, 2022
1 parent 8a2f483 commit bf78c28
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 6 deletions.
17 changes: 12 additions & 5 deletions core_dsl.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"strings"
"time"

"github.com/go-logr/logr"
"github.com/onsi/ginkgo/v2/formatter"
"github.com/onsi/ginkgo/v2/internal"
"github.com/onsi/ginkgo/v2/internal/global"
Expand All @@ -46,7 +47,9 @@ func init() {
var err error
flagSet, err = types.BuildTestSuiteFlagSet(&suiteConfig, &reporterConfig)
exitIfErr(err)
GinkgoWriter = internal.NewWriter(os.Stdout)
writer := internal.NewWriter(os.Stdout)
GinkgoWriter = writer
GinkgoLogr = internal.GinkgoLogrFunc(writer)
}

func exitIfErr(err error) {
Expand Down Expand Up @@ -90,11 +93,11 @@ type GinkgoWriterInterface interface {
}

/*
SpecContext is the context object passed into nodes that are subject to a timeout or need to be notified of an interrupt. It implements the standard context.Context interface but also contains additional helpers to provide an extensibility point for Ginkgo. (As an example, Gomega's Eventually can use the methods defined on SpecContext to provide deeper integratoin with Ginkgo).
SpecContext is the context object passed into nodes that are subject to a timeout or need to be notified of an interrupt. It implements the standard context.Context interface but also contains additional helpers to provide an extensibility point for Ginkgo. (As an example, Gomega's Eventually can use the methods defined on SpecContext to provide deeper integratoin with Ginkgo).
You can do anything with SpecContext that you do with a typical context.Context including wrapping it with any of the context.With* methods.
You can do anything with SpecContext that you do with a typical context.Context including wrapping it with any of the context.With* methods.
Ginkgo will cancel the SpecContext when a node is interrupted (e.g. by the user sending an interupt signal) or when a node has exceeded it's allowed run-time. Note, however, that even in cases where a node has a deadline, SpecContext will not return a deadline via .Deadline(). This is because Ginkgo does not use a WithDeadline() context to model node deadlines as Ginkgo needs control over the precise timing of the context cancellation to ensure it can provide an accurate progress report at the moment of cancellation.
Ginkgo will cancel the SpecContext when a node is interrupted (e.g. by the user sending an interupt signal) or when a node has exceeded it's allowed run-time. Note, however, that even in cases where a node has a deadline, SpecContext will not return a deadline via .Deadline(). This is because Ginkgo does not use a WithDeadline() context to model node deadlines as Ginkgo needs control over the precise timing of the context cancellation to ensure it can provide an accurate progress report at the moment of cancellation.
*/
type SpecContext = internal.SpecContext

Expand All @@ -112,6 +115,11 @@ You can learn more at https://onsi.github.io/ginkgo/#logging-output
*/
var GinkgoWriter GinkgoWriterInterface

/*
GinkgoLogr is a logr.Logger that writes to GinkgoWriter
*/
var GinkgoLogr logr.Logger

// The interface by which Ginkgo receives *testing.T
type GinkgoTestingT interface {
Fail()
Expand Down Expand Up @@ -686,7 +694,6 @@ Multiple BeforeAll nodes can be defined in a given Ordered container however the
BeforeAll can take a func() body, or an interruptible func(SpecContext)/func(context.Context) body.
You cannot nest any other Ginkgo nodes within a BeforeAll node's closure.
You can learn more about Ordered Containers at: https://onsi.github.io/ginkgo/#ordered-containers
And you can learn more about BeforeAll at: https://onsi.github.io/ginkgo/#setup-in-ordered-containers-beforeall-and-afterall
Expand Down
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,8 @@ You can also attach additional `io.Writer`s for `GinkgoWriter` to tee to via `Gi

Finally - when running in verbose mode via `ginkgo -v` anything written to `GinkgoWriter` will be immediately streamed to stdout. This can help shorten the feedback loop when debugging a complex spec.

If [logr](https://github.com/go-logr/logr) is used for logging in a project the globally available `GinkgoLogr` provides a logger implementation. Any logging on `GinkgoLogr` is forwarded to `GinkgoWriter`.

### Documenting Complex Specs: By
As a rule, you should try to keep your subject and setup closures short and to the point. Sometimes this is not possible, particularly when testing complex workflows in integration-style tests. In these cases your test blocks begin to hide a narrative that is hard to glean by looking at code alone. Ginkgo provides `By` to help in these situations. Here's an example:

Expand Down
3 changes: 2 additions & 1 deletion dsl/core/core_dsl.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
Ginkgo is usually dot-imported via:
import . "github.com/onsi/ginkgo/v2"
import . "github.com/onsi/ginkgo/v2"
however some parts of the DSL may conflict with existing symbols in the user's code.
Expand All @@ -24,6 +24,7 @@ type GinkgoTInterface = ginkgo.GinkgoTInterface
type SpecContext = ginkgo.SpecContext

var GinkgoWriter = ginkgo.GinkgoWriter
var GinkgoLogr = ginkgo.GinkgoLogr
var GinkgoConfiguration = ginkgo.GinkgoConfiguration
var GinkgoRandomSeed = ginkgo.GinkgoRandomSeed
var GinkgoParallelProcess = ginkgo.GinkgoParallelProcess
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/onsi/ginkgo/v2
go 1.18

require (
github.com/go-logr/logr v1.2.3
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38
github.com/onsi/gomega v1.22.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
Expand Down
9 changes: 9 additions & 0 deletions internal/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"fmt"
"io"
"sync"

"github.com/go-logr/logr"
"github.com/go-logr/logr/funcr"
)

type WriterMode uint
Expand Down Expand Up @@ -101,3 +104,9 @@ func (w *Writer) Printf(format string, a ...interface{}) {
func (w *Writer) Println(a ...interface{}) {
fmt.Fprintln(w, a...)
}

func GinkgoLogrFunc(writer *Writer) logr.Logger {
return funcr.New(func(prefix, args string) {
writer.Printf("%s", args)
}, funcr.Options{})
}
16 changes: 16 additions & 0 deletions internal/writer_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package internal_test

import (
"errors"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

Expand Down Expand Up @@ -108,4 +110,18 @@ var _ = Describe("Writer", func() {
Ω(string(out.Contents())).Should(Equal("foo17 - bar\n"))
})
})

When("wrapped by logr", func() {
It("can print Info logs", func() {
log := internal.GinkgoLogrFunc(writer)
log.Info("message", "key", 5)
Ω(string(out.Contents())).Should(Equal("\"level\"=0 \"msg\"=\"message\" \"key\"=5"))
})

It("can print Error logs", func() {
log := internal.GinkgoLogrFunc(writer)
log.Error(errors.New("cake"), "planned failure", "key", "banana")
Ω(string(out.Contents())).Should(Equal("\"msg\"=\"planned failure\" \"error\"=\"cake\" \"key\"=\"banana\""))
})
})
})

0 comments on commit bf78c28

Please sign in to comment.