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

Feat/approx equal #40

Merged
merged 2 commits into from
Nov 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
1 change: 1 addition & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ Then expected records
| topic_out | key1 | aValue |
And assert aValue $.foo == "fooString"
And assert aValue $.fooInt == 42
And assert aValue $.fooDouble == 12.0038 +- 1E-4
And assert aValue $.foos has size 3
And assert aValue $.foos == ["item1","item2","item3"]
And assert aValue $ match object {"foos":["item1","item2","item3"],"bar":{"baz":["item1","item2","item3"]}}
Expand Down
20 changes: 20 additions & 0 deletions src/main/scala/com/lectra/kapoeira/glue/Asserts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,21 @@ object Asserts extends Matchers with LazyLogging {
}
)

def approxEqual(assertionContext: AssertionContext, alias: String, jsonExpression: String, expected: String, approxRange: String):Assertion =
assertKafkaOutput(
assertionContext,
alias,
jsonExpression,
{ actual => (
for{
x <- actual.double()
expected <- JsonExpr(expected).value.double()
approx <- JsonExpr(approxRange).value.double()
} yield{ x should equal ( expected +- approx ) }
).fold(fail(s"${actual} equal ${expected} +- ${approxRange}"))(identity)
}
)

def matchExactObject(
assertionContext: AssertionContext,
alias: String,
Expand Down Expand Up @@ -150,6 +165,11 @@ object Asserts extends Matchers with LazyLogging {

implicit class JsonNodeOps(val jsonNode: JsonNode) {

def double():Option[Double] ={
val none = (_:Any) => Option.empty[Double]
jsonNode.fold(obj = none, arr = none, number = Some(_), strng = none, bln = none, bin = none, nullOrUndef = none)
}

def fold[T](
obj: JsonNode => T,
arr: JsonNode => T,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class FeaturesStepDefinitions
}

// ASSERT
And("^assert\\s+(\\S+)\\s+(\\S+)\\s*==\\s*(.*)\\s*$") {
And("^assert\\s+(\\S+)\\s+(\\S+)\\s*==\\s*([^+-]*)\\s*$") {
(alias: String, jsonExpression: String, expected: String) =>
logger.debug(
s"Assert Step : (alias,jsonExpression,expected) ($alias,$jsonExpression,$expected)"
Expand Down Expand Up @@ -226,6 +226,21 @@ class FeaturesStepDefinitions
)
}

And("""^assert\s+(\S+)\s+(\$\S*)\s*==\s+([+-.eE0-9]+)\s+\+\-\s+([+-.eE0-9]+)\s*$""") {
(alias: String, jsonExpression: String, expectedJsonNumber: String,approximationJsonNumber:String) =>
val interpolatedExpectedJson =
backgroundContext.substituteVariablesIn(expectedJsonNumber)
val interpolatedApproximationJson =
backgroundContext.substituteVariablesIn(approximationJsonNumber)
Asserts.approxEqual(
assertionContext,
alias,
jsonExpression,
interpolatedExpectedJson,
interpolatedApproximationJson
)
}

And("^assert\\s+var\\s+(\\S+)\\s+(\\$\\S*)\\s+match\\s+object\\s+(.*)$") {
(variableName: String, jsonExpression: String, expectedJson: String) =>
val interpolatedExpectedJson =
Expand Down
9 changes: 9 additions & 0 deletions src/test/resources/features/assertions.feature
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,19 @@ Feature: assertions
| topic_out | key1_${uuid} | aliasHeaders2.1 | value2.1 |
| topic_out | key2_${uuid} | aliasHeaders2.2 | value2.2 |
| topic_out | key3_${uuid} | aliasHeaders2.3 | value2.3 |
| topic_out | key4_${uuid} | aliasHeaders2.4 | value2.4 |
And assert value2.1 $.qux == 42
And assert value2.2 $ has size 2
And assert value2.2 $ == [3,4]
And assert value2.3 $ == "value2.3"
And assert value2.4 $.foo == 12.0038209653823934567890123456789
And assert value2.4 $.foo == 12.0 +- 0.1
And assert value2.4 $.foo == 12.1 +- 0.1
And assert value2.4 $.foo == 12.0038 +- 1E-4
And assert value2.4 $.foo == 12.0037 +- 1E-3
And assert value2.4 $.foo == 12.0039 +- 1E-3
And assert value2.4 $.foo == 12.003 +- 1E-3
And assert value2.4 $.foo == 12.004 +- 1E-3
And assert aliasHeaders2.1 $ == {"foo":"bar","baz":"42"}
And assert aliasHeaders2.1 $.foo == "bar"

Expand Down
1 change: 1 addition & 0 deletions src/test/resources/features/records/keyheadersvalue.dat
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
key1_${uuid}#{"qux":42}#{"foo":"bar","baz":42}
key2_${uuid}#[3,4]#{"foo":"bar","baz":[1,2]}
key3_${uuid}#value2.3#{"foo":"bar"}
key4_${uuid}#{"foo":12.0038209653823934567890123456789}#{"foo":"bar"}
25 changes: 25 additions & 0 deletions src/test/scala/com/lectra/kapoeira/glue/AssertsTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,31 @@ class AssertsTest extends AnyFlatSpec with Matchers with MockFactory {

behavior of "Asserts"

it should "assert approximatively equals on numbers" in {
val backgroundContext = mock[BackgroundContext]
val assertionContext = new AssertionContext(WhenStepsLive(backgroundContext, recordConsume, KapoeiraProducer.run _))
val consumerRecord =
new ConsumerRecord("topic", 0, 0, "key", """{"foo": 12.003820965382393}""".getBytes.asInstanceOf[Any])
val valueAlias = "valueAlias"
val keyValueRecord = KeyValueWithAliasesRecord("topic", "key", valueAlias)
(backgroundContext
.consumeTopic(_: String, _: Map[String, Int])(_: RecordConsumer))
.expects(*, *, *)
.returning(Map("key" -> Seq(consumerRecord)))
val expectedConsumedRecords = List(keyValueRecord)
assertionContext.launchConsumption(expectedConsumedRecords)

Asserts.approxEqual(assertionContext, valueAlias, "$.foo", "12.0038","0.0001" )
Asserts.approxEqual(assertionContext, valueAlias, "$.foo", "12.0038","1E-4" )
Asserts.approxEqual(assertionContext, valueAlias, "$.foo", "12.0037","1E-3" )
Asserts.approxEqual(assertionContext, valueAlias, "$.foo", "12.0039","1E-3" )
Asserts.approxEqual(assertionContext, valueAlias, "$.foo", "12.003","1E-3" )
Asserts.approxEqual(assertionContext, valueAlias, "$.foo", "12.004","1E-3" )
Asserts.approxEqual(assertionContext, valueAlias, "$.foo", "12.0","0.1" )
Asserts.approxEqual(assertionContext, valueAlias, "$.foo", "12.1","0.1" )

}

it should "assert equality on literals" in {
val backgroundContext = mock[BackgroundContext]
val assertionContext = new AssertionContext(WhenStepsLive(backgroundContext, recordConsume, KapoeiraProducer.run _))
Expand Down
Loading