避免X& Y问题,一点背景:
我正在尝试建立一个Web项目,我将要复制业务逻辑服务器和客户端,客户端显然是在Javascript和Scala中的服务器。我计划在Cucumber中编写业务逻辑,这样我就可以确保测试和功能在双方都排成一行。最后,我想把ScalaCheck和JSCheck引入这个,生成输入数据而不是指定。
基本上,这些陈述的工作原理如下:
给定语句选择添加生成器。 当语句指定函数按顺序对这些值起作用时。 然后语句获取输入数据和最终结果数据并运行属性。
目标是使这类事物可组合,这样你就可以指定几个生成器,一组在每个生成器上运行的动作,然后是一组属性,每个属性都可以在输入和结果上运行。
已经在Javascript(技术上是Coffeescript)中完成了这一点,当然使用动态语言也很简单。基本上我想在scala步骤定义中做的就是这样,原谅任意测试数据:
class CucumberSteps extends ScalaDsl with EN
with ShouldMatchers with QuickCheckCucumberSteps {
Given("""^an list of integer between 0 and 100$""") {
addGenerator(Gen.containerOf[List, Int](Gen.choose(0,100)))
}
Given("""^an list of random string int 500 and 700$""") {
addGenerator(Gen.containerOf[List, Int](Gen.choose(500,700)))
}
When("""^we concatenate the two lists$""") {
addAction {(l1: List[Int], l2: List[Int]) => l1 ::: l2 }
}
Then("""^then the size of the result should equal the sum of the input sizes$""") {
runProperty { (inputs: (List[Int], List[Int]), result: (List[Int])) =>
inputs._1.size + inputs._2.size == result._1.size
}
}
}
所以我想要做的关键是创建一个特性QuickCheckCucumberSteps,它将是API,实现addGenerator,addAction和runProperty。
到目前为止,我已经粗暴地讨论了这个问题,以及我遇到的问题:
trait QuickCheckCucumberSteps extends ShouldMatchers {
private var generators = ArrayBuffer[Gen[Any]]()
private var actions = ArrayBuffer[""AnyFunction""]()
def addGenerator(newGen: Gen[Any]): Unit =
generators += newGen
def addAction(newFun: => ""AnyFunction""): Unit =
actions += newFun
def buildPartialProp = {
val li = generators
generators.length match {
case 1 => forAll(li(0))_
case 2 => forAll(li(0), li(1))_
case 3 => forAll(li(0), li(1), li(2))_
case 4 => forAll(li(0), li(1), li(2), li(3))_
case _ => forAll(li(0), li(1), li(2), li(3), li(4))_
}
}
def runProperty(propertyFunc: => Any): Prop = {
val partial = buildPartialProp
val property = partial {
??? // Need a function that takes x number of generator inputs,
// applies each action in sequence
// and then applies the `propertyFunc` to the
// inputs and results.
}
val result = Test.check(new Test.Parameters.Default {},
property)
result.status match {
case Passed => println("passed all tests")
case Failed(a, l) => fail(format(pretty(result), "", "", 75))
case _ => println("other cases")
}
}
}
我的关键问题是,我想让注释块成为一个函数,它接受所有添加的操作,按顺序应用它们然后运行并返回属性函数的结果。这是否可以用Scala的类型系统表达,如果是这样,我该如何开始?很高兴阅读并获得这个,但我至少需要前进的方式,因为我不知道如何表达它。如果我想在这里做的不明确,请高兴我的Javascript代码。
答案 0 :(得分:0)
如果我是你,我不会把ScalaCheck生成器代码放在你的Cucumber Given / When / Then语句中:)。 ScalaCheck api调用是“测试装备”的一部分 - 所以没有经过测试。试试这个(未编译/测试):
class CucumberSteps extends ScalaDsl with EN with ShouldMatchers {
forAll(Gen.containerOf[List, Int](Gen.choose(0,100)),
Gen.containerOf[List, Int](Gen.choose(500,700)))
((l1: List[Int], l2: List[Int]) => {
var result: Int = 0
Given(s"""^a list of integer between 0 and 100: $l1 $""") { }
Given(s"""^a list of integer between 0 and 100: $l2 $""") { }
When("""^we concatenate the two lists$""") { result = l1 ::: l2 }
Then("""^the size of the result should equal the sum of the input sizes$""") {
l1.size + l2.size == result.size }
})
}