代码之家  ›  专栏  ›  技术社区  ›  amuttsch

Scalacheck-向命令添加参数

  •  0
  • amuttsch  · 技术社区  · 7 年前

    Scalacheck documentation 对于有状态测试,提到ATM机作为用例。为了使其工作,命令需要参数,例如PIN或提取量。在给定的示例中,类中的方法 Counter 没有参数。

    现在我的问题是如何在scalachecks状态测试中测试这样的方法:

    class Counter {
        private var n = 0
        def inc(i: Int) = n += i
        ...
    }
    

    这个 run nextState 命令的方法不提供参数。添加 Random.nextInt 不起作用,因为在 下一个状态 数值不同,测试失败:

    case object Inc extends UnitCommand {
        def run(sut: Sut): Unit = sut.inc(Random.nextInt)
    
        def nextState(state: State): State = state + Random.nextInt
        ...
    }
    

    有没有办法将参数传递给 Sut ?

    1 回复  |  直到 7 年前
        1
  •  1
  •   SergGr    7 年前

    你可能会注意到 genCommand ,ScalaCheck Commands 实际上有点像初始状态之间的笛卡尔积,由 genInitialState 和生成的一系列命令 GECOMMAND公司 . 因此,如果某些命令实际上需要参数,则需要将其从对象转换为类,并提供 Gen 为了他们。因此,修改文档中的示例时,您将需要以下内容:

    /** A generator that, given the current abstract state, should produce
      * a suitable Command instance. */
    def genCommand(state: State): Gen[Command] = {
      val incGen = for (v <- arbitrary[Int]) yield Inc(v)
      val decGen = for (v <- arbitrary[Int]) yield Dec(v)
      Gen.oneOf(incGen, decGen, Gen.oneOf(Get, Reset))
    }
    
    // A UnitCommand is a command that doesn't produce a result
    case class Inc(dif: Int) extends UnitCommand {
      def run(sut: Sut): Unit = sut.inc(dif)
    
      def nextState(state: State): State = state + dif
    
      // This command has no preconditions
      def preCondition(state: State): Boolean = true
    
      // This command should always succeed (never throw an exception)
      def postCondition(state: State, success: Boolean): Prop = success
    }
    
    case class Dec(dif: Int) extends UnitCommand {
      def run(sut: Sut): Unit = sut.dec(dif)
    
      def nextState(state: State): State = state - dif
    
      def preCondition(state: State): Boolean = true
    
      def postCondition(state: State, success: Boolean): Prop = success
    }
    

    注意,如果您的参数只是常量而不是变量(就像PIN代码一样),那么您应该在命令中硬编码它们,或者生成整个规范类而不是对象,并从外部传递这些参数。