{"id":21517542,"url":"https://github.com/tek/kallikrein","last_synced_at":"2025-04-09T21:42:39.906Z","repository":{"id":57736362,"uuid":"206958635","full_name":"tek/kallikrein","owner":"tek","description":"scala testing framework","archived":false,"fork":false,"pushed_at":"2020-04-28T14:39:43.000Z","size":135,"stargazers_count":25,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-18T19:10:12.420Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-07T11:30:32.000Z","updated_at":"2021-11-09T21:52:51.000Z","dependencies_parsed_at":"2022-08-24T11:20:47.943Z","dependency_job_id":null,"html_url":"https://github.com/tek/kallikrein","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tek%2Fkallikrein","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tek%2Fkallikrein/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tek%2Fkallikrein/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tek%2Fkallikrein/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tek","download_url":"https://codeload.github.com/tek/kallikrein/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226113180,"owners_count":17575436,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-24T00:42:27.084Z","updated_at":"2024-11-24T00:42:27.655Z","avatar_url":"https://github.com/tek.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Intro\n\n**kallikrein** is a Scala testing framework for sbt focused on running [cats-effect] based programs.\n\nIf you're into matcher DSLs, check out [xpct], which is a framework-agnostic typed matcher lib with support for\n**kallikrein**.\n\n## module ids\n\n```sbt\n\"io.tryp\" %% \"kallikrein-sbt\" % \"0.5.2\"\n\"io.tryp\" %% \"kallikrein-http4s-sbt\" % \"0.5.2\"\n```\n\n## sbt\n\nTo use the framework in a project, specify the setting:\n\n```sbt\ntestFrameworks += new TestFramework(\"klk.KlkFramework\")\n```\n\n# Basics\n\n## Imperative DSL\n\n```scala\nclass SomeTest\nextends klk.IOTest\n{\n  test(\"description\")(IO.pure(1 == 1))\n}\n```\n\nTests are added by calling the `test` function in a class inheriting `klk.SimpleTest[F]`, where `F[_]` is an effect that\nimplements `cats.effect.Sync`.\n`klk.IOTest` is a convenience trait using `cats.effect.IO`.\n\nAssertions are returned from the test thunk and can be anything, as long as there is an instance for `klk.TestResult`.\nThe internal type representing the result is `KlkResult`.\n\n## Composable Tests\n\nThe above mentioned `test` builder can also be used in a pure context and has a nice arsenal of typeclass instances for\ncomposition.\n\nWhen tests are sequenced in a for comprehension, the semantic effect is that of conditional execution:\nIf one test fails, all following tests are skipped.\n\nThere is an instance of `SemigroupK` available, allowing you to use the `\u003c+\u003e` operator, resulting in the alternative, or\n`unless`, semantics – i.e. if and only if the first test fails, execute the second one and use its result.\n\nFor independent tests, there are two combinators: `sequential` and `parallel`.\nThey do what you would expect, similar to the imperative test building syntax.\nThe `parallel` variant requires an instances of `cats.Parallel` and will execute the tests with a `parTraverse`.\n\nThe following example will result in a successful end result:\n\n```scala\nclass DepTest\nextends ComposeTest[IO, SbtResources]\n{\n  def testSuccess: IO[Boolean] =\n    IO.pure(true)\n\n  def testFail: IO[Boolean] =\n    IO.raiseError(new Exception(\"boom\"))\n\n  implicit def cs: ContextShift[IO] =\n    IO.contextShift(ExecutionContext.global)\n\n  def tests: Suite[IO, Unit, Unit] =\n    for {\n      _ \u003c- sharedResource(Resource.pure(5))(\n        builder =\u003e\n          builder.test(\"five is 4\")(five =\u003e IO.pure(five == 4)) \u003c+\u003e\n          builder.test(\"five is 5\")(five =\u003e IO.pure(five == 5))\n      )\n      _ \u003c- test(\"test 1\")(testSuccess)\n      _ \u003c- test(\"test 2\")(testFail) \u003c+\u003e test(\"test 3\")(testSuccess)\n      _ \u003c- Suite.parallel(test(\"test 4a\")(testSuccess), test(\"test 4b\")(testSuccess)) \u003c+\u003e test(\"test 5\")(testFail)\n      _ \u003c- test(\"test 7\")(testSuccess)\n    } yield ()\n}\n```\n\n# Results and Effects\n\nThe effect type of an individual test can be different from the main effect if there is an instance of `klk.Compile[F,\nG]`.\nFor example, `EitherT` is supported out of the box:\n\n```scala\ntest(\"EitherT\")(EitherT.right[Unit](IO.pure(1 == 1)))\n```\n\nA `Left` value will be converted into a failure by the typeclass `TestResult[A]`, meaning that this works just as well with\n`IO[Either[A, B]]`.\n\n## fs2\n\nA `Stream[F, A]` will automatically be compiled to `F`, with the inner value being handled by a dependent typeclass\ninstance.\n\n## http4s\n\nThe `kallikrein-http4s-sbt` module provides a [shared resource](#resources) that runs an [http4s] server on a random\nport and supplies tests with a client and the `Uri` of the server wrapped in a test client interface:\n\n```scala\nclass SomeTest\nextends klk.Http4sTest[IO]\n{\n  def tests: Suite[IO, Unit, Unit] =\n    server\n      .app(HttpApp.liftF(IO.pure(Response[IO]())))\n      .test { builder =\u003e\n      builder.test(\"http4s\") { client =\u003e\n        client.fetch(Request[IO]())(_ =\u003e IO.pure(true))\n      }\n    }\n}\n```\n\nThe `TestClient` class provides a `fetch` method that injects the uri into the request with its\n`withUri(request: Request[F])` method, as well as a `success` method, which produces a failed `KlkResult` if the\nresponse status is other than `2xx`.\n\n# Resources\n\nTests can depend on shared and individual resources that will be supplied by the framework when running:\n\n```scala\nclass SomeTest\nextends klk.IOTest\n{\n  val res1: Resource[IO, Int] = Resource.pure(1)\n\n  val res2: Resource[IO, Int] = Resource.pure(1)\n\n  test(\"resource\").resource(res1).resource(res2)((i: Int) =\u003e (j: Int) =\u003e IO.pure(i == j))\n\n  def eightySix: SharedResource[IO, Int] =\n    sharedResource(Resource.pure(86))\n\n  eightySix.test(\"shared resource 1\")(i =\u003e IO.pure(i == 86))\n\n  eightySix.test(\"shared resource 2\")(i =\u003e IO.pure(i == 68))\n}\n```\n\nThe shared resource will be acquired only once and supplied to all tests that use it.\n\n# Property Testing\n\n[Scalacheck] can be used in a test by calling the `forall` method on a test builder:\n\n```scala\nclass SomeTest\nextends klk.IOTest\n{\n  test(\"are all lists of integers shorter than 5 elements?\").forall((l1: List[Int]) =\u003e IO(l1.size \u003c 5))\n}\n```\n\nThis features a custom runner for the properties built on fs2.\n\nA second variant `forallNoShrink` does what it advertises.\n\n# Law Checking\n\n[cats-discipline] laws can be checked like this:\n\n```scala\nclass SomeTest\nextends klk.IOTest\n{\n  test(\"laws\").laws(IO.pure(FunctorTests[List].functor[Int, Int, Int]))\n}\n```\n\n[cats-effect]: https://github.com/typelevel/cats-effect\n[xpct]: https://github.com/tek/xpct\n[scalacheck]: https://github.com/typelevel/scalacheck\n[cats-discipline]: https://github.com/typelevel/discipline\n[http4s]: https://github.com/http4s/http4s\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftek%2Fkallikrein","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftek%2Fkallikrein","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftek%2Fkallikrein/lists"}