I am curious to know if it is possible to fully test following code with Pitest/ScalaCheck
Methods to test:
def insertionSort(xs: List[Int]): List[Int] = xs match {
case Nil => Nil
case a :: as => insert(a, insertionSort(as))
}
private def insert(x: Int, xs: List[Int]): List[Int] = xs match {
case Nil => List(x)
case a :: as =>
if (a >= x) x :: xs
else a :: insert(x, as)
}
Tests provided:
@RunWith(classOf[ScalaCheckJUnitPropertiesRunner])
class InsertionSortTests extends Properties("InsertionSortTests") {
private val nonEmptyIntListGen: Gen[List[Int]] = Gen.nonEmptyListOf(Arbitrary.arbitrary[Int])
property("ordered") = forAll(nonEmptyIntListGen) { (xs: List[Int]) =>
val sorted = insertionSort(xs)
xs.nonEmpty ==> xs.indices.tail.forall((i: Int) => sorted(i - 1) <= sorted(i))
}
property("permutation") = forAll { (xs: List[Int]) =>
val sorted = insertionSort(xs)
def count(a: Int, as: List[Int]) = as.count(_ == a)
xs.forall((x: Int) => count(x, xs) == count(x, sorted))
}
}
I am getting full coverage except following lines:
def insertionSort(xs: List[Int]): List[Int] = xs match {
private def insert(x: Int, xs: List[Int]): List[Int] = xs match {
I am getting following error on both lines:
1. removed call to scala/MatchError::<init> → NO_COVERAGE
The call to
scala/MatchError
is synthesized by the compiler for the case where the match fails (it's the call toMatchError
's constructor which gets thrown if none of thecase
s in the pattern match apply). Since your pattern match is in fact exhaustive, there's no way for the match to fail, ergo there's no way in Scala to force the match to fail (this is assuming that you're using the standard libraryList
; if you're using your own implementation ofList
, perhaps it's notsealed
?)It's perhaps a Scala compiler bug that it generates bytecode for failed pattern matches which can't fail.
I'm not familiar with pitest, but it's likely that it doesn't understand Scala (or the higher level semantic meaning of the bytecode emitted by the Scala compiler); tools which rely on bytecode manipulation are likely to not always work as they would for Java with Scala.