Skip to content

Commit

Permalink
fix: assertions on date (#352)
Browse files Browse the repository at this point in the history
* fix: assertions on date

close #348

Signed-off-by: Yvonnick Esnault <[email protected]>
  • Loading branch information
yesnault authored Jan 4, 2021
1 parent d4a2b47 commit 984a392
Show file tree
Hide file tree
Showing 46 changed files with 564 additions and 69 deletions.
82 changes: 41 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,47 +366,47 @@ Available formats: jUnit (xml), json, yaml, tap reports

## Keywords

* ShouldEqual
* ShouldNotEqual
* ShouldAlmostEqual
* ShouldNotAlmostEqual
* ShouldBeNil
* ShouldNotBeNil
* ShouldBeTrue
* ShouldBeFalse
* ShouldBeZeroValue
* ShouldBeGreaterThan
* ShouldBeGreaterThanOrEqualTo
* ShouldBeLessThan
* ShouldBeLessThanOrEqualTo
* ShouldBeBetween
* ShouldNotBeBetween
* ShouldBeBetweenOrEqual
* ShouldNotBeBetweenOrEqual
* ShouldContain
* ShouldNotContain
* ShouldContainKey
* ShouldNotContainKey
* ShouldBeIn
* ShouldNotBeIn
* ShouldBeEmpty
* ShouldNotBeEmpty
* ShouldHaveLength
* ShouldStartWith
* ShouldNotStartWith
* ShouldEndWith
* ShouldNotEndWith
* ShouldBeBlank
* ShouldNotBeBlank
* ShouldContainSubstring
* ShouldNotContainSubstring
* ShouldEqualTrimSpace
* ShouldHappenBefore
* ShouldHappenOnOrBefore
* ShouldHappenAfter
* ShouldHappenOnOrAfter
* ShouldHappenBetween
* ShouldNotExist
* ShouldEqual - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldEqual.yml)
* ShouldNotEqual - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotEqual.yml)
* ShouldAlmostEqual - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldAlmostEqual.yml)
* ShouldNotAlmostEqual - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotAlmostEqual.yml)
* ShouldBeNil - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeNil.yml)
* ShouldNotBeNil - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotBeNil.yml)
* ShouldBeTrue - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeTrue.yml)
* ShouldBeFalse - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeFalse.yml)
* ShouldBeZeroValue - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeZeroValue.yml)
* ShouldBeGreaterThan - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeGreaterThan.yml)
* ShouldBeGreaterThanOrEqualTo - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeGreaterThanOrEqualTo.yml)
* ShouldBeLessThan - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeLessThan.yml)
* ShouldBeLessThanOrEqualTo - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeLessThanOrEqualTo.yml)
* ShouldBeBetween - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeBetween.yml)
* ShouldNotBeBetween - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotBeBetween.yml)
* ShouldBeBetweenOrEqual - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeBetweenOrEqual.yml)
* ShouldNotBeBetweenOrEqual - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotBeBetweenOrEqual.yml)
* ShouldContain - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldContain.yml)
* ShouldNotContain - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotContain.yml)
* ShouldContainKey - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldContainKey.yml)
* ShouldNotContainKey - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotContainKey.yml)
* ShouldBeIn - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeIn.yml)
* ShouldNotBeIn - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotBeIn.yml)
* ShouldBeEmpty - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeEmpty.yml)
* ShouldNotBeEmpty - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotBeEmpty.yml)
* ShouldHaveLength - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldHaveLength.yml)
* ShouldStartWith - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldStartWith.yml)
* ShouldNotStartWith - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotStartWith.yml)
* ShouldEndWith - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldEndWith.yml)
* ShouldNotEndWith - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotEndWith.yml)
* ShouldBeBlank - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldBeBlank.yml)
* ShouldNotBeBlank - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotBeBlank.yml)
* ShouldContainSubstring - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldContainSubstring.yml)
* ShouldNotContainSubstring - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotContainSubstring.yml)
* ShouldEqualTrimSpace - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldEqualTrimSpace.yml)
* ShouldNotExist - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldNotExist.yml)
* ShouldHappenBefore - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldHappenBefore.yml)
* ShouldHappenOnOrBefore - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldHappenOnOrBefore.yml)
* ShouldHappenAfter - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldHappenAfter.yml)
* ShouldHappenOnOrAfter - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldHappenOnOrAfter.yml)
* ShouldHappenBetween - [example](https://github.com/ovh/venom/tree/master/tests/assertions/ShouldHappenBetween.yml)

Most assertion keywords documentation can be found on https://pkg.go.dev/github.com/ovh/venom/assertions.

Expand Down
189 changes: 165 additions & 24 deletions assertions/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ func deepEqual(x, y interface{}) bool {
}

// ShouldEqual receives exactly two parameters and does an equality check.
//
// Example of testsuite file:
//
// name: Assertions testsuite
// testcases:
// - name: test assertion
// steps:
// - script: echo 'foo'
// assertions:
// - result.code ShouldEqual 0
//
func ShouldEqual(actual interface{}, expected ...interface{}) error {
if err := need(1, expected); err != nil {
return err
Expand Down Expand Up @@ -528,6 +539,17 @@ func ShouldNotContainKey(actual interface{}, expected ...interface{}) error {
// that is passed in either as the second parameter, or of the collection that is comprised
// of all the remaining parameters. This assertion ensures that the proposed member is in
// the collection (using ShouldEqual).
//
// Example of testsuite file:
//
// name: Assertions testsuite
// testcases:
// - name: ShouldBeIn
// steps:
// - script: echo 1
// assertions:
// - result.systemoutjson ShouldBeIn 1 2
//
func ShouldBeIn(actual interface{}, expected ...interface{}) error {
if err := atLeast(1, expected); err != nil {
return err
Expand All @@ -549,6 +571,17 @@ func ShouldBeIn(actual interface{}, expected ...interface{}) error {
// that is passed in either as the second parameter, or of the collection that is comprised
// of all the remaining parameters. This assertion ensures that the proposed member is NOT in
// the collection (using ShouldEqual).
//
// Example of testsuite file:
//
// name: Assertions testsuite
// testcases:
// - name: ShouldNotBeIn
// steps:
// - script: echo 3
// assertions:
// - result.systemoutjson ShouldNotBeIn 1 2
//
func ShouldNotBeIn(actual interface{}, expected ...interface{}) error {
if err := atLeast(1, expected); err != nil {
return err
Expand Down Expand Up @@ -812,15 +845,33 @@ func ShouldEqualTrimSpace(actual interface{}, expected ...interface{}) error {
}

// ShouldHappenBefore receives exactly 2 time.Time arguments and asserts that the first happens before the second.
// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00
//
// Example of testsuite file:
//
// name: test ShouldHappenBefore
// vars:
// time: 2006-01-02T15:04:05+07:00
// time_with_5s_after: 2006-01-02T15:04:10+07:00
// testcases:
// - name: test assertion
// steps:
// - type: exec
// script: "echo {{.time}}"
// assertions:
// - result.systemout ShouldHappenBefore "{{.time_with_5s_after}}"
func ShouldHappenBefore(actual interface{}, expected ...interface{}) error {
if err := need(1, expected); err != nil {
return err
}
actualTime, firstOk := actual.(time.Time)
expectedTime, secondOk := expected[0].(time.Time)

if !firstOk || !secondOk {
return errors.Errorf("invalid date provided")
actualTime, err := getTimeFromString(actual)
if err != nil {
return err
}
expectedTime, err := getTimeFromString(expected[0])
if err != nil {
return err
}

if actualTime.Before(expectedTime) {
Expand All @@ -831,15 +882,32 @@ func ShouldHappenBefore(actual interface{}, expected ...interface{}) error {
}

// ShouldHappenOnOrBefore receives exactly 2 time.Time arguments and asserts that the first happens on or before the second.
// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00
//
// Example of testsuite file:
//
// name: test ShouldHappenOnOrBefore
// vars:
// time: 2006-01-02T15:04:05+07:00
// time_with_5s_after: 2006-01-02T15:04:10+07:00
// testcases:
// - name: test assertion
// steps:
// - type: exec
// script: "echo {{.time}}"
// assertions:
// - result.systemout ShouldHappenOnOrBefore "{{.time_with_5s_after}}"
func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) error {
if err := need(1, expected); err != nil {
return err
}
actualTime, firstOk := actual.(time.Time)
expectedTime, secondOk := expected[0].(time.Time)

if !firstOk || !secondOk {
return errors.Errorf("invalid date provided")
actualTime, err := getTimeFromString(actual)
if err != nil {
return err
}
expectedTime, err := getTimeFromString(expected[0])
if err != nil {
return err
}

if actualTime.Before(expectedTime) || actualTime.Equal(expectedTime) {
Expand All @@ -850,15 +918,32 @@ func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) error {
}

// ShouldHappenAfter receives exactly 2 time.Time arguments and asserts that the first happens after the second.
// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00
//
// Example of testsuite file:
//
// name: test ShouldHappenAfter
// vars:
// time_with_5s_before: 2006-01-02T15:04:00+07:00
// time: 2006-01-02T15:04:05+07:00
// testcases:
// - name: test assertion
// steps:
// - type: exec
// script: "echo {{.time}}"
// assertions:
// - result.systemout ShouldHappenAfter "{{.time_with_5s_before}}"
func ShouldHappenAfter(actual interface{}, expected ...interface{}) error {
if err := need(1, expected); err != nil {
return err
}
actualTime, firstOk := actual.(time.Time)
expectedTime, secondOk := expected[0].(time.Time)

if !firstOk || !secondOk {
return errors.Errorf("invalid date provided")
actualTime, err := getTimeFromString(actual)
if err != nil {
return err
}
expectedTime, err := getTimeFromString(expected[0])
if err != nil {
return err
}

if actualTime.After(expectedTime) {
Expand All @@ -869,38 +954,94 @@ func ShouldHappenAfter(actual interface{}, expected ...interface{}) error {
}

// ShouldHappenOnOrAfter receives exactly 2 time.Time arguments and asserts that the first happens on or after the second.
// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00
//
// Example of testsuite file:
//
// name: test ShouldHappenOnOrAfter
// vars:
// time_with_5s_before: 2006-01-02T15:04:00+07:00
// time: 2006-01-02T15:04:05+07:00
// testcases:
// - name: test assertion
// steps:
// - type: exec
// script: "echo {{.time}}"
// assertions:
// - result.systemout ShouldHappenOnOrAfter "{{.time_with_5s_before}}"
func ShouldHappenOnOrAfter(actual interface{}, expected ...interface{}) error {
if err := need(1, expected); err != nil {
return err
}
actualTime, firstOk := actual.(time.Time)
expectedTime, secondOk := expected[0].(time.Time)

if !firstOk || !secondOk {
return errors.Errorf("invalid date provided")
actualTime, err := getTimeFromString(actual)
if err != nil {
return err
}
expectedTime, err := getTimeFromString(expected[0])
if err != nil {
return err
}

if actualTime.Before(expectedTime) || actualTime.Equal(expectedTime) {
if actualTime.After(expectedTime) || actualTime.Equal(expectedTime) {
return nil
}
return fmt.Errorf("expected '%v' to be before or on '%v'", actualTime, expectedTime)
}

// ShouldHappenBetween receives exactly 3 time.Time arguments and asserts that the first happens between (not on) the second and third.
// The arguments have to respect the date format RFC3339, as 2006-01-02T15:04:00+07:00
//
// Example of testsuite file:
//
// name: test ShouldHappenBetween
// vars:
// time_with_5s_before: 2006-01-02T15:04:00+07:00
// time: 2006-01-02T15:04:05+07:00
// time_with_5s_after: 2006-01-02T15:04:10+07:00
// testcases:
// - name: test assertion
// steps:
// - type: exec
// script: "echo {{.time}}"
// assertions:
// - result.systemout ShouldHappenBetween "{{.time_with_5s_before}}" "{{.time_with_5s_after}}"
func ShouldHappenBetween(actual interface{}, expected ...interface{}) error {
if err := need(2, expected); err != nil {
return err
}
actualTime, firstOk := actual.(time.Time)
min, minOk := expected[0].(time.Time)
max, maxOk := expected[1].(time.Time)

if !firstOk || !minOk || !maxOk {
return errors.Errorf("invalid date provided")
actualTime, err := getTimeFromString(actual)
if err != nil {
return err
}
min, err := getTimeFromString(expected[0])
if err != nil {
return err
}
max, err := getTimeFromString(expected[1])
if err != nil {
return err
}

if actualTime.After(min) && actualTime.Before(max) {
return nil
}
return fmt.Errorf("expected '%v' to be between '%v' and '%v' ", actualTime, min, max)
}

func getTimeFromString(in interface{}) (time.Time, error) {
if t, isTime := in.(time.Time); isTime {
return t, nil
}
s, err := cast.ToStringE(in)
if err != nil {
return time.Time{}, errors.Errorf("invalid date provided: %q", in)
}

t, err := time.Parse(time.RFC3339, s)
if err != nil {
return time.Time{}, errors.Errorf("invalid date RFC3339 provided with %q", in)
}
return t, nil
}
Loading

0 comments on commit 984a392

Please sign in to comment.