Merge pull request #99 from Orange-OpenSource/feature/arithmetic-predicates-for-number

Make predicates with numbers "arithmetic"
This commit is contained in:
Fabrice Reix 2020-11-29 17:42:05 +01:00 committed by GitHub
commit 269eb43b90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 40 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,10 @@
GET http://localhost:8000/assert-json
HTTP/1.0 200
[Asserts]
jsonpath "$.count" equals 5
jsonpath "$.count" equals 5.0
jsonpath "$.count" greaterThan 1
jsonpath "$.count" greaterThan 1.0
jsonpath "$.success" equals false
jsonpath "$.success" not equals null
jsonpath "$.success" exists
@ -23,6 +27,7 @@ jsonpath "$.duration" not isInteger
jsonpath "$.nullable" equals null
{
"count": 5,
"success": false,
"errors": [{"id":"error1"},{"id":"error2"}],
"warnings": [],

View File

@ -1 +1 @@
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/assert-json"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"equal","value":false}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"not":true,"type":"equal","value":null}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"isBoolean"}},{"query":{"type":"jsonpath","expr":"$.errors"},"predicate":{"type":"count","value":2}},{"query":{"type":"jsonpath","expr":"$.errors"},"predicate":{"type":"isCollection"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"count","value":0}},{"query":{"type":"jsonpath","expr":"$.toto"},"predicate":{"not":true,"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors[0]"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors[0]"},"predicate":{"type":"isCollection"}},{"query":{"type":"jsonpath","expr":"$.errors[0].id"},"predicate":{"type":"equal","value":"error1"}},{"query":{"type":"jsonpath","expr":"$.errors[0]['id']"},"predicate":{"type":"equal","value":"error1"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"equal","value":1.5}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"less-than-or-equal","value":"2.0"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"greater-than","value":"2"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"isFloat"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"not":true,"type":"isInteger"}},{"query":{"type":"jsonpath","expr":"$.nullable"},"predicate":{"type":"equal","value":null}}],"body":{"type":"json","value":{"success":false,"errors":[{"id":"error1"},{"id":"error2"}],"warnings":[],"duration":1.5,"tags":["test"],"nullable":null}}}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json/index"},"response":{"version":"HTTP/1.0","status":200,"captures":[{"name":"index","query":{"type":"body"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.errors[{{index}}].id"},"predicate":{"type":"equal","value":"error2"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"type":"include","value":"test"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"not":true,"type":"include","value":"prod"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"not":true,"type":"include","value":null}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json/list"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$"},"predicate":{"type":"count","value":2}},{"query":{"type":"jsonpath","expr":"$.[0].name"},"predicate":{"type":"equal","value":"Bob"}},{"query":{"type":"jsonpath","expr":"$[0].name"},"predicate":{"type":"equal","value":"Bob"}}]}}]}
{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/assert-json"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.count"},"predicate":{"type":"equal","value":5}},{"query":{"type":"jsonpath","expr":"$.count"},"predicate":{"type":"equal","value":5.0}},{"query":{"type":"jsonpath","expr":"$.count"},"predicate":{"type":"greater-than","value":"1"}},{"query":{"type":"jsonpath","expr":"$.count"},"predicate":{"type":"greater-than","value":"1.0"}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"equal","value":false}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"not":true,"type":"equal","value":null}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.success"},"predicate":{"type":"isBoolean"}},{"query":{"type":"jsonpath","expr":"$.errors"},"predicate":{"type":"count","value":2}},{"query":{"type":"jsonpath","expr":"$.errors"},"predicate":{"type":"isCollection"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"count","value":0}},{"query":{"type":"jsonpath","expr":"$.toto"},"predicate":{"not":true,"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.warnings"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors[0]"},"predicate":{"type":"exist"}},{"query":{"type":"jsonpath","expr":"$.errors[0]"},"predicate":{"type":"isCollection"}},{"query":{"type":"jsonpath","expr":"$.errors[0].id"},"predicate":{"type":"equal","value":"error1"}},{"query":{"type":"jsonpath","expr":"$.errors[0]['id']"},"predicate":{"type":"equal","value":"error1"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"equal","value":1.5}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"less-than-or-equal","value":"2.0"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"greater-than","value":"2"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"type":"isFloat"}},{"query":{"type":"jsonpath","expr":"$.duration"},"predicate":{"not":true,"type":"isInteger"}},{"query":{"type":"jsonpath","expr":"$.nullable"},"predicate":{"type":"equal","value":null}}],"body":{"type":"json","value":{"count":5,"success":false,"errors":[{"id":"error1"},{"id":"error2"}],"warnings":[],"duration":1.5,"tags":["test"],"nullable":null}}}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json/index"},"response":{"version":"HTTP/1.0","status":200,"captures":[{"name":"index","query":{"type":"body"}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$.errors[{{index}}].id"},"predicate":{"type":"equal","value":"error2"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"type":"include","value":"test"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"not":true,"type":"include","value":"prod"}},{"query":{"type":"jsonpath","expr":"$.tags"},"predicate":{"not":true,"type":"include","value":null}}]}},{"request":{"method":"GET","url":"http://localhost:8000/assert-json/list"},"response":{"version":"HTTP/1.0","status":200,"asserts":[{"query":{"type":"jsonpath","expr":"$"},"predicate":{"type":"count","value":2}},{"query":{"type":"jsonpath","expr":"$.[0].name"},"predicate":{"type":"equal","value":"Bob"}},{"query":{"type":"jsonpath","expr":"$[0].name"},"predicate":{"type":"equal","value":"Bob"}}]}}]}

View File

@ -4,6 +4,7 @@ from flask import Response
@app.route("/assert-json")
def assert_json():
return Response('''{
"count": 5,
"success": false,
"errors": [{"id":"error1"},{"id":"error2"}],
"warnings": [],

View File

@ -36,7 +36,7 @@ error: Assert Failure
|
8 | jsonpath "$.count" greaterThan 5
| actual: int <2>
| expected: int <5>
| expected: greater than int <5>
|
error: Assert Failure

View File

@ -582,6 +582,12 @@ fn assert_values_equal(actual: Value, expected: Value) -> Result<AssertResult, E
expected: expected.display(),
type_mismatch: false,
}),
(Value::Integer(int1), Value::Float(int2, decimal)) => Ok(AssertResult {
success: int1 == int2 && decimal == 0,
actual: actual.display(),
expected: expected.display(),
type_mismatch: false,
}),
(Value::Float(i1, d1), Value::Float(i2, d2)) => Ok(AssertResult {
success: i1 == i2 && d1 == d2,
actual: actual.display(),
@ -621,93 +627,110 @@ fn assert_values_equal(actual: Value, expected: Value) -> Result<AssertResult, E
}
}
fn assert_values_greater(actual: Value, expected: Value) -> Result<AssertResult, Error> {
match compare_numbers(actual.clone(), expected.clone()) {
fn assert_values_greater(
actual_value: Value,
expected_value: Value,
) -> Result<AssertResult, Error> {
let actual = actual_value.clone().display();
let expected = format!("greater than {}", expected_value.clone().display());
match compare_numbers(actual_value, expected_value) {
Some(1) => Ok(AssertResult {
success: true,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: false,
}),
Some(0) | Some(-1) => Ok(AssertResult {
success: false,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: false,
}),
_ => Ok(AssertResult {
success: false,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: true,
}),
}
}
fn assert_values_greater_or_equal(actual: Value, expected: Value) -> Result<AssertResult, Error> {
match compare_numbers(actual.clone(), expected.clone()) {
fn assert_values_greater_or_equal(
actual_value: Value,
expected_value: Value,
) -> Result<AssertResult, Error> {
let actual = actual_value.clone().display();
let expected = format!("greater or equal than {}", expected_value.clone().display());
match compare_numbers(actual_value, expected_value) {
Some(1) | Some(0) => Ok(AssertResult {
success: true,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: false,
}),
Some(-1) => Ok(AssertResult {
success: false,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: false,
}),
_ => Ok(AssertResult {
success: false,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: true,
}),
}
}
fn assert_values_less(actual: Value, expected: Value) -> Result<AssertResult, Error> {
match compare_numbers(actual.clone(), expected.clone()) {
fn assert_values_less(actual_value: Value, expected_value: Value) -> Result<AssertResult, Error> {
let actual = actual_value.clone().display();
let expected = format!("less than {}", expected_value.clone().display());
match compare_numbers(actual_value, expected_value) {
Some(-1) => Ok(AssertResult {
success: true,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: false,
}),
Some(0) | Some(1) => Ok(AssertResult {
success: false,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: false,
}),
_ => Ok(AssertResult {
success: false,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: true,
}),
}
}
fn assert_values_less_or_equal(actual: Value, expected: Value) -> Result<AssertResult, Error> {
match compare_numbers(actual.clone(), expected.clone()) {
fn assert_values_less_or_equal(
actual_value: Value,
expected_value: Value,
) -> Result<AssertResult, Error> {
let actual = actual_value.clone().display();
let expected = format!("less or equal than {}", expected_value.clone().display());
match compare_numbers(actual_value, expected_value) {
Some(-1) | Some(0) => Ok(AssertResult {
success: true,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: false,
}),
Some(1) => Ok(AssertResult {
success: false,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: false,
}),
_ => Ok(AssertResult {
success: false,
actual: actual.display(),
expected: expected.display(),
actual,
expected,
type_mismatch: true,
}),
}
@ -724,6 +747,7 @@ fn compare_numbers(actual: Value, expected: Value) -> Option<i32> {
}
(Value::Float(i1, d1), Value::Float(i2, d2)) => Some(compare_float((i1, d1), (i2, d2))),
(Value::Float(i1, d1), Value::Integer(i2)) => Some(compare_float((i1, d1), (i2, 0))),
(Value::Integer(i1), Value::Float(i2, d2)) => Some(compare_float((i1, 0), (i2, d2))),
_ => None,
}
}
@ -1191,7 +1215,10 @@ mod tests {
);
// 1 integer and 1 float
assert!(compare_numbers(Value::Integer(2), Value::Float(2, 0)).is_none());
assert_eq!(
compare_numbers(Value::Integer(2), Value::Float(2, 0)).unwrap(),
0
);
// with a non number
assert!(compare_numbers(Value::Integer(-1), Value::String("hello".to_string())).is_none());
@ -1205,7 +1232,7 @@ mod tests {
success: true,
type_mismatch: false,
actual: "int <2>".to_string(),
expected: "int <1>".to_string(),
expected: "greater than int <1>".to_string(),
}
);
assert_eq!(
@ -1214,7 +1241,7 @@ mod tests {
success: false,
type_mismatch: false,
actual: "int <1>".to_string(),
expected: "int <1>".to_string(),
expected: "greater than int <1>".to_string(),
}
);
assert_eq!(
@ -1223,7 +1250,7 @@ mod tests {
success: true,
type_mismatch: false,
actual: "float <1.1>".to_string(),
expected: "int <1>".to_string(),
expected: "greater than int <1>".to_string(),
}
);
assert_eq!(
@ -1232,7 +1259,7 @@ mod tests {
success: false,
type_mismatch: false,
actual: "float <1.1>".to_string(),
expected: "int <2>".to_string(),
expected: "greater than int <2>".to_string(),
}
);
}