Skip to content

Commit

Permalink
make assertion predicates optional and repeated arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
wi101 committed Nov 28, 2020
1 parent d3ba19b commit d45947b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/cli/cli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ object Suite {

implicit val showOutcome: AnsiShow[Outcome] = _ match {
case Passed => pass
case FailsAt(Fail(map), 1) => fail
case FailsAt(Fail(map, _), 1) => fail
case FailsAt(ThrowsInCheck(exception, map), n) => checkThrows
case FailsAt(Throws(exception, map), 1) => throws
case FailsAt(_, n) => tailFail
Expand Down
30 changes: 19 additions & 11 deletions src/core/probably.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ object Runner {
sealed abstract class Datapoint(val map: Map[String, String])
case object Pass extends Datapoint(Map())

case class Fail(failMap: Map[String, String]) extends Datapoint(failMap)
case class Fail(failMap: Map[String, String], index: Int) extends Datapoint(failMap)
case class Throws(exception: Throwable, throwMap: Map[String, String]) extends Datapoint(throwMap)
case class ThrowsInCheck(exception: Exception, throwMap: Map[String, String]) extends Datapoint(throwMap)

Expand Down Expand Up @@ -76,7 +76,7 @@ class Runner(specifiedTests: Set[TestId] = Set()) extends Dynamic {

def applyDynamic[T](method: String)(name: String)(fn: => T): Test { type Type = T } =
applyDynamicNamed[T]("")("" -> name)(fn)

def applyDynamicNamed[T]
(method: String)
(name: (String, String), args: (String, Showable[_])*)
Expand Down Expand Up @@ -115,20 +115,28 @@ class Runner(specifiedTests: Set[TestId] = Set()) extends Dynamic {

def id: TestId = TestId(Runner.shortDigest(name))
def action(): Type

def assert(predicate: Type => Boolean): Unit =
try if(runTest(id)) check(predicate) catch { case NonFatal(e) => () }

def check(predicate: Type => Boolean): Type = {

def assert(predicate: (Type => Boolean)*): Unit =
try if(runTest(id)) check(predicate : _*) catch { case NonFatal(_) => () }

def check(predicates: (Type => Boolean)*): Type = {
def handler: PartialFunction[Throwable, Datapoint] = { case e: Exception => ThrowsInCheck(e, map) }
def makeDatapoint(predicates: Seq[Type => Boolean], count: Int, datapoint: Datapoint, value: Type): Datapoint = {
try {
if (predicates.isEmpty) datapoint
else
if (predicates.head(value)) makeDatapoint(predicates.tail, count + 1, Pass, value)
else Fail(map, count)
} catch handler
}

val t0 = System.currentTimeMillis()
val value = Try(action())
val time = System.currentTimeMillis() - t0

value match {
case Success(value) =>
def handler: PartialFunction[Throwable, Datapoint] = { case e: Exception => ThrowsInCheck(e, map) }
val datapoint: Datapoint = try(if(predicate(value)) Pass else Fail(map)) catch handler
record(this, time, datapoint)
record(this, time, makeDatapoint(predicates, 0, Pass, value))
value
case Failure(exception) =>
record(this, time, Throws(exception, map))
Expand Down Expand Up @@ -169,7 +177,7 @@ case class Summary(id: TestId,
def avg: Double = ttot.toDouble/count/1000.0
def min: Double = tmin.toDouble/1000.0
def max: Double = tmax.toDouble/1000.0

def append(test: String, duration: Long, datapoint: Datapoint): Summary =
Summary(id, name, count + 1, tmin min duration, ttot + duration, tmax max duration, outcome match {
case FailsAt(dp, c) => FailsAt(dp, c)
Expand Down
61 changes: 60 additions & 1 deletion src/test/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
*/
package probably.tests

import probably.Runner.{Fail, FailsAt}
import probably._
import scala.util.Try

object Main extends Suite("Probably Tests") {

Expand Down Expand Up @@ -86,7 +88,7 @@ object Main extends Suite("Probably Tests") {
for(i <- 1 to 10) runner("integers are less than six", i = i)(i).assert(_ < 6)
runner.report().results.head.outcome
}.assert {
case Runner.FailsAt(Runner.Fail(map), _) if map("i") == "6" => true
case Runner.FailsAt(Runner.Fail(map, _), _) if map("i") == "6" => true
case x => false
}

Expand All @@ -109,5 +111,62 @@ object Main extends Suite("Probably Tests") {
}.assert(_ == 2)
runner.report
}.assert(_.results.head.count == 100)

test("assert without predicate should succeed") {
val runner = new Runner()
runner("test division") {
5 / 2
}.assert()
runner.report()
}.assert(r => r.passed == r.total)

test("assert without predicate should fail") {
val runner = new Runner()
runner("test division") {
5 / 0
}.assert()
runner.report()
}.assert(r => r.passed == 0)

test("check without predicate should succeed") {
val runner = new Runner()
runner("test division") {
5 / 2
}.check()
runner.report()
}.assert(r => r.passed == r.total)

test("check without predicate should fail") {
val runner = new Runner()
Try(runner("test division") {
5 / 0
}.check())
runner.report()
}.assert(r => r.failed == 1)

test("assert with 2 successful predicates") {
val runner = new Runner()
runner("test double") {
0.001
}.assert(_ >= 0.0, _ <= 1.0)
runner.report()
}.assert(r => r.passed == r.total)

test("assert with 2 predicates") {
val runner = new Runner()
runner("test double") {
0.001
}.assert(_ >= 0.0, _ < 0.0)
runner.report().results.head.outcome
}.assert(_ == FailsAt(Fail(Map.empty, 1), 1))

test("assert with 3 predicates") {
val runner = new Runner()
runner("test double") {
0.001
}.assert(_ >= 0.0, _ <= 1.0, _ < 0.0)
runner.report().results.head.outcome
}.assert(_ == FailsAt(Fail(Map.empty, 2), 1))

}
}

0 comments on commit d45947b

Please sign in to comment.