Skip to content

Commit

Permalink
Merge branch 'main' into gh-pages
Browse files Browse the repository at this point in the history
  • Loading branch information
expectto committed Feb 8, 2024
2 parents fb82105 + 9595302 commit de3ca8b
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 88 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Expect(req).To(be_http.Request(
be_json.Matcher(
be_json.JsonAsReader,
be_json.HaveKeyValue("hello", "world"),
be_json.HaveKeyValue("n", be_reflected.AsIntish()),
be_json.HaveKeyValue("n", be_reflected.AsInteger()),
be_json.HaveKeyValue("ids", be_reflected.AsSliceOf[string]),
be_json.HaveKeyValue("details", And(
be_reflected.AsObjects(),
Expand Down Expand Up @@ -121,7 +121,7 @@ types.<br>[See detailed docs](be_reflected/README.md)

#### Data Type Matchers based on reflect.Kind

`AsString`, `AsBytes`, `AsNumeric`, `AsNumericString`, `AsIntish`, `AsIntishString`, `AsFloatish`, `AsFloatishString`,
`AsString`, `AsBytes`, `AsNumeric`, `AsNumericString`, `AsInteger`, `AsIntegerString`, `AsFloat`, `AsFloatishString`,

#### Interface Matchers based on reflect.Kind

Expand Down
6 changes: 2 additions & 4 deletions be_math/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ DivisibleBy succeeds if actual is numerically divisible by the passed-in value.
```go
func Even() types.BeMatcher
```
Even succeeds if actual is an even numeric value. todo: test if failure message
is OK
Even succeeds if actual is an even numeric value.

#### func GreaterThan

Expand Down Expand Up @@ -128,8 +127,7 @@ Negative succeeds if actual is a negative numeric value.
```go
func Odd() types.BeMatcher
```
Odd succeeds if actual is an odd numeric value. todo: test if failure message is
OK
Odd succeeds if actual is an odd numeric value.

#### func Positive

Expand Down
37 changes: 24 additions & 13 deletions be_math/matchers_math.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,51 +53,62 @@ func InRange(from any, fromInclusive bool, until any, untilInclusive bool) types
} else {
group[1] = Lt(until)
}
return psi_matchers.NewAllMatcher(cast.AsSliceOfAny(group)...)

// For compiling a nice failure message we better use `[from, until)` format
leftBracket, rightBracket := "(", ")"
if fromInclusive {
leftBracket = "["
}
if untilInclusive {
rightBracket = "]"
}

return WithCustomMessage(
psi_matchers.NewAllMatcher(cast.AsSliceOfAny(group)...),
fmt.Sprintf("be in range %s%v, %v%s", leftBracket, from, until, rightBracket),
)
}

// Odd succeeds if actual is an odd numeric value.
// todo: test if failure message is OK
func Odd() types.BeMatcher {
return Psi(
be_reflected.AsIntish(),
return WithCustomMessage(psi_matchers.NewAllMatcher(
be_reflected.AsInteger(),
WithFallibleTransform(func(actual any) any {
return int(cast.AsFloat(actual))%2 != 0
}, gomega.BeTrue()),
)
), "be an odd number")
}

// Even succeeds if actual is an even numeric value.
// todo: test if failure message is OK
func Even() types.BeMatcher {
return Psi(
be_reflected.AsIntish(),
return WithCustomMessage(psi_matchers.NewAllMatcher(
be_reflected.AsInteger(),
WithFallibleTransform(func(actual any) any {
return int(cast.AsFloat(actual))%2 == 0
}, gomega.BeTrue()),
)
), "be an even number")
}

// Negative succeeds if actual is a negative numeric value.
func Negative() types.BeMatcher {
return Psi(gcustom.MakeMatcher(LessThan(0.0).Match, "be negative"))
return WithCustomMessage(LessThan(0.0), "be negative")
}

// Positive succeeds if actual is a positive numeric value.
func Positive() types.BeMatcher {
return Psi(gcustom.MakeMatcher(GreaterThan(0.0).Match, "be positive"))
return WithCustomMessage(GreaterThan(0.0), "be positive")
}

// Zero succeeds if actual is numerically equal to zero.
// Any type of int/float will work for comparison.
func Zero() types.BeMatcher {
return Psi(gcustom.MakeMatcher(Approx(0, 0).Match, "be zero"))
return WithCustomMessage(Approx(0, 0), "be zero")
}

// ApproxZero succeeds if actual is numerically approximately equal to zero
// Any type of int/float will work for comparison.
func ApproxZero() types.BeMatcher {
return Psi(gcustom.MakeMatcher(Approx(0, 1e-8).Match, "be approximately zero"))
return WithCustomMessage(Approx(0, 1e-8), "be approximately zero")
}

// Integral succeeds if actual is an integral float, meaning it has zero decimal places.
Expand Down
33 changes: 31 additions & 2 deletions be_math/matchers_math_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ import (
"github.com/expectto/be/types"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"strings"
)

var _ = Describe("BeMath", func() {

DescribeTable("should positively match", func(matcher types.BeMatcher, actual any) {
// check gomega-compatible matching:
success, err := matcher.Match(actual)
Expect(err).Should(Succeed())
Expect(success).To(BeTrue())

// check gomock-compatible matching:
success = matcher.Matches(actual)
Expect(success).To(BeTrue())
},
Entry("10 GreaterThan 5", be_math.GreaterThan(5), 10),
Entry("10 GreaterThan 5 (alias)", be_math.Gt(5), 10),
Expand Down Expand Up @@ -71,9 +77,14 @@ var _ = Describe("BeMath", func() {
)

DescribeTable("should negatively match", func(matcher types.BeMatcher, actual any) {
// check gomega-compatible matching:
success, err := matcher.Match(actual)
Expect(err).Should(Succeed())
Expect(success).To(BeFalse())

// check gomock-compatible matching:
success = matcher.Matches(actual)
Expect(success).To(BeFalse())
},
Entry("5 is not GreaterThan 10", be_math.GreaterThan(10), 5),
Entry("5 is not GreaterThan 5 (alias)", be_math.Gt(5), 5),
Expand Down Expand Up @@ -104,11 +115,13 @@ var _ = Describe("BeMath", func() {
Entry("4 is not an odd number", be_math.Odd(), 4),
Entry("-2 is not an odd number", be_math.Odd(), -2),
Entry("-4 is not an odd number", be_math.Odd(), -4),
Entry("floats can't be matched as odd numbers", be_math.Odd(), 1.5),

Entry("3 is not an even number", be_math.Even(), 3),
Entry("7 is not an even number", be_math.Even(), 7),
Entry("-3 is not an even number", be_math.Even(), -3),
Entry("-7 is not an even number", be_math.Even(), -7),
Entry("floats can't be matched as even numbers", be_math.Even(), 1.5),

Entry("5 is not a negative number", be_math.Negative(), 5),
Entry("8.5 is not a negative number", be_math.Negative(), 8.5),
Expand All @@ -127,11 +140,27 @@ var _ = Describe("BeMath", func() {
)

DescribeTable("should return a valid failure message", func(matcher types.BeMatcher, actual any, message string) {
Expect(matcher.FailureMessage(actual)).To(Equal(message))
// FailureMessage is considered to be called after matching:
_, _ = matcher.Match(actual)

failureMessage := matcher.FailureMessage(actual)
Expect(failureMessage).To(Equal(message))

// in all our matchers negated failure messages are simply `to be` => `not to be`
Expect(matcher.NegatedFailureMessage(actual)).To(Equal(
strings.Replace(failureMessage, "\nto be ", "\nnot to be ", 1),
))
},
// Example of entry where FailureMessage is simply inherited from gomega's underlying matching
Entry("5 is not GreaterThan 10", be_math.GreaterThan(10), 5, "Expected\n <int>: 5\nto be >\n <int>: 10"),
Entry("10 is not divisible by 3", be_math.DivisibleBy(3), 10, "Expected:\n <int>: 10\nto be divisible by 3"),

// Examples of entry with custom message (gcustom.MakeMatcher matching)
Entry("10 is not divisible by 3", be_math.DivisibleBy(3), 10, "Expected:\n <int>: 10\nto be divisible by 3"),
Entry("0.1 is not zero", be_math.Zero(), 0.1, "Expected:\n <float64>: 0.1\nto be zero"),

// Examples of entry on complex Psi matchers (chaining + transform)
Entry("float is not odd", be_math.Odd(), 12.5, "Expected:\n <float64>: 12.5\nto be an odd number"),
Entry("8 is not odd", be_math.Odd(), 8, "Expected:\n <int>: 8\nto be an odd number"),
Entry("8 (uint) is not odd", be_math.Odd(), uint(8), "Expected:\n <uint>: 8\nto be an odd number"),
)
})
37 changes: 20 additions & 17 deletions be_reflected/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import "github.com/expectto/be/be_reflected"

Package be_reflected provides Be matchers that use reflection, enabling
expressive assertions on values' reflect kinds and types.
expressive assertions on values' reflect kinds and types. It consists of several
"core" matchers e.g. AsKind / AssignableTo / Implementing And many other
matchers that are made on-top on core ones. E.g. AsFunc / AsString / AsNumber /
### etc

## Usage

Expand All @@ -29,20 +32,20 @@ func AsFinalPointer() types.BeMatcher
AsFinalPointer succeeds if the actual value is a final pointer, meaning it's a
pointer to a non-pointer type.

#### func AsFloatish
#### func AsFloat

```go
func AsFloatish() types.BeMatcher
func AsFloat() types.BeMatcher
```
AsFloatish succeeds if actual is a numeric value that represents a
floating-point value.
AsFloat succeeds if actual is a numeric value that represents a floating-point
value.

#### func AsFloatishString
#### func AsFloatString

```go
func AsFloatishString() types.BeMatcher
func AsFloatString() types.BeMatcher
```
AsFloatishString succeeds if actual is a string that can be parsed into a valid
AsFloatString succeeds if actual is a string that can be parsed into a valid
floating-point value.

#### func AsFunc
Expand All @@ -52,20 +55,20 @@ func AsFunc() types.BeMatcher
```
AsFunc succeeds if actual is of kind reflect.Func.

#### func AsIntish
#### func AsInteger

```go
func AsIntish() types.BeMatcher
func AsInteger() types.BeMatcher
```
AsIntish succeeds if actual is a numeric value that represents an integer (from
AsInteger succeeds if actual is a numeric value that represents an integer (from
reflect.Int up to reflect.Uint64).

#### func AsIntishString
#### func AsIntegerString

```go
func AsIntishString() types.BeMatcher
func AsIntegerString() types.BeMatcher
```
AsIntishString succeeds if actual is a string that can be parsed into a valid
AsIntegerString succeeds if actual is a string that can be parsed into a valid
integer value.

#### func AsKind
Expand All @@ -83,12 +86,12 @@ func AsMap() types.BeMatcher
```
AsMap succeeds if actual is of kind reflect.Map.

#### func AsNumeric
#### func AsNumber

```go
func AsNumeric() types.BeMatcher
func AsNumber() types.BeMatcher
```
AsNumeric succeeds if actual is a numeric value, supporting various integer
AsNumber succeeds if actual is a numeric value, supporting various integer
kinds: reflect.Int, ... reflect.Int64, and floating-point kinds:
reflect.Float32, reflect.Float64

Expand Down
Loading

0 comments on commit de3ca8b

Please sign in to comment.