Releases: agourlay/cornichon
0.12.0 : New EffectStep type
This release contains several breaking changes impacting users building their own custom steps.
If you are only using the built-in DSL, those changes should be transparent.
New EffectStep type
Prior to 0.12.x an EffectStep
wrapped a function Session => Future[Session]
.
This has historically caused pain in the library code as it forces everyone to rely on Exceptions
to design failure in steps.
In Cornichon 0.12, the EffectType
is now modified to Session => Future[Either[CornichonError, Session]]
where CornichonError
is a simple case class holding a String
message.
In order to make the migration easy, EffectStep
proposes factory methods to work without the Either
.
EffectStep.fromSync(title = "identity", action = s => s)
EffectStep.fromSyncE(title = "identity", action = s => Right(s))
EffectStep.fromAsync(title = "identity", action = s => Future(s))
EffectStep(title = "identity", action = s => Future(Right(s)))
This change has enabled a much needed refactoring of the library code and an improvement of the failure semantics.
But to be complete, this transition also had to impact the helper methods on Session
and CornichonJson
to return Eithers
as well.
It is now possible to write EffectStep
and AssertionStep
in an imperative fashion using for-comprehension.
Here is a migration example
def a_plus_b_equals_c =
AssertStep(
"sum of 'a' + 'b' = 'c'",
s ⇒ GenericEqualityAssertion(s.get("a").toInt + s.get("b").toInt, s.get("c").toInt))
can be rewritten into
def a_plus_b_equals_c =
AssertStep(
"sum of 'a' + 'b' = 'c'",
s ⇒ Assertion.either {
for {
a <- s.get("a").map(_.toInt)
b <- s.get("b").map(_.toInt)
c <- s.get("c").map(_.toInt)
} yield GenericEqualityAssertion(a + b, c))
}
)
To smoothen the migration, unsafe versions of all helpers are still available, you will recognise them with the suffix "Unsafe".
E.g
s.getJson
vss.getJsonUnsafe
CornichonJson.parseString
vsCornichonJson.parseStringUnsafe
The EffectStep
also received a new experimental API to manually chain steps together or run various computations afterwards. Refer to the source code of EffectStep
for more information for the time being.
0.11.2 : Maintenance
Maintenance release containing the following changes.
- graphQL queries can now be used to create request effect in
HttpService
(contribution from @peter-gerhard #122) - upgrade to Akka-http 0.10.5
- upgrade to Sangria 1.1.0
- small breaking change due to the alias
gql
now being reserved by Sangria. Creating graphQL JSON is now done withgqljson
1f094c8
0.11.1 : Modules
This release contains a breaking change.
Modules
The project has been migrated to a SBT multi-modules setup to implement the following changes
Documentation web site
The documentation now lives on the official cornichon home page.
The site is built using sbt-microsite which offers a smooth integration with gh-pages and the possibility to have type checked examples with tut.
This should help the project keeping an updated correct documentation.
Giving a home to Cornichon was also requiring the creation of a logo which was beautifully designed by @OlegIlyenko!
cornichon-core
cornichon-core contains all the logic and DSLs without any dependency to scalatest.
It's goal is to enable the creation of new integrations with other testing frameworks and maybe even an sbt plugin with a dedicated test runner.
This was a necessary change to enable users to explore new directions that might shape the future of the library.
Therefore the current cornichon.jar depends on cornichon-core and contains only the scalatest integration.
It might be renamed to cornichon-scalatest in the future.
cornichon-benchmarks
An additional sbt-jmh modules was created in order to start tracking performance problems and opportunities in a more scientific way.
Breaking change
In order to improve the compilation times and IDE experience, a significant number of implicit type class instances from Cats have been removed from the DSL scope as they were rarely useful for the end users.
Keeping only the most used instances will help the project keep a "batteries included" philosophy while not taxing every single users for the extra things.
In practice, I don't expect anyone to be impacted by this change as the built-in HTTP DSL does not offer a use case for those instances.
0.11 : JSON matchers
This release contains several breaking changes.
JSON matchers
If the exact value of a field is unknown, you can use JSON matchers to make sure it has a certain property or shape.
JSON matchers work more or less like placeholders in practice.
And assert body.ignoring("city", "realName", "publisher.location").is(
"""
{
"name": "<favorite-superhero>",
"hasSuperpowers": *any-boolean*,
"publisher": {
"name": *any-string*,
"foundationYear": *any-positive-integer*
}
}
"""
)
You just need to replace the value of the field by one of the built-in JSON matchers without quotes.
Here are the available matchers:
*is-present*
: checks if the field is defined*any-string*
: checks if the field is a String*any-array*
: checks if the field is an Array*any-object*
: checks if the field is an Object*any-integer*
: checks if the field is an Integer*any-positive-integer*
: checks if the field is a positive Integer*any-negative-integer*
: checks if the field is a negative Integer*any-uuid*
: checks if the field is a valid UUID*any-boolean*
: checks if the field is a boolean*any-alphanum-string*
: checks if the field is an alpha-numeric String*any-date*
: checks if the field is a 'yyyy-MM-dd' date*any-date-time*
: checks if the field is a 'yyyy-MM-dd'T'HH:mm:ss.SSS'Z'' datetime*any-time*
: checks if the field is a 'HH:mm:ss.SSS' time"
This feature is still fresh and under experimentation therefore it comes with a couple of limitations:
- it is not yet possible to register custom JSON matchers
- matchers are not supported for JSON arrays assertions
Breaking changes
<timestamp>
has been replaced by<current-timestamp>
- circe updated to 0.7.0
Other changes
- improve error reporting in case of bad header session encoding
- add
event-stream
accept header to Server-Sent-Event connection - improve documentation of test packaging
- performance improvements
0.10.5 : Maintenance
Maintenance release containing the following changes.
- remove unecessary logback dependency - fixes #107
- always resolve placeholders in the headers contained in the
WithHeaders
key - remove sloppy undocumented Scalacheck mapper integration
- improve performance of tasks scheduling
- add Teamcity scalatest reporter as an example for users running features without
SBT
0.10.4 : Maintenance
Maintenance release containing the following changes.
- fix issue triggered when using the
Attach
block as a starting point of aScenario
. - improve error reporting of the status assertion error done via the
HttpService
. - introduce a
Feature
wide placeholder cache to avoid reparsing known input when retrying steps. - improve performance of
CornichonJson.parseJson
0.10.3 : Better JSON assertion reporting
Maintenance release containing improvements regarding the JSON assertions reporting:
JSON patch
JSON diffs are gone and replaced by the standard JSON patch.
The internal custom JSON diff implementation could produce some strange results and was not really idiomatic so it makes sense to adopt a standard instead.
As a bonus a JSON patch can give much more details regarding what has really changed in terms of Add, Remove, Replace, Copy and Move operations.
Better error reporting for empty JSON path
Basically it replaces the not really helpful
Then assert response body's field 'a.b.c[0].d' is 2 *** FAILED ***
expected result was:
'2'
but actual result is:
'null'
JSON diff. between actual result and expected result is :
deleted = 2
by a more interesting
Then assert response body's field 'a.b.c[0].d' is 2 *** FAILED ***
JSON path 'a.b.c[0].d' is not defined in object
{
"a" : 1,
"b" : 2,
"c" : [
{
"notD" : 3
}
]
}
Misc
- introduce
save_body(???)
as a shortcut forsave_body_path("$", ???)
- add
RepeatFrom
which is identical toRepeatWith
but for a collection instead of varargs argument. - improve HTTP status DSL with 4 new assertions to test the status code family (contributed by @kidi)
- status.isSuccess
- status.isRedirect
- status.isClientError
- status.isServerError
- whitelisting on array is now supported for some cases (*)
(*)As the underlying implementation relies on the position of the elements to track the changes within the array, the order of the array must be stable.
For this reason whitelisting
was not added on the asArray
DSL to avoid the potential confusion of asserting an array without order with whitelisting relying on a stable order.
0.10.2 : Improve assertions
Maintenance release containing a few renaming breaking changes and improvements regarding the assertions:
Breaking changes
GenericAssertion
renamed toGenericEqualityAssertion
- `show_last_response_body
renamed to
show_last_body`` show_last_response_body_as_json
renamed toshow_last_response_body_json
show_last_response_headers
renamed toshow_last_headers
Assertion redesign
The assertions have been redesigned to offer increase their reusability and expressiveness
There are now 4 types of assertions:
- Equality : GenericEqualityAssertion, CustomMessageEqualityAssertion
- Ordering : GreaterThanAssertion, LessThanAssertion, BetweenAssertion
- Collection: CollectionEmptyAssertion, CollectionNotEmptyAssertion, CollectionSizeAssertion, CollectionContainsAssertion
- String : StringContainsAssertion, RegexAssertion
Any of those assertion can be composed using and
and or
.
For instance, the BetweenAssertion is built by composition
LessThanAssertion(inspected, high) and GreaterThanAssertion(inspected, low)
There are also a some of helpers on the Assertion
companion objects.
Misc
- support for Scala 2.12
- new built-in extractor
<random-alphanum-string>
- add
isNotEmpty
on JsonArrayStep
Then assert body.asArray.isNotEmpty
- fix a bug in the JSON array comparaison in case of duplicated element
- fix a bug in the header session encoding
- new debug instruction to show the full response
show_last_response
show_last_response_json
- introduce new DSL block
RepeatWith
to repeat a series of step with different values
RepeatWith("Superman", "Superman", "GreenLantern", "Spiderman")("superhero-name") {
When I get("/superheroes/<superhero-name>").withParams("sessionId" → "<session-id>")
Then assert status.is(200)
Then assert body.path("hasSuperpowers").is(true)
}
- improve error reporting of wrapper steps with the initial nested error.
0.10.1 : Maintenance
Maintenance release introducing the following changes:
Improving HTTP mock
The experimental HTTP mock DSL received a couple of new features.
- a network interface and a range of ports can be provided to offer more control regarding the server binding.
- recorded requests can be purged using the reset endpoint.
- the mock can enter an error mode on demand to return HTTP 500.
Refer to those examples for more information.
Other changes
- The HTTP DSL regarding headers has been improved with the following steps:
headers.name("cache-control").isPresent
headers.name("cache_control").isAbsent
save_header_value("cache-control" → "my-cache-control-value")
0.10 : Non-blocking steps
This release contains several breaking changes.
Non-blocking steps
All steps are now running in a non-blocking
fashion.
This migration required a large refactoring of the codebase which relied significantly on blocking
to orchestrate the execution of features.
The only impact on the user side concerns the definition of EffectStep which now requires an effect function of type Session => Future[Session]
.
A helper is present if you still want to feed a synchronous function as effect via Effect.fromSync(s => s)
.
Other changes
- Manually building a
GenericAssertion[A]
now requires an instance ofcats.kernel.Eq[A]
in scope. This change should be transparent as most common instances are provided. - The duration of
AssertStep
is now shown in the execution logs. - Various performance improvements.