Skip to content

Releases: agourlay/cornichon

0.12.0 : New EffectStep type

02 May 14:30
Compare
Choose a tag to compare

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 vs s.getJsonUnsafe
  • CornichonJson.parseString vs CornichonJson.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

21 Mar 12:55
Compare
Choose a tag to compare

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 with gqljson 1f094c8

0.11.1 : Modules

16 Feb 16:23
Compare
Choose a tag to compare

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 banner

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

06 Feb 09:39
Compare
Choose a tag to compare

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

23 Jan 12:24
Compare
Choose a tag to compare

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

14 Dec 14:17
Compare
Choose a tag to compare

Maintenance release containing the following changes.

  • fix issue triggered when using the Attach block as a starting point of a Scenario.
  • 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

07 Dec 13:01
Compare
Choose a tag to compare

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 for save_body_path("$", ???)
  • add RepeatFrom which is identical to RepeatWith 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

25 Nov 10:45
Compare
Choose a tag to compare

Maintenance release containing a few renaming breaking changes and improvements regarding the assertions:

Breaking changes

  • GenericAssertion renamed to GenericEqualityAssertion
  • `show_last_response_bodyrenamed toshow_last_body``
  • show_last_response_body_as_json renamed to show_last_response_body_json
  • show_last_response_headers renamed to show_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

07 Nov 10:39
Compare
Choose a tag to compare

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

31 Oct 10:01
Compare
Choose a tag to compare

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 of cats.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.