scala中case类的部分覆盖测试用例

oxf4rvwz  于 2022-11-23  发布在  Scala
关注(0)|答案(1)|浏览(205)

我有一个case类定义如下

case class Person(name:String = null)

以下是此用例类的测试用例。

import org.scalatest.FunSuite
class PersonTest extends FunSuite{

  test("Person test"){
    val personName=Person("Bill")
    assert(personName.name == s"Bill")
}

测试用例通过,但是在sonarqube代码覆盖中,20个用例中只有1个被覆盖或部分覆盖。我如何知道哪些是该用例类未覆盖的剩余19个条件?

6ioyuze2

6ioyuze21#

jacoco标记来看,您似乎正在使用Jacoco生成覆盖率数据,以便sonarqube进行报告。
Jacoco并不理解Scala,所以它只是将case class看作一个JVM类。Scala case class有很多功能是由编译器合成的:对于jacoco来说,这个功能对于测试覆盖率来说很重要。
最值得注意的是,编译器综合了

  • equals
  • toString
  • hashCode
  • copy

这些实施经过实战测试(并且Scala编译器团队在CI中进行了测试,我的雇主雇佣了他们中的很大一部分人),所以对它们进行测试可能没有太大的价值。至少在您使用大量case class和/或有覆盖率要求的情况下是如此,这将迫使您测试合成功能(像scoverage这样的东西会知道case class是什么)。
如果出于某种原因,你必须提高案例类的覆盖率,那么像这样的测试应该会有所帮助:

// test equals method
val bill = Person("Bill")
val ted = Person("Ted")
assert(bill == bill)
assert(bill != ted)
assert(bill != new AnyRef)

// test hashCode
assert(bill.hashCode == Person("Bill").hashCode)
// might be very unlucky if "Bill" and "Ted" hash the same, in which case this adventure is kinda bogus
assert(bill.hashCode != ted.hashCode)

// alternatively (only works since this is a single-field case class
assert((bill.name.hashCode == ted.name.hashCode) || (bill.hashCode != ted.hashCode))

// test toString
assert(bill.toString.startsWith("Person("))

// test copy (repeat this for all permutations of fields)
assert(bill.copy().name == bill.name)
assert(bill.copy(name = "Rufus").name == "Rufus")

您可能必须查看生成的字节码,以找到可以测试的其他方法;类似地,合成方法应该能够被反编译成Java,这样您就可以了解分支是什么。hashCode中的模移位之类的内容可能被解释为条件,在这种情况下,您可能需要试验满足覆盖率度量所需的幻值。
如上所述,这种满足非完整覆盖率指标的努力基本上是浪费了。我建议在这些测试中包含一个注解,如:

// included solely to satisfy code coverage: these methods are synthesized by the compiler

(you可以让他们变得像你喜欢的那样消极攻击:))
对于分支覆盖率(我认为条件的意思是什么?),有些分支可能无法在惯用的Scala中触发。

相关问题