-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
046f073
commit 5c9b9a2
Showing
7 changed files
with
263 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
) | ||
|
||
// checkAssertions takes the rules provided in the test spec and iterates over them, | ||
// returning an error if at any point a comparison is false. | ||
// value comparisons: | ||
// "equals" | ||
// "lt" (less than) | ||
// "gt" (greater than) | ||
// "le" (less than or equal to) | ||
// "ge" (greater than or equal to) | ||
// "exists" (key exists in the JSON response body) | ||
func checkAssertions(value interface{}, rules map[string]interface{}) error { | ||
for k, comparisonValue := range rules { | ||
switch k { | ||
case "equals": | ||
// compare values using string formatting. This is equivalent to "strict=false" | ||
// e.g.: | ||
// 123 == 123 > true | ||
// 123 == "123" > true | ||
|
||
if !equals(value, comparisonValue) { | ||
return fmt.Errorf("expected: %v received: %v", comparisonValue, value) | ||
} | ||
case "lt": | ||
// convert to floats, returning an error if that's not possible (bad input) | ||
val1, val2, err := asFloat(value, comparisonValue) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// perform comparison | ||
if val1 >= val2 { | ||
return fmt.Errorf("expected %v less than %v", value, comparisonValue) | ||
} | ||
case "gt": | ||
val1, val2, err := asFloat(value, comparisonValue) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if val1 <= val2 { | ||
return fmt.Errorf("expected %v greater than %v", value, comparisonValue) | ||
} | ||
case "le": | ||
val1, val2, err := asFloat(value, comparisonValue) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if val1 > val2 { | ||
return fmt.Errorf("expected %v less than or equal to %v", value, comparisonValue) | ||
} | ||
case "ge": | ||
val1, val2, err := asFloat(value, comparisonValue) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if val1 < val2 { | ||
return fmt.Errorf("expected %v greater than or equal to %v", value, comparisonValue) | ||
} | ||
case "exists": | ||
// check whether this key was received as part of the body, even if null. | ||
// not elegant, but due to the jq parsing in checkJSONResponse(), this api test case will | ||
// fail earlier in checkJSONResponse if the key doesn't exist. Therefore, if the test case | ||
// gets this far, we already know the key exists. This is here to provide a means to check | ||
// the "exists" case without having to provide a comparison value. In the future, I need | ||
// to refactor to allow `exists: false`. | ||
default: | ||
// invalid rule (not defined above) | ||
return fmt.Errorf("invalid rule: %s", k) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// equals returns true if two values are equal, when cast to strings. | ||
// this means that 123 == "123" (int vs string). | ||
func equals(val interface{}, comparison interface{}) bool { | ||
return fmt.Sprintf("%v", val) == fmt.Sprintf("%v", comparison) | ||
} | ||
|
||
// asFloat converts two values (received value and comparison value) to floats. | ||
// returns an error if not possible. | ||
func asFloat(val1 interface{}, val2 interface{}) (float64, float64, error) { | ||
float1, err := strconv.ParseFloat(fmt.Sprintf("%v", val1), 64) | ||
if err != nil { | ||
return 0, 0, fmt.Errorf("unable to parse %v as a float", val1) | ||
} | ||
float2, err := strconv.ParseFloat(fmt.Sprintf("%v", val2), 64) | ||
if err != nil { | ||
return 0, 0, fmt.Errorf("unable to parse %v as a float", val2) | ||
} | ||
return float1, float2, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package main | ||
|
||
import "testing" | ||
|
||
func TestEqualsAssertion(t *testing.T) { | ||
type testCase struct { | ||
Value interface{} | ||
Comparison interface{} | ||
Expected bool | ||
} | ||
|
||
cases := []testCase{ | ||
testCase{Value: "123", Comparison: 123, Expected: true}, | ||
testCase{Value: "123", Comparison: 124, Expected: false}, | ||
testCase{Value: 123, Comparison: 123, Expected: true}, | ||
testCase{Value: "the quick brown fox", Comparison: "the quick brown fox", Expected: true}, | ||
testCase{Value: "quick", Comparison: 421421, Expected: false}, | ||
testCase{Value: 123.4, Comparison: 123.4, Expected: true}, | ||
testCase{Value: 123.4, Comparison: 123.5, Expected: false}, | ||
} | ||
|
||
for _, c := range cases { | ||
err := checkAssertions(c.Value, map[string]interface{}{"equals": c.Comparison}) | ||
if (err == nil) != c.Expected { | ||
t.Errorf("failed: expected %v == %v to have been %v; %v", c.Value, c.Comparison, c.Expected, err) | ||
} | ||
} | ||
} | ||
|
||
// TestLTAssertion tests the "less than" comparison rule | ||
func TestLTAssertion(t *testing.T) { | ||
type testCase struct { | ||
Value interface{} | ||
Comparison interface{} | ||
Expected bool | ||
} | ||
|
||
cases := []testCase{ | ||
testCase{Value: "123", Comparison: 123, Expected: false}, | ||
testCase{Value: "123", Comparison: 124, Expected: true}, | ||
testCase{Value: 123, Comparison: 124, Expected: true}, | ||
testCase{Value: 123, Comparison: 122, Expected: false}, | ||
} | ||
|
||
for _, c := range cases { | ||
err := checkAssertions(c.Value, map[string]interface{}{"lt": c.Comparison}) | ||
if (err == nil) != c.Expected { | ||
t.Errorf("failed: expected %v < %v to have been %v; %v", c.Value, c.Comparison, c.Expected, err) | ||
} | ||
} | ||
} | ||
|
||
// TestGTAssertion tests the "greater than" comparison rule | ||
func TestGTAssertion(t *testing.T) { | ||
type testCase struct { | ||
Value interface{} | ||
Comparison interface{} | ||
Expected bool | ||
} | ||
|
||
cases := []testCase{ | ||
testCase{Value: "123", Comparison: 123, Expected: false}, | ||
testCase{Value: "123", Comparison: 124, Expected: false}, | ||
testCase{Value: 123, Comparison: 124, Expected: false}, | ||
testCase{Value: 123, Comparison: 122, Expected: true}, | ||
} | ||
|
||
for _, c := range cases { | ||
err := checkAssertions(c.Value, map[string]interface{}{"gt": c.Comparison}) | ||
if (err == nil) != c.Expected { | ||
t.Errorf("failed: expected %v > %v to have been %v; %v", c.Value, c.Comparison, c.Expected, err) | ||
} | ||
} | ||
} | ||
|
||
// TestLEAssertion tests the "less than or equal to" comparison rule | ||
func TestLEAssertion(t *testing.T) { | ||
type testCase struct { | ||
Value interface{} | ||
Comparison interface{} | ||
Expected bool | ||
} | ||
|
||
cases := []testCase{ | ||
testCase{Value: "123", Comparison: 123, Expected: true}, | ||
testCase{Value: "123", Comparison: 124, Expected: true}, | ||
testCase{Value: 123, Comparison: 124, Expected: true}, | ||
testCase{Value: 123, Comparison: 122, Expected: false}, | ||
testCase{Value: 123, Comparison: 123, Expected: true}, | ||
} | ||
|
||
for _, c := range cases { | ||
err := checkAssertions(c.Value, map[string]interface{}{"le": c.Comparison}) | ||
if (err == nil) != c.Expected { | ||
t.Errorf("failed: expected %v <= %v to have been %v; %v", c.Value, c.Comparison, c.Expected, err) | ||
} | ||
} | ||
} | ||
|
||
// TestGEAssertion tests the "greater than or equal to" comparison rule | ||
func TestGEAssertion(t *testing.T) { | ||
type testCase struct { | ||
Value interface{} | ||
Comparison interface{} | ||
Expected bool | ||
} | ||
|
||
cases := []testCase{ | ||
testCase{Value: "123", Comparison: 123, Expected: true}, | ||
testCase{Value: "123", Comparison: 124, Expected: false}, | ||
testCase{Value: 123, Comparison: 124, Expected: false}, | ||
testCase{Value: 123, Comparison: 122, Expected: true}, | ||
testCase{Value: 123, Comparison: 123, Expected: true}, | ||
} | ||
|
||
for _, c := range cases { | ||
err := checkAssertions(c.Value, map[string]interface{}{"ge": c.Comparison}) | ||
if (err == nil) != c.Expected { | ||
t.Errorf("failed: expected %v >= %v to have been %v; %v", c.Value, c.Comparison, c.Expected, err) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters