Skip to content

Commit

Permalink
Improve test coverage overridden Foldable methods
Browse files Browse the repository at this point in the history
  • Loading branch information
peterneyens committed Feb 2, 2017
1 parent 0f6775d commit 04bbbdd
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 12 deletions.
2 changes: 1 addition & 1 deletion core/src/main/scala/cats/instances/try.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ trait TryInstances extends TryInstances1 {
override def size[A](fa: Try[A]): Long =
fa match {
case Failure(_) => 0L
case Success(a) => 1L
case Success(_) => 1L
}

override def find[A](fa: Try[A])(f: A => Boolean): Option[A] =
Expand Down
11 changes: 11 additions & 0 deletions laws/src/main/scala/cats/laws/FoldableLaws.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ trait FoldableLaws[F[_]] {
): Boolean = {
!F.isEmpty(fa) || F.forall(fa)(p)
}

/**
* Monadic folding with identity monad is analogous to `foldLeft`.
*/
def foldMIdentity[A, B](
fa: F[A],
b: B,
f: (B, A) => B
): IsEq[B] = {
F.foldM[Id, A, B](fa, b)(f) <-> F.foldLeft(fa, b)(f)
}
}

object FoldableLaws {
Expand Down
31 changes: 21 additions & 10 deletions tests/src/test/scala/cats/tests/FoldableTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ import org.scalacheck.Arbitrary
import scala.util.Try

import cats.instances.all._
import cats.data.Validated
import cats.data.{NonEmptyList, NonEmptyStream, NonEmptyVector, Validated}
import cats.laws.discipline.arbitrary._

abstract class FoldableCheck[F[_]: Foldable](name: String)(implicit ArbFInt: Arbitrary[F[Int]], ArbFString: Arbitrary[F[String]]) extends CatsSuite with PropertyChecks {

def iterator[T](fa: F[T]): Iterator[T]

test("size") {
test(s"Foldable[$name].size") {
forAll { (fa: F[Int]) =>
fa.size should === (iterator(fa).size.toLong)
}
}

test("summation") {
test(s"Foldable[$name] summation") {
forAll { (fa: F[Int]) =>
val total = iterator(fa).sum
fa.foldLeft(0)(_ + _) should === (total)
Expand All @@ -29,7 +29,7 @@ abstract class FoldableCheck[F[_]: Foldable](name: String)(implicit ArbFInt: Arb
}
}

test("find/exists/forall/filter_/dropWhile_") {
test(s"Foldable[$name].find/exists/forall/filter_/dropWhile_") {
forAll { (fa: F[Int], n: Int) =>
fa.find(_ > n) should === (iterator(fa).find(_ > n))
fa.exists(_ > n) should === (iterator(fa).exists(_ > n))
Expand All @@ -40,15 +40,15 @@ abstract class FoldableCheck[F[_]: Foldable](name: String)(implicit ArbFInt: Arb
}
}

test("toList/isEmpty/nonEmpty") {
test(s"Foldable[$name].toList/isEmpty/nonEmpty") {
forAll { (fa: F[Int]) =>
fa.toList should === (iterator(fa).toList)
fa.isEmpty should === (iterator(fa).isEmpty)
fa.nonEmpty should === (iterator(fa).nonEmpty)
}
}

test("maximum/minimum") {
test(s"Foldable[$name].maximum/minimum") {
forAll { (fa: F[Int]) =>
val maxOpt = fa.maximumOption
val minOpt = fa.minimumOption
Expand All @@ -63,21 +63,21 @@ abstract class FoldableCheck[F[_]: Foldable](name: String)(implicit ArbFInt: Arb
}
}

test("reduceLeftOption/reduceRightOption") {
test(s"Foldable[$name].reduceLeftOption/reduceRightOption") {
forAll { (fa: F[Int]) =>
val list = fa.toList
fa.reduceLeftOption(_ - _) should === (list.reduceLeftOption(_ - _))
fa.reduceRightOption((x, ly) => ly.map(x - _)).value should === (list.reduceRightOption(_ - _))
}
}

test("intercalate") {
test(s"Foldable[$name].intercalate") {
forAll { (fa: F[String], a: String) =>
fa.intercalate(a) should === (fa.toList.mkString(a))
}
}

test("toList") {
test(s"Foldable[$name].toList") {
forAll { (fa: F[Int]) =>
fa.toList should === (iterator(fa).toList)
}
Expand All @@ -92,7 +92,6 @@ class FoldableTestsAdditional extends CatsSuite {
if (a === goal) Now(true) else lb
}


test("Foldable[List]") {
val F = Foldable[List]

Expand Down Expand Up @@ -159,6 +158,18 @@ class FoldableTestsAdditional extends CatsSuite {
checkFoldMStackSafety[Map[String, ?]](_.map(x => x.toString -> x).toMap)
}

test("Foldable[NonEmptyList].foldM stack safety") {
checkFoldMStackSafety[NonEmptyList](xs => NonEmptyList.fromListUnsafe(xs.toList))
}

test("Foldable[NonEmptyVector].foldM stack safety") {
checkFoldMStackSafety[NonEmptyVector](xs => NonEmptyVector.fromVectorUnsafe(xs.toVector))
}

test("Foldable[NonEmptyStream].foldM stack safety") {
checkFoldMStackSafety[NonEmptyStream](xs => NonEmptyStream(xs.head, xs.tail: _*))
}

test("Foldable[Stream]") {
val F = Foldable[Stream]

Expand Down
13 changes: 13 additions & 0 deletions tests/src/test/scala/cats/tests/OneAndTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package tests

import cats.kernel.laws.{GroupLaws, OrderLaws}

import cats.instances.stream._
import cats.data.{NonEmptyStream, OneAnd}
import cats.laws.discipline.{ComonadTests, FunctorTests, SemigroupKTests, FoldableTests, MonadTests, SerializableTests, CartesianTests, TraverseTests, ReducibleTests}
import cats.laws.discipline.arbitrary._
Expand Down Expand Up @@ -174,3 +175,15 @@ class OneAndTests extends CatsSuite {
}
}
}

class ReducibleNonEmptyStreamCheck extends ReducibleCheck[NonEmptyStream]("NonEmptyStream") {
def iterator[T](nes: NonEmptyStream[T]): Iterator[T] =
(nes.head #:: nes.tail).iterator

def range(start: Long, endInclusive: Long): NonEmptyStream[Long] = {
// if we inline this we get a bewildering implicit numeric widening
// error message in Scala 2.10
val tailStart: Long = start + 1L
NonEmptyStream(start, (tailStart).to(endInclusive).toStream)
}
}
1 change: 0 additions & 1 deletion tests/src/test/scala/cats/tests/TupleTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class TupleTests extends CatsSuite {
checkAll("Tuple2[String, Int]", ReducibleTests[(String, ?)].reducible[Option, Int, Int])
checkAll("Reducible[(String, ?)]", SerializableTests.serializable(Reducible[(String, ?)]))


test("Cartesian composition") {
val cart = ContravariantCartesian[Eq].composeFunctor[(Int, ?)]
val eq = cart.product(Eq[(Int, String)], Eq[(Int, Int)])
Expand Down

0 comments on commit 04bbbdd

Please sign in to comment.