给出了实现子类的Scala特性
trait Foo {
def doesStuff() : Int
}
case class Bar() extends Foo { ... }
case class Baz() extends Foo { ... }
如何组织单元测试以测试特征,然后将测试应用于每个实现?
我在找这种形式的东西:
class FooSpec(foo : Foo) extends FlatSpec {
"A Foo" should {
"do stuff" in {
assert(foo.doesStuff == 42)
}
}
}
然后将其应用于每个实现类:
FooSpec(Bar())
FooSpec(Baz())
2条答案
按热度按时间vnjpjtjt1#
如果
Bar.doesStuff
和Baz.doesStuff
的实现具有不同的行为,则使用两个单独的测试是合适的解决方案。但是,如果它们具有相同的行为,则可以使用函数重构测试以避免重复代码。我不相信scalatest能够像您所要求的那样在规范级别上实现这种重用模式。
不过,基于属性的测试完全可以实现您想要的结果。下面是一个使用scalacheck的示例:
与ScalaTest规范不同,属性始终是函数。
forAll
函数接受一个生成器,对生成器的值进行采样,并对所有采样运行测试。我们的生成器将始终返回Bar
或Baz
的示例,这意味着该属性将涵盖您要测试的所有用例。forAll
Assert,如果单个测试失败,则整个属性都会失败。rsaldnfx2#
虽然公认的答案肯定有效,但scalacheck默认情况下运行100个单元测试,并且通常用于解决与问题所建议的不同的问题。
也许这在2019年还没有提供,但我想给出一个答案,即ScalaTest3.2.9(以及更早的版本)更适用。
您可以创建一个特征来容纳所有可重用的测试,然后将其扩展到您的单元测试中。下面我将使用问题类给出一个简短的例子。The full example is provided at this link under "Shared tests".
链接摘录,以防它不起作用
有时,您可能希望在不同的装置对象上运行相同的测试代码。换句话说,您可能希望编写由不同的Fixture对象“共享”的测试。要在AnyFlatSpec中实现这一点,首先要将共享测试放在行为函数中。这些行为函数将在使用它们的任何AnyFlatSpec的构造阶段被调用,因此它们包含的测试将被注册为该AnyFlatSpec中的测试。例如,给定此堆栈类:
..。
您可能希望在不同的状态下测试Stack类:空、满、一项、一项小于容量,等等。您可能会发现,只要堆栈不为空,您就有几个测试是有意义的。因此,理想情况下,您会希望对三个堆栈装置对象运行相同的测试:一个完整的堆栈,一个只有一个项目的堆栈,以及一个项目少于容量的堆栈。使用共享测试,您可以将这些测试分解到一个行为函数中,并将运行测试时使用的堆栈装备传递到该函数中。因此,在您的AnyFlatSpec for Stack中,您将调用三次Behavior函数,传入三个堆栈装备中的每一个,以便为所有三个装备运行共享测试。您可以定义一个行为函数,将这些共享测试封装在使用它们的AnyFlatSpec中。但是,如果它们在不同的AnyFlatSpec之间共享,您还可以在混合到使用它们的每个AnyFlatSpec中的单独特征中定义它们。