Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add docs #9

Merged
merged 2 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Go
name: CI

on:
push:
Expand Down
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# teq

![CI](https://github.com/seiyab/teq/actions/workflows/go.yml/badge.svg)

teq is a Go library designed to enhance your testing experience by providing a flexible and customizable way to perform deep equality checks. It's especially useful when you need to compare complex objects or types that have specific equality conditions.

## Features

- Transforms: Register a "transform" function that can modify objects before comparison. This allows you to control how equality is determined. For example, by transforming time.Time objects to UTC, you can make your equality checks timezone-insensitive.
- Formats: Register a "format" function that defines how objects are displayed when they are not equal. This is useful for types like time.Time and decimal.Decimal that may not be human-readable in their default format. By registering your own format, you can make the output of your tests more understandable.

## Installation

```sh
go get github.com/seiyab/teq@latest
```

## Usage

To use teq, you first need to create a new instance:

```go
tq := teq.New()
```

Then, you can add your transforms and formats:

```go
// time.Time will be transformed into UTC time. So equality check with `tq` will be timezone-insensitive.
tq.AddTransform(func(d time.Time) time.Time {
return d.In(d.UTC)
})

// time.Time will be shown in RFC3339 format when it appear in diff.
tq.AddFormat(func(d time.Time) string {
return d.Format(time.RFC3339)
})
```

Finally, you can use teq to perform deep equality checks in your tests:

```go
tq.Equal(t, expected, actual)
```

If you need "common" equality across your project, we recommend to define function that returns your customized teq.

```go
func NewTeq() teq.Teq {
tq := teq.New()
tq.AddTransform(/* ... */)
tq.AddTransform(/* ... */)
// :
return tq
}

// then you can use easily it everywhere
tq := NewTeq()
```

## Prior works

- [testify](https://github.com/stretchr/testify)
- [deepequal.go](https://github.com/weaveworks/scope/blob/12175b96a3456f1c2b050f1e1d6432498ed64d95/test/reflect/deepequal.go) in "github.com/weaveworks/scope/test/reflect" package authored by Weaveworks Ltd
- [go-cmp](https://github.com/google/go-cmp)
31 changes: 31 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Package teq is a Go library designed to enhance your testing experience by providing a flexible and customizable way to perform deep equality checks. It's especially useful when you need to compare complex objects or types that have specific equality conditions.

# Features

- Transforms: Register a "transform" function that can modify objects before comparison. This allows you to control how equality is determined. For example, by transforming time.Time objects to UTC, you can make your equality checks timezone-insensitive.
- Formats: Register a "format" function that defines how objects are displayed when they are not equal. This is useful for types like time.Time and decimal.Decimal that may not be human-readable in their default format. By registering your own format, you can make the output of your tests more understandable.

# Usage

To use teq, you first need to create a new instance:

tq := teq.New()

Then, you can add your transforms and formats:

// time.Time will be transformed into UTC time. So equality check with `tq` will be timezone-insensitive.
tq.AddTransform(func(d time.Time) time.Time {
return d.In(d.UTC)
})

// time.Time will be shown in RFC3339 format when it appear in diff.
tq.AddFormat(func(d time.Time) string {
return d.Format(time.RFC3339)
})

Finally, you can use teq to perform deep equality checks in your tests:

tq.Equal(t, expected, actual)
*/
package teq
16 changes: 16 additions & 0 deletions teq.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import (
"reflect"
)

// Teq is a object for deep equality comparison.
type Teq struct {
// MaxDepth is the maximum depth of the comparison. Default is 1000.
MaxDepth int

transforms map[reflect.Type]func(reflect.Value) reflect.Value
formats map[reflect.Type]func(reflect.Value) string
}

// New returns new instance of Teq.
func New() Teq {
return Teq{
MaxDepth: 1_000,
Expand All @@ -20,6 +23,7 @@ func New() Teq {
}
}

// Equal perform deep equality check and report error if not equal.
func (teq Teq) Equal(t TestingT, expected, actual any) bool {
t.Helper()
defer func() {
Expand All @@ -34,6 +38,7 @@ func (teq Teq) Equal(t TestingT, expected, actual any) bool {
return ok
}

// NotEqual perform deep equality check and report error if equal.
func (teq Teq) NotEqual(t TestingT, expected, actual any) bool {
t.Helper()
defer func() {
Expand All @@ -54,6 +59,12 @@ func (teq Teq) NotEqual(t TestingT, expected, actual any) bool {

}

// AddTransform adds a transform function to Teq.
// The transform function must have only one argument and one return value.
// The argument type is the type to be transformed.
// If the passed transform function is not valid, it will panic.
// The transformed value will be used for equality check instead of the original value.
// The transformed value and its internal values won't be transformed to prevent infinite recursion.
func (teq *Teq) AddTransform(transform any) {
ty := reflect.TypeOf(transform)
if ty.Kind() != reflect.Func {
Expand All @@ -72,6 +83,11 @@ func (teq *Teq) AddTransform(transform any) {
teq.transforms[ty.In(0)] = reflectTransform
}

// AddFormat adds a format function to Teq.
// The format function must have only one argument and one return value.
// The argument type is the type to be formatted.
// If the passed format function is not valid, it will panic.
// The formatted string will be shown instead of the original value in the error report when the values are not equal.
func (teq *Teq) AddFormat(format any) {
ty := reflect.TypeOf(format)
if ty.Kind() != reflect.Func {
Expand Down
Loading