Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preliminary Munit port #3538

Merged
merged 17 commits into from
Aug 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
package alleycats.tests

import org.scalactic.anyvals.{PosInt, PosZDouble, PosZInt}
import org.scalatest.matchers.should.Matchers
import org.scalatest.prop.Configuration
import org.scalacheck.Test.Parameters

trait TestSettings extends Configuration with Matchers {
trait TestSettings {

lazy val checkConfiguration: PropertyCheckConfiguration =
PropertyCheckConfiguration(
minSuccessful = PosInt(50),
maxDiscardedFactor = PosZDouble(5.0),
minSize = PosZInt(0),
sizeRange = PosZInt(10),
workers = PosInt(1)
)
lazy val checkConfiguration: Parameters =
Parameters.default
.withMinSuccessfulTests(50)
.withMaxDiscardRatio(5.0f)
.withMaxSize(10)
.withMinSize(0)
.withWorkers(1)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,17 @@ package alleycats.tests
import alleycats.std.MapInstances
import cats._
import cats.instances.all._
import cats.tests.StrictCatsEquality
import org.scalatest.funsuite.AnyFunSuiteLike
import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks
import org.typelevel.discipline.scalatest.FunSuiteDiscipline
import org.scalacheck.{Arbitrary, Gen}
import org.scalacheck.Arbitrary.arbitrary
import org.scalatest.matchers.should.Matchers
import scala.util.{Failure, Success, Try}
import org.scalacheck.Test.Parameters

/**
* An opinionated stack of traits to improve consistency and reduce
* boilerplate in Alleycats tests. Derived from Cats.
*/
trait AlleycatsSuite
extends AnyFunSuiteLike
with Matchers
with ScalaCheckDrivenPropertyChecks
with FunSuiteDiscipline
with TestSettings
with TestInstances
with StrictCatsEquality
with MapInstances {
implicit override val generatorDrivenConfig: PropertyCheckConfiguration =
trait AlleycatsSuite extends munit.DisciplineSuite with TestSettings with TestInstances with MapInstances {
implicit override def scalaCheckTestParameters: Parameters =
checkConfiguration

implicit def EqIterable[A: Eq]: Eq[Iterable[A]] = Eq.by(_.toList)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@ class IterableTests extends AlleycatsSuite {

test("foldLeft sum == sum") {
val it = Iterable(1, 2, 3)
Foldable[Iterable].foldLeft(it, 0) {
case (b, a) => a + b
} shouldEqual (it.sum)
assertEquals(Foldable[Iterable].foldLeft(it, 0) {
case (b, a) => a + b
},
it.sum
)
}

test("foldRight early termination") {
Foldable[Iterable]
.foldRight(Iterable(1, 2, 3), Eval.now("KO")) {
case (2, _) => Eval.now("OK")
case (a, b) => b
}
.value shouldEqual (Eval.now("OK").value)
assertEquals(Foldable[Iterable]
.foldRight(Iterable(1, 2, 3), Eval.now("KO")) {
case (2, _) => Eval.now("OK")
case (a, b) => b
}
.value,
Eval.now("OK").value
)
}

checkAll("Foldable[Iterable]", FoldableTests[Iterable].foldable[Int, Int])
Expand Down
4 changes: 2 additions & 2 deletions binCompatTest/src/test/scala/catsBC/MimaExceptionsTest.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package catsBC

import org.scalatest.funsuite.AnyFunSuiteLike
import munit.FunSuite

class MimaExceptionsTest extends AnyFunSuiteLike {
class MimaExceptionsTest extends FunSuite {
test("is binary compatible") {
MimaExceptions.isBinaryCompatible
}
Expand Down
19 changes: 7 additions & 12 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ isTravisBuild in Global := sys.env.get("TRAVIS").isDefined

val scalaCheckVersion = "1.14.3"

val scalatestVersion = "3.2.0"
val scalatestplusScalaCheckVersion = "3.2.0.0"
val munitVersion = "0.7.10"

val disciplineVersion = "1.0.2"

val disciplineScalatestVersion = "2.0.0"
val disciplineMunitVersion = "0.2.2"

val kindProjectorVersion = "0.11.0"

Expand Down Expand Up @@ -68,6 +68,7 @@ lazy val commonSettings = commonScalaVersionSettings ++ Seq(
Test / unmanagedSourceDirectories ++= scalaVersionSpecificFolders("test", baseDirectory.value, scalaVersion.value),
resolvers ++= Seq(Resolver.sonatypeRepo("releases"), Resolver.sonatypeRepo("snapshots")),
parallelExecution in Test := false,
testFrameworks += new TestFramework("munit.Framework"),
scalacOptions in (Compile, doc) := (scalacOptions in (Compile, doc)).value.filter(_ != "-Xfatal-warnings")
) ++ warnUnusedImport

Expand Down Expand Up @@ -126,6 +127,7 @@ lazy val commonJsSettings = Seq(
jsEnv := new org.scalajs.jsenv.nodejs.NodeJSEnv(),
// batch mode decreases the amount of memory needed to compile Scala.js code
scalaJSLinkerConfig := scalaJSLinkerConfig.value.withBatchMode(isTravisBuild.value),
scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this change necessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly don't know, but the error message I got when running the tests without it pointed me to this. 😄

// currently sbt-doctest doesn't work in JS builds
// https://github.com/tkawachi/sbt-doctest/issues/52
doctestGenTests := Seq.empty,
Expand Down Expand Up @@ -159,17 +161,10 @@ lazy val disciplineDependencies = Seq(

lazy val testingDependencies = Seq(
libraryDependencies ++= Seq(
"org.scalatest" %%% "scalatest-shouldmatchers" % scalatestVersion % Test,
"org.scalatest" %%% "scalatest-funsuite" % scalatestVersion % Test,
"org.scalatestplus" %%% "scalacheck-1-14" % scalatestplusScalaCheckVersion % Test
),
libraryDependencies ++= Seq(
("org.typelevel" %%% "discipline-scalatest" % disciplineScalatestVersion % Test)
"org.scalameta" %%% "munit-scalacheck" % munitVersion % Test,
"org.typelevel" %%% "discipline-munit" % disciplineMunitVersion % Test
).map(
_.exclude("org.scalatestplus", "scalacheck-1-14_2.13")
.exclude("org.scalactic", "scalactic_2.13")
.exclude("org.scalatest", "scalatest_2.13")
.withDottyCompat(scalaVersion.value)
_.withDottyCompat(scalaVersion.value)
)
)

Expand Down
8 changes: 5 additions & 3 deletions docs/src/main/tut/typeclasses/lawtesting.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,14 @@ object arbitraries {
```

Now we can convert these `ScalaCheck` `Properties` into tests that the test framework can run. [discipline](https://github.com/typelevel/discipline) provides a helper `checkAll` function that performs
this conversion for two test frameworks: `ScalaTest` and `Specs2`.
this conversion for three test frameworks: `ScalaTest`, `Specs2` and `MUnit`.

* If you are using `Specs2`, extend your test class with `org.typelevel.discipline.specs2.Discipline` (provided by `discipline-specs2`).

* If you are using `ScalaTest`, extend your test class with `org.typelevel.discipline.scalatest.FunSuiteDiscipline` (provided by `discipline-scalatest`) and `org.scalatest.funsuite.AnyFunSuiteLike`.

* If you are using `MUnit`, extend your test class with `munit.DisciplineSuite` (provided by `discipline-munit`).

* For other test frameworks, you need to resort to their integration with `ScalaCheck` to test
the `ScalaCheck` `Properties` provided by `cats-laws`.

Expand All @@ -111,7 +113,7 @@ class TreeLawTests extends AnyFunSuite with FunSuiteDiscipline with Checkers {
* `arbitraries._` imports the `Arbitrary[Tree[_]]` instances needed to check the laws.

Alternatively, you can use the `CatsSuite` provided by [Cats-testkit-scalatest](https://github.com/typelevel/cats-testkit-scalatest),
which is the same `CatsSuite` used in Cats to test all instances.
which used to be what Cats used internally to test all instances.

Now when we run `test` in our sbt console, ScalaCheck will test if the `Functor` laws hold for our `Tree` type.
You should see something like this:
Expand Down Expand Up @@ -167,7 +169,7 @@ import org.typelevel.discipline.scalatest.FunSuiteDiscipline
import arbitraries._

class TreeLawTests extends AnyFunSuite with FunSuiteDiscipline with Checkers {
checkAll("Tree[Int].SemigroupLaws", SemigroupTests[Tree[Int]].semigroup)
checkAll("Tree.FunctorLaws", FunctorTests[Tree].functor[Int, Int, String])
checkAll("Tree[Int].SemigroupLaws", SemigroupTests[Tree[Int]].semigroup)
}
```
31 changes: 16 additions & 15 deletions free/src/test/scala/cats/free/CofreeSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import cats.laws.discipline.SemigroupalTests.Isomorphisms
import cats.syntax.list._
import cats.tests.{CatsSuite, Spooky}
import org.scalacheck.{Arbitrary, Cogen, Gen}
import cats.syntax.eq._

class CofreeSuite extends CatsSuite {

Expand All @@ -32,7 +33,7 @@ class CofreeSuite extends CatsSuite {
test("Cofree.unfold") {
val unfoldedHundred: CofreeNel[Int] = Cofree.unfold[Option, Int](0)(i => if (i == 100) None else Some(i + 1))
val nelUnfoldedHundred: NonEmptyList[Int] = NonEmptyList.fromListUnsafe(List.tabulate(101)(identity))
cofNelToNel(unfoldedHundred) should ===(nelUnfoldedHundred)
assert(cofNelToNel(unfoldedHundred) === nelUnfoldedHundred)
}

test("Cofree.ana") {
Expand All @@ -41,7 +42,7 @@ class CofreeSuite extends CatsSuite {
_.head
)
val nelUnfoldedHundred: NonEmptyList[Int] = NonEmptyList.fromListUnsafe(List.tabulate(101)(identity))
cofNelToNel(anaHundred) should ===(nelUnfoldedHundred)
assert(cofNelToNel(anaHundred) === nelUnfoldedHundred)
}

test("Cofree.tailForced") {
Expand All @@ -50,9 +51,9 @@ class CofreeSuite extends CatsSuite {
Cofree.unfold[Id, Int](spooky.counter) { _ =>
spooky.increment(); spooky.counter
}
spooky.counter should ===(0)
assert(spooky.counter === 0)
incrementor.tailForced
spooky.counter should ===(1)
assert(spooky.counter === 1)
}

test("Cofree.forceTail") {
Expand All @@ -61,9 +62,9 @@ class CofreeSuite extends CatsSuite {
Cofree.unfold[Id, Int](spooky.counter) { _ =>
spooky.increment(); spooky.counter
}
spooky.counter should ===(0)
assert(spooky.counter === 0)
incrementor.forceTail
spooky.counter should ===(1)
assert(spooky.counter === 1)
}

test("Cofree.forceAll") {
Expand All @@ -77,9 +78,9 @@ class CofreeSuite extends CatsSuite {
Some(spooky.counter)
}
)
spooky.counter should ===(0)
assert(spooky.counter === 0)
incrementor.forceAll
spooky.counter should ===(5)
assert(spooky.counter === 5)
}

test("Cofree.mapBranchingRoot") {
Expand All @@ -88,7 +89,7 @@ class CofreeSuite extends CatsSuite {
def apply[A](a: Option[A]): Option[A] = None
})
val nelUnfoldedOne: NonEmptyList[Int] = NonEmptyList.one(0)
cofNelToNel(withNoneRoot) should ===(nelUnfoldedOne)
assert(cofNelToNel(withNoneRoot) === nelUnfoldedOne)
}

val unfoldedHundred: Cofree[Option, Int] = Cofree.unfold[Option, Int](0)(i => if (i == 100) None else Some(i + 1))
Expand All @@ -97,8 +98,8 @@ class CofreeSuite extends CatsSuite {
val toNelS = unfoldedHundred.mapBranchingS(toList)
val toNelT = unfoldedHundred.mapBranchingT(toList)
val nelUnfoldedOne: NonEmptyList[Int] = NonEmptyList.fromListUnsafe(List.tabulate(101)(identity))
cofRoseTreeToNel(toNelS) should ===(nelUnfoldedOne)
cofRoseTreeToNel(toNelT) should ===(nelUnfoldedOne)
assert(cofRoseTreeToNel(toNelS) === nelUnfoldedOne)
assert(cofRoseTreeToNel(toNelT) === nelUnfoldedOne)
}

val nelUnfoldedHundred: NonEmptyList[Int] = NonEmptyList.fromListUnsafe(List.tabulate(101)(identity))
Expand All @@ -110,7 +111,7 @@ class CofreeSuite extends CatsSuite {
Eval.now(NonEmptyList(i, lb.fold[List[Int]](Nil)(_.toList)))
)
.value
cata should ===(nelUnfoldedHundred)
assert(cata === nelUnfoldedHundred)
}

test("Cofree.cata is stack-safe") {
Expand All @@ -121,7 +122,7 @@ class CofreeSuite extends CatsSuite {
.cata[Option, Int, Int](unfolded)((i, lb) => Eval.now(lb.fold(0)(_ + i)))
.value

cata should ===(sum)
assert(cata === sum)
}

test("Cofree.cataM") {
Expand All @@ -141,8 +142,8 @@ class CofreeSuite extends CatsSuite {
)(folder)(inclusion)
.value
.value
cataHundred should ===(Some(nelUnfoldedHundred))
cataHundredOne should ===(None)
assert(cataHundred === Some(nelUnfoldedHundred))
assert(cataHundredOne === None)
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import cats.kernel.Eq
import cats.laws.discipline.{ContravariantTests, SerializableTests}
import cats.tests.CatsSuite
import org.scalacheck.{Arbitrary}
import cats.syntax.eq._
import org.scalacheck.Prop._

class ContravariantCoyonedaSuite extends CatsSuite {

Expand Down
6 changes: 4 additions & 2 deletions free/src/test/scala/cats/free/CoyonedaSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import cats.kernel.Eq
import cats.laws.discipline.{FunctorTests, SerializableTests}
import cats.tests.CatsSuite
import org.scalacheck.Arbitrary
import cats.syntax.eq._
import org.scalacheck.Prop._

class CoyonedaSuite extends CatsSuite {
implicit def coyonedaArbitrary[F[_]: Functor, A: Arbitrary](implicit F: Arbitrary[F[A]]): Arbitrary[Coyoneda[F, A]] =
Expand All @@ -22,15 +24,15 @@ class CoyonedaSuite extends CatsSuite {

test("toYoneda and then toCoyoneda is identity") {
forAll { (y: Coyoneda[Option, Int]) =>
y.toYoneda.toCoyoneda should ===(y)
assert(y === y.toYoneda.toCoyoneda)
}
}

test("mapK and run is same as applying natural trans") {
val nt = new FunctionK[Option, List] { def apply[A](a: Option[A]): List[A] = a.toList }
val o = Option("hello")
val c = Coyoneda.lift(o)
c.mapK(nt).run should ===(nt(o))
assert(c.mapK(nt).run === nt(o))
}

test("map order") {
Expand Down
Loading