我正在尝试使用scalacheck 1.6.6和specs 1.7(scala 2.8.1)创建一个生成(非零长度)合法unicode字符串的生成器.
我希望我可以创建如下的生成器:
object Generators {
def unicodeChar: Gen[Char] =
choose(Math.MIN_CHAR, Math.MAX_CHAR).map(_.toChar).filter(
c => Character.isDefined(c))
def unicodeStr: Gen[String] = for(cs <- listOf1(unicodeChar)) yield cs.mkString
}
Run Code Online (Sandbox Code Playgroud)
...然后从规格中使用它们:
import org.specs.Specification
import org.specs.matcher.ScalaCheckMatchers
object CoreSpec extends Specification with ScalaCheckMatchers {
"The core" should {
"pass trivially" in {
Generators.unicodeStr must pass((s: String) => s == s)
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,似乎在unicodeChar中使用过滤器会导致问题:
Specification "CoreSpec"
The core should
x pass trivially
Gave up after only 64 passed tests. 500 tests were discarded.
Run Code Online (Sandbox Code Playgroud)
如果我从unicodeChar中删除过滤器,我的测试通过了,但我后来遇到其他问题,因为我的字符串并不总是定义良好的unicode.
提前感谢有关如何实现这一目标的任何建议.
我正在通过阅读 ScalaCheck 的代码来学习 scala,发现许多组合器都以suchThat
. 然而,在很多情况下,这样的做法看起来并不是很有必要。我想知道为什么它们要这样设计。以下是GitHub上的一些摘录:
Example 1.
/** Picks a random value from a list */
def oneOf[T](xs: Seq[T]): Gen[T] =
choose(0, xs.size-1).map(xs(_)).suchThat(xs.contains)
Run Code Online (Sandbox Code Playgroud)
map
从 xs 中选择一个元素,因此xs.contains
看起来是多余的。
--
Example 2.
def containerOfN[C[_],T](n: Int, g: Gen[T])
(implicit evb: Buildable[T,C], evt: C[T] => Traversable[T]): Gen[C[T]] =
sequence[C,T](Traversable.fill(n)(g)) suchThat { c =>
c.size == n && c.forall(g.sieveCopy)
}
Run Code Online (Sandbox Code Playgroud)
c.size == n
既然成功sequence
返回的长度为 n ,为什么需要这样做呢?
--
Example 3.
/** Generates a string of alpha characters */ …
Run Code Online (Sandbox Code Playgroud) 我正在尝试解决两个ScalaCheck(+ specs2)问题:
有没有办法改变ScalaCheck生成的案例数量?
如何生成包含某些Unicode字符的字符串?
例如,我想生成大约10个包含字母数字和Unicode字符的随机字符串.但是,此代码始终生成100个随机字符串,并且它们严格基于字母字符:
"make a random string" in {
def stringGenerator = Gen.alphaStr.suchThat(_.length < 40)
implicit def randomString: Arbitrary[String] = Arbitrary(stringGenerator)
"the string" ! prop { (s: String) => (s.length > 20 && s.length < 40) ==> { println(s); success; } }.setArbitrary(randomString)
}
Run Code Online (Sandbox Code Playgroud)
编辑
我刚才意识到还有另一个问题:
当然,我不想要100,但显然我的代码试图生成一套过于复杂的规则.它最后一次运行,我看到"47次测试后放弃了".
我可以找到许多为发生器设置最大尺寸的示例,但是如何在最小和最大长度之间生成列表?
我正在使用 scalatest 和 scalacheck,也正在使用 FeatureSpec。
我有一个生成器类,它为我生成对象,如下所示:
object InvoiceGen {
def myObj = for {
country <- Gen.oneOf(Seq("France", "Germany", "United Kingdom", "Austria"))
type <- Gen.oneOf(Seq("Communication", "Restaurants", "Parking"))
amount <- Gen.choose(100, 4999)
number <- Gen.choose(1, 10000)
valid <- Arbitrary.arbitrary[Boolean]
} yield SomeObject(country, type, "1/1/2014", amount,number.toString, 35, "something", documentTypeValid, valid, "")
Run Code Online (Sandbox Code Playgroud)
现在,我有了与 FeatureSpec 一起使用的测试类以及运行测试所需的一切。
在这个类中,我有场景,在每个场景中我想生成一个不同的对象。据我了解,生成对象最好使用 forAll 函数,但 forall 不确定会给您带来一个对象,因此您可以添加 minSuccessful(1) 以确保您获得列表 1 obj... 。
我这样做了并且有效:
scenario("some scenario") {
forAll(MyGen.myObj, minSuccessful(1)) { someObject =>
Given("A connection to the system")
loginActions shouldBe 'Connected
When("something")
//blabla …
Run Code Online (Sandbox Code Playgroud) 我正在使用Scalacheck来查找缺陷,作为任务的一部分.令人难以置信的是,我被卡住了,因为它产生了一对非零整数.
从我的IntelliJ工作表,逐字广告:
import org.scalacheck._
import Arbitrary._
import Gen._
import Prop._
implicit lazy val genUnequalIntPairs = for {
i <- Gen.choose(1,1000)
j <- Gen.choose(i+1,1000)
if (i < j)
} yield (i,j)
val kk = forAll (genUnequalIntPairs) {
case (x,y) => println("x =" + x + ", y =" + y)
x == y
}
kk.check
Run Code Online (Sandbox Code Playgroud)
因为,我明确提到所选值的最小值为非零,我不应该在属性中看到任何零,对吧?至少,这是我的理解.但这就是我所看到的:
x =134, y =547
x =0, y =547
x =0, y =0
x =0, y =274
x =0, y =0
x …
Run Code Online (Sandbox Code Playgroud) 我具有以下属性:
import org.scalacheck.Prop.propBoolean
def elementsAreReversed(list: List[Int], reversed: List[Int]): Boolean =
if (list.isEmpty) true else {
val lastIdx = list.size - 1
list.zipWithIndex.forall { case (element, index) =>
element == reversed(lastIdx - index)
}
}
val propReversed = Prop.forAll { list: List[Int] =>
val reversed = list.reverse
if (list.isEmpty)
list == reversed
else {
val hasSameSize = reversed.size == list.size
val hasAllElements = list.forall(reversed.contains)
// It works until I add a label here:
hasSameSize && hasAllElements && elementsAreReversed(list, reversed)
}
Run Code Online (Sandbox Code Playgroud)
如果添加标签,则会中断: …
ScalaCheck的Gen
API 文档解释lazy val sized
:
def size [T](f:(Int)⇒Gen[T]):Gen [T]
创建可以访问其生成大小的生成器
看下面的例子:
import org.scalacheck.Gen.{sized, posNum}
scala> sized( s => { println(s); posNum[Int] })
res12: org.scalacheck.Gen[Int] = org.scalacheck.Gen$$anon$3@6a071cc0
scala> res12.sample
100
res13: Option[Int] = Some(12)
scala> res12.sample
100
res14: Option[Int] = Some(40)
Run Code Online (Sandbox Code Playgroud)
是什么意思generation size
,即上述输出中的100?
如何使用ScalaCheck从一组值(而不是生成器)生成n个唯一值(Gen[List[T]]
)的列表?这篇文章使用Gen[T]*
而不是一组值,我似乎无法重写它以使其工作.
编辑
在@Jubobs的要求下,我现在可耻地展示了我到目前为止所做的一切,揭示了我在使用ScalaCheck时的全新状态:-)
我只是试图取代gs: Gen[T]
重复参数到Set
什么@Eric写的解决方案在这里:
def permute[T](n: Int, gs: Set[T]): Gen[Seq[T]] = {
val perm = Random.shuffle(gs.toList)
for {
is <- Gen.pick(n, 1 until gs.size)
xs <- Gen.sequence[List[T], T](is.toList.map(perm(_)))
} yield xs
}
Run Code Online (Sandbox Code Playgroud)
但是is.toList.map(perm(_))
用红色强调,IntelliJ IDEA告诉我"你应该在盲目(虽然直观)试验和错误之前首先阅读ScalaCheck API",或者"类型不匹配,预期:Traversable [Gen [T]],实际列表[T ]",我不记得了.
我还尝试了其他几种方法,其中大多数我觉得很荒谬(因而不值得发布),最天真的是使用@Eric的(其他有用和整洁的)解决方案:
val g = for (i1 <- Gen.choose(0, myList1.length - 1);
i2 <- Gen.choose(0, myList2.length - 1))
yield new MyObject(myList1(i1), myList2(i2)) …
Run Code Online (Sandbox Code Playgroud) 我在 scalacheck 1.13.3 中遇到了一个奇怪的问题:任意实例A => java.util.Date
根据调用时间生成不同的值。
这是一个具体的、可重现的示例:
import org.scalatest.FunSuite
import org.scalatest.prop.GeneratorDrivenPropertyChecks
import java.util.Date
import org.scalacheck._
class Repr extends FunSuite with GeneratorDrivenPropertyChecks {
implicit val cogenDate: Cogen[Date] = Cogen(_.getTime)
test("reproduce") {
forAll { (s: String, g: String => Date) =>
val d1 = g(s)
Thread.sleep(100)
val d2 = g(s)
assert(d1 === d2)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这失败了。d1
打印和的实际值d2
显示日期确实不同,差异在 100 到 103 毫秒之间。
我猜问题出在我的Cogen
实例上,但我必须承认我不明白为什么。
scalacheck ×10
scala ×9
scalatest ×2
unit-testing ×2
generator ×1
specs ×1
specs2 ×1
testing ×1
unicode ×1
unique ×1