Code Monkey home page Code Monkey logo

xpct's Introduction

About

xpct provides an algebra that abstracts assertion of conditions and extraction of values from heterogeneous data types contained in a computation effect.

In more concrete terms, you can sequence IOs in a for-comprehension, adding an expectation to each step, while extracting values contained in Options or Eithers through typeclass based matchers:

import cats.implicits._

for {
  a <- IO.pure(Either.right("test")) must contain("test")
  b <- IO.pure(Option(5)) must beSome(be_>=(2))
  _ <- IO.pure(s"$a $b") must_== "test 5"
} yield ()

Module IDs

"io.tryp" %% "xpct-core" % "0.2.1"
"io.tryp" %% "xpct-klk" % "0.2.1"
"io.tryp" %% "xpct-specs2" % "0.2.1"
"io.tryp" %% "xpct-scalatest" % "0.2.1"
"io.tryp" %% "xpct-utest" % "0.2.1"

Features

Matching and Extracting

Matches are based on the typeclass Match, where Predicate[_] is an arbitrary data type that represents a specific condition, like IsSome[Int](5) (here Target is Int):

trait Match[Predicate[_], Target, Subject, Output]
{
  def apply(a: Subject, fb: Predicate[Target]): AssertResult[Output]
}

Subject is the expectable value; matches can be performed on differing types, producing a third type Output that is extracted monadically. When a Predicate[Target] value is passed to the implicit must method on the expectable, an Xp value is produced, which uses the Output value returned from Match.apply for monadic composition, allowing you to use the expectation in a for-comprehension regardless of the type of Subject.

Nesting matchers is a mechanism that is implemented in an ad-hoc way in common spec frameworks. With xpct, a separate instance of Match can be defined that has another matcher type as its Target, allowing arbitrary nesting.

Included Matchers and Modifiers

All matchers and modifiers can be chained, i.e. applied to both IO and Xp[IO, *].

Match Types

Alternative syntaxes are available for matching:

Implicit Methods

IO(1).must(beSome(1)).retryEvery(100.milli)(30)
IO(1).assert(beSome(1)).attempt.retry(5)

Combinators

retryEvery(100.milli)(30)(assert(beSome(1))(IO(1)))
retry(5)(attempt(assert(beSome(1))(IO(1))))

IO and Retrying

When testing asynchronous programs, especially UIs, it is not unusual to wait for a condition to become fulfilled. In frameworks like specs2 and scalatest, this feature is implemented as a special case with severe limitations on composability. xpct treats retrying as a first class operation, allowing to retry a sequence of expectations with the same semantics as strict operations:

for {
  text <- {
    for {
      elem <- getUiElement(5) must beASome[Text]
      text <- IO.pure(elem) must containText("Cancel")
    } yield text
  }.retryEvery(10, 100.milliseconds)
  _ <- setUiElementText(6, text) must beRight
} yield ()

Aside from cats.effect.IO, arbitrary async effects can be used, as long as they implement the typeclass EvalXp:

trait EvalXp[F[_]]
{
  def apply[A](fa: F[A]): A
}

For the retry operation, an instance of cats.effect.Timer[F] is required.

Test Frameworks

kallikrein

kallikrein integration is the most seamless one, since it also focuses on IO programs.

The xpct-klk package contains instances of Compile[Xp] and TestResult[XpResult]. Either import the package xpct.klk._, mix in XpctKlk or subclass XpctKlkTest[F, SbtResources].

specs2

The xpct-specs2 package contains an instance of AsResult[Xpct], which is sufficient for automatic conversion of Xpct values to specs2 Fragments.

A convenience trait XpctSpec is provided, which includes the implicit conversion to the extension class with must methods.

scalatest

The xpct-scalatest package contains the trait XpctSpec, providing a helper function xpct that converts an Xpct to a TestFailedException.

utest

The xpct-utest package contains the trait XpctSpec, providing a helper function xpct that converts an Xpct to an exception.

xpct's People

Contributors

tek avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.