Package for comparing Go values in tests

Overview

Package for equality of Go values

GoDev Build Status

This package is intended to be a more powerful and safer alternative to reflect.DeepEqual for comparing whether two values are semantically equal.

The primary features of cmp are:

  • When the default behavior of equality does not suit the needs of the test, custom equality functions can override the equality operation. For example, an equality function may report floats as equal so long as they are within some tolerance of each other.

  • Types that have an Equal method may use that method to determine equality. This allows package authors to determine the equality operation for the types that they define.

  • If no custom equality functions are used and no Equal method is defined, equality is determined by recursively comparing the primitive kinds on both values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported fields are not compared by default; they result in panics unless suppressed by using an Ignore option (see cmpopts.IgnoreUnexported) or explicitly compared using the AllowUnexported option.

See the documentation for more information.

This is not an official Google product.

Install

go get -u github.com/google/go-cmp/cmp

License

BSD - See LICENSE file

Issues
  • Implement an AllowAllUnexported Option

    Implement an AllowAllUnexported Option

    Hi, I was wondering if you would consider adding a new option which would apply the AllowUnexported Option to all types and would not require a slice of input like the current AllowUnexported function does?

    My use case is that I have a lot of tests which use the github.com/stretchr/testify package, which ultimately uses reflect.DeepEqual for comparing two objects, that break in Go 1.9 because they try to compare structs which contain time.Time fields. Admittedly, I could define an Equal method for all such structs but that doesn't seem to address the root of the problem to me, which is that I would like reflect.DeepEqual functionality (which compares all fields, both private and public) with the caveat that I would like to check if the types being compared have an Equal method for testing equality. Furthermore, while for structs I could pass the structs being compared to AllowUnexported, I would like the same behavior for composite types as well (e.g. maps and slices) which is not supported by AllowUnexported currently since it specifically checks that the types of the objects passed to it are structs.

    I would be more than happy to put up a PR for such an Option, a first look at the code leads me to believe that we could define an additional field on state indicating that we want to always check private fields. Then, when set to true, we would always extract a struct's fields in tryExporting. With that being said, I got the impression that you might be opposed to such an Option given the warnings for AllowUnexported already and so I thought it better to open an issue first where we could discuss.

    Thanks!

    enhancement 
    opened by jeromefroe 30
  • comparer not called with different concrete types of interface

    comparer not called with different concrete types of interface

    https://godoc.org/github.com/google/go-cmp/cmp#Comparer states "If T is an interface, it is possible that f is called with two values of different concrete types that both implement T."

    I'm trying to compare different concrete types of an interface, but my Comparer is never called.

    Running:

    package main
    
    import (
    	"github.com/google/go-cmp/cmp"
    )
    
    func main() {
    	var i1 I
    	var i2 I
    	
    	i1 = &A{}
    	i2 = &B{}
    	
    	cmp.Equal(i1, i2, cmp.Comparer(ic))
    	
    	panic("not compared")
    }
    
    type I interface {
      Foo()
    }
    
    type A struct {}
    func(a *A) Foo() {}
    
    type B struct {}
    func(b *B) Foo() {}
    
    func ic(i1 I, i2 I) bool {
            panic("compared")
    }
    

    Results in:

    panic: not compared
    
    goroutine 1 [running]:
    main.main()
            /tmp/main.go:16 +0x111
    exit status 2
    
    $ go version
    go version go1.13 linux/amd64
    $ go env
    GO111MODULE=""
    GOARCH="amd64"
    GOBIN=""
    GOCACHE="/home/cjnosal/.cache/go-build"
    GOENV="/home/cjnosal/.config/go/env"
    GOEXE=""
    GOFLAGS=""
    GOHOSTARCH="amd64"
    GOHOSTOS="linux"
    GONOPROXY=""
    GONOSUMDB=""
    GOOS="linux"
    GOPATH="/mnt/d/workspace/go"
    GOPRIVATE=""
    GOPROXY="https://proxy.golang.org,direct"
    GOROOT="/usr/lib/go"
    GOSUMDB="sum.golang.org"
    GOTMPDIR=""
    GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
    GCCGO="gccgo"
    AR="ar"
    CC="gcc"
    CXX="g++"
    CGO_ENABLED="1"
    GOMOD=""
    CGO_CFLAGS="-g -O2"
    CGO_CPPFLAGS=""
    CGO_CXXFLAGS="-g -O2"
    CGO_FFLAGS="-g -O2"
    CGO_LDFLAGS="-g -O2"
    PKG_CONFIG="pkg-config"
    GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build444735255=/tmp/go-build -gno-record-gcc-switches"
    
    question 
    opened by cjnosal 17
  • Should Transformers be recursive?

    Should Transformers be recursive?

    The current implementation of cmp.Equal recursively applies any Transformers that remain after applying all the filters. For a trivial Transformer of the type func(T) T, this will be recursively apply to the output since it will always match. For this reason, the cmpopts.SortSlices is wrapped with a FilterValues that acts as a "base-case" to prevent infinite recursion. One alteration to the algorithm is to say that a given Transformer cannot be recursively applied on a value that was transformed at some point by that very Transformer.

    The major advantage of non-recursive Transformers is:

    • A naive use of func(T) T works as expected without any need for a "base-case" filter.

    The disadvantages of non-recursive Transformer is:

    • The additional documentation needed to explain the special-case where Transformers are not executed. The implementation of this is essentially a set of "spent" Transformers, where transformers are added to the set when descending down the tree, and popped when ascending up the tree.
    • In some rare use-cases you may actually want Transformers to be recursive. Imagine you have a non-binary tree, where each node is essentially a set of children. When comparing this data-structure, you may want to sort each node using a transformer. You would need the property of recursive transformers to ensure each node may get transformed.
    • The need for "base-case" filters to prevent recursive cycles.

    Thoughts? I do see the value in non-recursive Transformers. It simplifies use of them, but prevents some very rare use-cases.

    \cc @bcmills @jba

    enhancement question 
    opened by dsnet 16
  • Add DiscardElements helper transformer

    Add DiscardElements helper transformer

    In some situations users want to compare two maps where missing entries are equal to those that have the zero value. For example, the following maps would be considered equal: x := map[string]int{"foo": 12345, "zero":0} y := map[string]int{"foo": 12345}

    To help with this, we add DiscardElements to cmpopts that transforms maps and slices by stripping entries based on a user provided function. To strip zero values, the user can provide: cmpopts.DiscardElements(func(v int) bool { return v == 0 })

    opened by dsnet 12
  • Allow use of AllowUnexported on GopherJS

    Allow use of AllowUnexported on GopherJS

    GopherJS does not have a complete implementation of unsafe, but it is complete enough that it can do basic pointer arithmetic, which is all we need to forcibly export an unexported field.

    opened by dsnet 11
  • refactor: expose the DefaultReporter

    refactor: expose the DefaultReporter

    I am trying to stop go-cmp from calling fmt.Stringer, as this in some cases makes the output worse instead of better.

    The DefaultReporter implementation is quite customizable, but this functionality is not exposed to the user.

    While users can register custom exporters, they would then need to re-implement the entire DefaultExporter, even though changing a single bool in it's config would suffice.

    This PR exposes the DefaultReporter implementation so it can be customized and used outside of this package

    opened by sh0rez 10
  • [FR] Change cmpopts.SortSlices param from `interface{}` to `func(a,b interface{}) bool`

    [FR] Change cmpopts.SortSlices param from `interface{}` to `func(a,b interface{}) bool`

    I just tried using cmpopts.SortSlices, and I know.. there are no generics in Go yet, but I think the current signature is not intuitive.

    Current state of the world:

    opt := cmpopts.SortSlices("yay") // can do whatever I want, it's an interface{}
    cmp.Diff(someFoo, otherFoo, opt)
    

    My desired state of the world:

    // Can still mess things up, but it's more obvious.
    opt := cmpopts.SortSlices(func (a, b interface{}){ return a.(Foo).Val < b.(Foo).Val })
    cmp.Diff(someFoo, otherFoo, opt)
    

    This proposal goes against Issue #67 but we could make it work like...

    opt := cmpopts.SortSlices(cmpopts.DefaultSort) // renamed GenericLess to DefaultSort
    cmp.Diff(someFoo, otherFoo, opt)
    
    opened by Goodwine 10
  • Bump minimum version to Go1.8

    Bump minimum version to Go1.8

    Go1.8 went GA on AppEngine. The lack of Go1.8 support was the primary reason for much of these backwards compatibility hacks.

    Bumping to Go1.8 still ensures that we're supporting at least the latest 2 versions of Go, which are Go1.8 and Go1.9.

    opened by dsnet 10
  • Use reflect.Value.IsZero

    Use reflect.Value.IsZero

    Now that Go 1.13 is the minimum version, we can use the reflect.Value.IsZero method instead of our own internal/value.IsZero function. Interestingly, our IsZero function pre-dates the IsZero method, but fortunately has the exact same semantics, since both are targetting semantics defined by the Go language specification.

    opened by dsnet 9
  • retrieveUnexportedField violates Go 1.14's checkptr validation, fails under -race

    retrieveUnexportedField violates Go 1.14's checkptr validation, fails under -race

    With Go tip (to become Go 1.14) and its new checkptr mode (enabled by default in -race mode on anything but Windows for now):

    === CONT  TestDiff/EqualMethod/StructE1
    panic: runtime error: unsafe pointer arithmetic [recovered]
            panic: runtime error: unsafe pointer arithmetic [recovered]
            panic: runtime error: unsafe pointer arithmetic
    
    goroutine 142 [running]:
    testing.tRunner.func1(0xc000238d00)
            /home/bradfitz/go/src/testing/testing.go:881 +0x69f
    panic(0x6f3c00, 0xc00000f5e0)
            /home/bradfitz/go/src/runtime/panic.go:679 +0x1b2
    github.com/google/go-cmp/cmp_test.TestDiff.func1.1.1(0xc000097eb8)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare_test.go:70 +0xfe
    panic(0x6f3c00, 0xc00000f5e0)
            /home/bradfitz/go/src/runtime/panic.go:679 +0x1b2
    github.com/google/go-cmp/cmp.retrieveUnexportedField(0x6e33c0, 0xc000128ad8, 0x199, 0x6ad073, 0xd, 0x6b70c3, 0x31, 0x778440, 0x6d34e0, 0x0, ...)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/export_unsafe.go:22 +0x7d
    github.com/google/go-cmp/cmp.StructField.Values(0xc0002bd300, 0x8, 0x42c5e0, 0x0, 0x0, 0xc00026f6c0, 0x203000)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/path.go:190 +0x187
    github.com/google/go-cmp/cmp.(*valueNode).PushStep(0xc0000a8420, 0x775540, 0xc0002bd300, 0x45bc9a)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/report_value.go:54 +0x5d
    github.com/google/go-cmp/cmp.(*defaultReporter).PushStep(0xc00027d680, 0x775540, 0xc0002bd300)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/report.go:24 +0x6e
    github.com/google/go-cmp/cmp.(*state).compareAny(0xc0002be900, 0x775540, 0xc0002bd300)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare.go:214 +0x22d
    github.com/google/go-cmp/cmp.(*state).compareStruct(0xc0002be900, 0x778440, 0x6e33c0, 0x6e33c0, 0xc000128ad8, 0x199, 0x6e33c0, 0xc000128ae0, 0x199)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare.go:383 +0x548
    github.com/google/go-cmp/cmp.(*state).compareAny(0xc0002be900, 0x775480, 0xc000012a00)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare.go:252 +0x1a58
    github.com/google/go-cmp/cmp.(*state).comparePtr(0xc0002be900, 0x778440, 0x6d8140, 0x6d8140, 0xc000128ad8, 0x16, 0x6d8140, 0xc000128ae0, 0x16)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare.go:513 +0x526
    github.com/google/go-cmp/cmp.(*state).compareAny(0xc0002be900, 0x775280, 0xc0000129c0)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare.go:258 +0x18e6
    github.com/google/go-cmp/cmp.Equal(0x6d8140, 0xc000128ad8, 0x6d8140, 0xc000128ae0, 0xc00000f580, 0x2, 0x2, 0x580c98)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare.go:107 +0x406
    github.com/google/go-cmp/cmp.Diff(0x6d8140, 0xc000128ad8, 0x6d8140, 0xc000128ae0, 0xc00012ab70, 0x1, 0x1, 0xc000106000, 0xc000106070)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare.go:127 +0x1ce
    github.com/google/go-cmp/cmp_test.TestDiff.func1.1(0xc000241eb8, 0xc00023c600, 0xc0002f7ec8)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare_test.go:74 +0x138
    github.com/google/go-cmp/cmp_test.TestDiff.func1(0xc000238d00)
            /home/bradfitz/pkg/mod/github.com/google/[email protected]/cmp/compare_test.go:75 +0x99
    testing.tRunner(0xc000238d00, 0xc0001c1bd0)
            /home/bradfitz/go/src/testing/testing.go:916 +0x19a
    created by testing.(*T).Run
            /home/bradfitz/go/src/testing/testing.go:967 +0x652
    FAIL    github.com/google/go-cmp/cmp    0.116s
    
    opened by bradfitz 9
  • proposal: support cyclic data structures

    proposal: support cyclic data structures

    Hi The following program crashes on an infinite recursion:

    package main
    
    import "github.com/google/go-cmp/cmp"
    
    type Node struct {
    	Next *Node
    }
    
    func main() {
    	a := &Node{}
    	a.Next = a
    
    	cmp.Equal(a, a)
    }
    

    Fixing this is needed to use this package in testify.

    I saw that there is already a TODO comment.

    enhancement 
    opened by posener 9
  • Adjust heuristic for line-based versus byte-based diffing

    Adjust heuristic for line-based versus byte-based diffing

    If the string has many characters that require escape sequences to print, then we need to take that into consideration and avoid byte-by-byte diffing.

    opened by dsnet 1
  • Recursive output poorly reported

    Recursive output poorly reported

    We have a case where we have a linked datastructure pointing to both children and parent nodes. Due to a bug in our test implementation we were getting a result that seems like a false-positive, but in fact cmp hides the actual difference under ref#0. This occurrs because the data structure has the same values, but different pointer addresses. See the simplified example input and output below:

    func Test_demo(t *testing.T) {
    	type node struct {
    		parent *node
    		child  *node
    	}
    
    	t2 := &node{}
    	t1 := &node{child: t2}
    	t2.parent = t1
    
    	t3 := &node{child: t2}
    	t2.parent = t3
    
    	if diff := cmp.Diff(t1, t3, cmp.AllowUnexported(node{})); diff != "" {
    		t.Errorf("node mismatch (-want +got):\n%s", diff)
    	}
    }
    

    which produces the following output:

        demo_test.go:20: node mismatch (-want +got):
              &⟪ref#0⟫demo.node{
                    parent: nil,
                    child: &demo.node{
            -               parent: &⟪ref#0: 0x0140004009b0⟫(...),
            +               parent: &⟪ref#0: 0x0140004009b0⟫(...),
                            child:  nil,
                    },
              }
    

    The example code is obviously flawed, but in our case that was hidden among 100 other lines before it was distilled to these lines

    bug 
    opened by ajpetersons 5
  • Add build tag to force use of unsafe even with purego?

    Add build tag to force use of unsafe even with purego?

    In https://github.com/golang/go/issues/23172#issuecomment-1000544013, @cespare writes:

    It's unfortunate that the best reference for this convention is still this issue, since in the intervening four years no documentation change has been merged.

    Additionally, I have found during this time that, in practice, I cannot use the purego tag for its intended purpose in our internal codebase at my company. The reason is that we use go-cmp. Some of go-cmp's core functionality is unsafe. That functionality is now behind a purego build tag. Enabling the purego tag makes most of our tests panic. We have packages with asm as well as pure-Go implementations, and we often want to run automated tests of both code paths, but we cannot run the tests with purego, so we end up using a different build tag to indicate "Go rather than assembly".

    I'm not even sure what the right fix is. Maybe the ideal outcome would be that something in the Go standard library (testing? reflect?) would allow go-cmp to do what it needs to do without unsafe. But for now, the existence and popularity of go-cmp kind of "infects" the purego tag and makes it a not-very-useful convention.

    I'm not sure what the right fix is, but perhaps an explicit gocmp_unsafe build tag that enables the use of unsafe even if purego is specified? There isn't an obvious fix here since we must use unsafe to introspect unexported fields.

    \cc @neild

    opened by dsnet 2
  • Add cmpopts.FilterValue

    Add cmpopts.FilterValue

    cmp.FilterValues expects a function of the signature func(T, T) bool where the function is called with values from both the left argument and the right argument.

    I propose the addition of cmpopts.FilterValue that is semantically equivalent to:

    func FilterValue[T any](f func(T) bool) cmp.Option {
        return cmp.FilterValues(func(x, y T) bool {
            return f(x) && f(y)
        })
    }
    

    The current cmp.FilterValues is more powerful as you can make a filtering decision based on information from both values, but most usages of it want the logical AND of a single-argument predicate function. In fact, all of the usages of cmp.FilterValues in cmpopts would prefer to use a single-argument predicate function. Examples:

    • https://github.com/google/go-cmp/blob/6faefd0594fae82639a62c23f0aed1451509dcc0/cmp/cmpopts/equate.go#L26-L31
    • https://github.com/google/go-cmp/blob/6faefd0594fae82639a62c23f0aed1451509dcc0/cmp/cmpopts/equate.go#L60-L62
    • https://github.com/google/go-cmp/blob/6faefd0594fae82639a62c23f0aed1451509dcc0/cmp/cmpopts/equate.go#L85-L87
    • https://github.com/google/go-cmp/blob/6faefd0594fae82639a62c23f0aed1451509dcc0/cmp/cmpopts/equate.go#L104-L106
    • https://github.com/google/go-cmp/blob/6faefd0594fae82639a62c23f0aed1451509dcc0/cmp/cmpopts/equate.go#L144-L148

    Alternatively, we could modify cmp.FilterValues to also accept a function of the form func(T) bool where it effectively performs the AND of the predicate function applies to both arguments.

    \cc @neild

    opened by dsnet 4
Releases(v0.5.8)
  • v0.5.8(Apr 26, 2022)

    Reporter changes:

    • (#293) Fix printing of types in reporter output for interface and pointer types
    • (#294) Use string formatting for slice of bytes in more circumstances

    Dependency changes:

    • (#292) Update minimum supported version to go1.13 and remove xerrors dependency
    Source code(tar.gz)
    Source code(zip)
  • v0.5.7(Jan 19, 2022)

    Reporter changes:

    • (#266) Fix textual printing of byte slices
    • (#275) Reduce minimum length for specialize string diffing
    • (#276) Use any alias instead of interface{}

    Code cleanup changes:

    • (#281) Update minimum supported version to go1.11
    • (#282) Drop hacks to work around Go reflection bugs in Go1.9
    • (#285) Add //go:build lines
    • (#262) Fix staticcheck findings
    • (#263) Avoid shadowing variable
    • (#268) Use sha256 in test
    • (#271) Fix spelling mistakes
    • (#269) Change build status badge
    Source code(tar.gz)
    Source code(zip)
  • v0.5.6(May 25, 2021)

    Reporter changes:

    • (#258) Print as text if mostly text
    • (#259) Cleanup edit groups after coalescing
    • (#260) Avoid diffing by lines if inefficient

    Minor documentation changes:

    • (#256) Fix typo in path.go
    Source code(tar.gz)
    Source code(zip)
  • v0.5.5(Mar 4, 2021)

    Bug fixes:

    • (#253) Fix reporter verbosity bug

    Reporter changes:

    • (#254) De-virtualize interfaces for specialized diffing

    Dependency changes:

    • (#251) Use errors.Is with ≥go1.13 in compareErrors
    Source code(tar.gz)
    Source code(zip)
  • v0.5.4(Nov 24, 2020)

  • v0.5.3(Nov 12, 2020)

  • v0.5.2(Aug 25, 2020)

  • v0.5.1(Jul 21, 2020)

    Minor reporter changes:

    • (#221) Swallow panics when calling String or Error methds.
    • (#229) Use triple-quote formatting for multiline strings in diffs.

    Minor documentation changes:

    • (#228) Adjust panic for IgnoreUnexported and IgnoreFields to be more specific.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Jun 18, 2020)

    The most notable changes in this release are improvements to the reporter output (i.e., the implementation that produces output for Diff). The changes seek to improve the signal-to-noise ratio such that differences of interest to the user are emphasized, while information that is less relevant are de-emphasized.

    The reporter largely consists of a set of heuristics to determine what would be the best way to format the difference in the common case. If the output seems sub-par, please file an issue. The reports are highly valuable in improving its output (e.g., #195, #194, #202, #185).

    Reporter changes:

    • (#201) Do not use custom format for nil slice. Previously, the reporter had a bug (#157) where it would fail to print the difference between empty slices that were nil versus non-nil, which is now fixed by this change.
    • (#212) Use custom triple-quote syntax for diffing string literals. This adds another way that strings are displayed. Previously, the reporter used a strings.Join({...}, "\n") syntax to show diffs between lines within a string. While this representation is unambiguous, the need to escape every line made the output visually distracting. Now, we add a new syntax where multiple lines are represented by a literal syntax using """ as delimiters. When possible, this syntax is preferred if it can unambiguously represent the difference.
    • (#208) Batch reporter output for simple lists of text elements. Previously, when formatting a slice of primitives, the reporter would print each element on a new line, causing the output to be long. Now, multiple elements are batched together into a single line to keep the output more dense.
    • (#210) Allow batched diffing of slices with a custom comparer. As a performance optimization, a user may choose to pass cmp.Comparer(bytes.Equal) so that large byte slices are compared using an efficient implementation. Previously, this would prevent the reporter from being able to use specialized logic to show the per-element difference between these two slices if they were different, but now it is able to.
    • (#213, #215) Limit verbosity of reporter output. For slices, maps, and structs, the reporter now imposes a limit on the number of elements, entries, and structs that it will print. The limit is chosen based on heuristics such as the depth of the tree and also whether the node represents an equal value or not, where inequal values are given a larger verbosity budget.
    • (#216) Disambiguate reporter output. Previously, there were certain edge cases where the reporter output failed to show a difference between two values that the comparer determined to be different. Now, the reporter works harder to ensure that the output is guaranteed to be different if a semantic difference is there. For example, it may try increasing the verbosity limit, printing pointer addresses, avoid calling the String method, using fully qualified type names, or some combination of the above.
    • (#217) Improve reporting of values with cycles. Previously, the reporter would simply truncate the result if it ever detected a cycle. While this prevents a stack overflow trying to print a graph, it failed to properly show the topology of the graph. Now, the reporter additionally provides reference markers so that the user can visually identify where a pointer refers to in the output.
    • (1776240f8f841dfa00cb72d811301dbb0298f983) Forcibly export fields for use by the reporter. This allows the reporter to use the String or Error method (if available) to format values within unexported fields. This occurs regardless of whether any cmp.Exporter or cmp.AllowUnexported options are used or not.
    • (#210) Use raw string literal syntax only for valid UTF-8. This fixes a minor bug in the reporter to ensure that the output is always valid UTF-8.

    Feature changes:

    • (#203) Permit use of IgnoreFields with unexported fields. The cmpopts.IgnoreFields option now accepts unexported field names. Unlike exported fields, unexported field must be explicitly specified as they do not respect forwarding due to struct embedding.

    Comparer changes:

    • (#204) Optimize Diff for frequent equality. The cmp package is intended for use primarily within tests where the expected outcome is generally equality. Previously, even if the result is equal, cmp.Diff would construct an expensive diff tree only to discard the result since the values are equal. Now, optimize for the common case by first checking whether the values are equal first, and only construct a diff if they are not.
    • (#214) Introduce deliberate instability to difference output. The internal algorithm used for diffing elements of a slice is sub-optimal. It does not produce an optimal edit script (i.e., one with the fewest possible reported differences), but is guaranteed to run in O(n). To keep the future open for algorithmic improvements, introduce some degree of deliberate instability so that users do not accidentally rely on it's output being stable.
    • (#206) Avoid leaking implementation details of the exporter. In order for the current implementation to forcibly access unexported fields using unsafe, it requires that the parent struct be addressable. In Go, a struct field is only addressable if and only if the parent struct is addressable. To avoid leaking this internal implementation detail, we shallow copy the result to remove properties of addressability.
    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(May 15, 2020)

    Minor reporter changes:

    • (#199) Format uints in decimal except bytes.

    Minor documentation changes:

    • (#190) Update README.md to use go.dev for documentation.
    • (#189) Document the test-only intentions of this package.
    • (#193) Fix typo on example
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Jan 7, 2020)

    Added features:

    Bug fixes:

    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Aug 7, 2019)

    Minor reporter fixes:

    • (#142) Fixed reporter to invoke the String method when formatting map keys.
    • (#148) Fixed reporter to properly elide a struct field on the right side if it is a zero value.
    • (#147) Fixed reporter to avoid diffing by lines if any line exceeds a certain maximum length.
    • (#152) Fixed reporter to properly treat -0.0 as not being the zero value.
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Apr 29, 2019)

    Added features:

    • (#108) The _ field is always ignored when comparing a struct.
    • (#109) The naming rules for cmp.Transformer is relaxed and clearly specified.
    • (#82) cmpopts.AcyclicTransformer makes it easier to write a transformer that avoids infinite recursion when the output type contains the input type.
    • (#126) cmpopts.IgnoreSliceElements and cmpopts.IgnoreMapEntries provide the ability to ignore specific slice elements or map entries.
    • (#123) cmp.Reporter provides users the ability to add custom difference reporters.
    • (#119) cmp.PathStep.Values provide the current reflect.Value for the x and y arguments at that given path step.

    Bug fixes:

    • (#87) Fixed proper comparing of slices where one is a sub-slice of the other.

    Reporter changes:

    • (#124) The cmp.Diff output has been completely re-written to provide a unified diff of the two Go objects as a literal in pseudo-Go syntax (example).
    • (#131) The default reporter has built-in heuristics to detect whether a string or a byte-slice looks like binary data or human readable text, and can provide more humanly readable differences in certain use-cases. For example, a string may be detecting as containing multiple lines of text, for which it will print the difference based on the lines.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Feb 20, 2018)

    Added Features:

    • Add implicit filter to transformers where a Transformer can only apply if that specific transformer does not already exist within the tail of the current Path since the last non-transform step. This filter makes it easier to create same-type transformations (e.g., func(T) T) without needing to manually add your own filter. (#29)

    • Add Path.Index method, which provides an easier way to index a Path without needing to manually perform bounds checking. (#56)

    • Add Transform.Option method, which returns the original Transformer option. This enables the creation of non-reentrant transformers. (#59)

    • Add handling for purego build tag, which prevents use of unsafe, which is necessary to implementAllowUnexported. However, unsafe is not available in some build environments such as GopherJS and Google AppEngine Standard. A future release will remove special casing for these two environments. (#68)

    Reporting changes:

    • Diff only batches multiple differences together for slices of primitives. (#45)
    • Diff prints uses a s prefix to indicate that the String method was used. (#46)
    • Diff prints strings using the raw literal syntax when helpful. (#46)
    • Diff reports the type of a primitive when helpful. (#65)
    • Path.GoString elides printing type assertions on anonymous types. (#21)

    Bug fixes:

    • Unexported map values no longer panics when printing. (#38)
    • Explicitly convert assignable nil interface values. This works around a reflect bug present in Go1.9 and below. (#49)
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Aug 9, 2017)

    Package cmp is intended to be a more powerful and safer alternative to reflect.DeepEqual for comparing whether two values are semantically equal.

    The primary features of cmp are:

    • When the default behavior of equality does not suit the needs of the test, custom equality functions can override the equality operation. For example, an equality function may report floats as equal so long as they are within some tolerance of each other.

    • Types that have an Equal method may use that method to determine equality. This allows package authors to determine the equality operation for the types that they define.

    • If no custom equality functions are used and no Equal method is defined, equality is determined by recursively comparing the primitive kinds on both values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported fields are not compared by default; they result in panics unless suppressed by using an Ignore option (see cmpopts.IgnoreUnexported) or explictly compared using the AllowUnexported option.

    Package API:

    func Equal(x, y interface{}, opts ...Option) bool { ... }
    func Diff(x, y interface{}, opts ...Option) string { ... }
    
    // Section: 1. Configuration options for Equal and Diff
    type Option interface{ ... }
        func AllowUnexported(types ...interface{}) Option { ... }
    type Options []Option
    
    // Section: 1.1. Fundamental options to customize comparison of values
    func Ignore() Option { ... }
    func Comparer(f func(T, T) bool) Option { ... }
    func Transformer(name string, f func(T) R) Option { ... }
    
    // Section: 1.2. Filter options to control the scope of fundamental options
    func FilterPath(f func(Path) bool, opt Option) Option { ... }
    func FilterValues(f func(T, T) bool, opt Option) Option { ... }
    
    // Section: 2. Path to a node in the value tree
    type Path []PathStep
    type PathStep interface{ ... }
    
    // Section: 2.1. Individual steps that comprise a Path
    type StructField interface{ ... }
    type SliceIndex interface{ ... }
    type MapIndex interface{ ... }
    type Indirect interface{ ... }
    type TypeAssertion interface{ ... }
    type Transform interface{ ... }
    

    Package cmpopts provides helper functions for creating cmp.Option values to configure comparisons for common use-cases.

    Package API:

    // Section: Comparers
    func EquateApprox(fraction, margin float64) cmp.Option { ... }
    func EquateEmpty() cmp.Option { ... }
    func EquateNaNs() cmp.Option { ... }
    
    // Section: Ignorers
    func IgnoreFields(typ interface{}, names ...string) cmp.Option { ... }
    func IgnoreInterfaces(ifaces interface{}) cmp.Option { ... }
    func IgnoreTypes(typs ...interface{}) cmp.Option { ... }
    func IgnoreUnexported(typs ...interface{}) cmp.Option { ... }
    
    // Section: Transformers
    func SortMaps(less func(T, T) bool) cmp.Option { ... }
    func SortSlices(less func(T, T) bool) cmp.Option { ... }
    
    Source code(tar.gz)
    Source code(zip)
Owner
Google
Google ❤️ Open Source
Google
Extremely flexible golang deep comparison, extends the go testing package and tests HTTP APIs

go-testdeep Extremely flexible golang deep comparison, extends the go testing package. Latest news Synopsis Description Installation Functions Availab

Maxime Soulé 312 Aug 4, 2022
Package has tool to generate workload for vegeta based kube-api stress tests.

Package has tool to generate workload for vegeta based kube-api stress tests.

Mikhail Sakhnov 0 Nov 22, 2021
Record and replay your HTTP interactions for fast, deterministic and accurate tests

go-vcr go-vcr simplifies testing by recording your HTTP interactions and replaying them in future runs in order to provide fast, deterministic and acc

Marin Atanasov Nikolov 893 Jul 27, 2022
Go testing in the browser. Integrates with `go test`. Write behavioral tests in Go.

GoConvey is awesome Go testing Welcome to GoConvey, a yummy Go testing tool for gophers. Works with go test. Use it in the terminal or browser accordi

SmartyStreets 7.4k Aug 12, 2022
Testing framework for Go. Allows writing self-documenting tests/specifications, and executes them concurrently and safely isolated. [UNMAINTAINED]

GoSpec GoSpec is a BDD-style testing framework for the Go programming language. It allows writing self-documenting tests/specs, and executes them in p

Esko Luontola 112 Apr 5, 2022
Ruby on Rails like test fixtures for Go. Write tests against a real database

testfixtures Warning: this package will wipe the database data before loading the fixtures! It is supposed to be used on a test database. Please, doub

null 826 Aug 1, 2022
Automatically update your Go tests

autogold - automatically update your Go tests autogold makes go test -update automatically update your Go tests (golden files and Go values in e.g. fo

Hexops 123 Jun 30, 2022
A simple `fs.FS` implementation to be used inside tests.

testfs A simple fs.FS which is contained in a test (using testing.TB's TempDir()) and with a few helper methods. PS: This lib only works on Go 1.16+.

Carlos Alexandro Becker 31 Mar 3, 2022
A next-generation testing tool. Orion provides a powerful DSL to write and automate your acceptance tests

Orion is born to change the way we implement our acceptance tests. It takes advantage of HCL from Hashicorp t o provide a simple DSL to write the acceptance tests.

Wesovi Labs 43 Jul 16, 2022
Terratest is a Go library that makes it easier to write automated tests for your infrastructure code.

Terratest is a Go library that makes it easier to write automated tests for your infrastructure code. It provides a variety of helper functions and patterns for common infrastructure testing tasks,

Gruntwork 6.2k Aug 4, 2022
Go testing in the browser. Integrates with `go test`. Write behavioral tests in Go.

GoConvey is awesome Go testing Welcome to GoConvey, a yummy Go testing tool for gophers. Works with go test. Use it in the terminal or browser accordi

SmartyStreets 7.4k Aug 7, 2022
gostub is a library to make stubbing in unit tests easy

gostub gostub is a library to make stubbing in unit tests easy. Getting started Import the following package: github.com/prashantv/gostub Click here t

Prashant Varanasi 243 Jul 29, 2022
Golang application focused on tests

Maceio Golang application that listens for webhook events coming from Github, runs tests previously defined in a configuration file and returns the ou

Leonardo Damasceno 5 Sep 8, 2021
Robust framework for running complex workload scenarios in isolation, using Go; for integration, e2e tests, benchmarks and more! 💪

e2e Go Module providing robust framework for running complex workload scenarios in isolation, using Go and Docker. For integration, e2e tests, benchma

null 105 Jul 20, 2022
gomonkey is a library to make monkey patching in unit tests easy

gomonkey is a library to make monkey patching in unit tests easy, and the core idea of monkey patching comes from Bouke, you can read this blogpost for an explanation on how it works.

Zhang Xiaolong 1.2k Aug 12, 2022
A simple and expressive HTTP server mocking library for end-to-end tests in Go.

mockhttp A simple and expressive HTTP server mocking library for end-to-end tests in Go. Installation go get -d github.com/americanas-go/mockhttp Exa

Americanas Go 6 Dec 19, 2021
How we can run unit tests in parallel mode with failpoint injection taking effect and without injection race

This is a simple demo to show how we can run unit tests in parallel mode with failpoint injection taking effect and without injection race. The basic

amyangfei 1 Oct 31, 2021
Learning go with tests! Also setting up automated versioning via SemVer.

learn-go-with-tests The purpose of this repo is to complete the learn-go-with-test course located here. I am also interested in learning how to automa

Derek Willingham 0 Nov 23, 2021
S3 etag tests for golang

S3-etag-tests Quickstart Run docker-compose up. Execute tests in /test with $ go

null 0 Dec 16, 2021