标签: property-based-testing

如果随机生成的输入无效,我该如何重新尝试基于属性的测试?

我是单元测试的n00b.我已经安装FsCheck.Nunit,并NUnitTestAdapter从的NuGet,我试图做基于属性的测试,主要是由灵感不可估量的斯科特Wlaschin.

我正在使用该[<Property>]属性,我希望能够"跳过"不符合测试要求的输入:

[<Property(MaxTest=10)>]
let ``Calling unzipTo with an invalid destination will yield a failure.`` badDest =
    if Directory.Exists(badDest)
    then // somehow skip to the next randomized input
    else // do the actual test
Run Code Online (Sandbox Code Playgroud)

最简单的方法是什么?

我更喜欢FsCheck/NUnit的答案,如果它存在,但我也会考虑任何其他框架,其测试可以在Visual Studio中运行.(我以为我看到了一个框架,其中有一个简单的函数来完成这个,但我无法弄清楚它是什么.)

到目前为止,我更喜欢FsCheck.NUnit,因为它可以为F#类型(有区别的联合等)生成随机输入而无需额外的工作.

.net f# nunit fscheck property-based-testing

6
推荐指数
1
解决办法
106
查看次数

如果我已经练习了基于示例的测试,为什么还要使用基于属性的测试?

一些开发人员在基于示例的测试中争论 TDD 的一个警告是,可能缺乏所有有效的输入处理。

让我们举一个简单的例子,这些开发人员可能会争论:

编写一个将两个数字相加的程序。

Bob,开发人员开始编写第一个测试:
给定 1 + 3,那么结果是 4
实现:def add(x: Int, y: Int) = 4
很好,通过了。

Now second test:
Given 2 + 2, then result is 4. Implementation still the same: def add(x: Int, y: Int) = 4

So other developers would come and tell him:

"Now you see Bob that Example-based testing is not enough with your poor 2 examples !
You didn't test every output and looking at your actual implementation, it …

testing tdd unit-testing property-based-testing

5
推荐指数
1
解决办法
1841
查看次数

使用scalacheck测试有效的状态转换

假设我有这个课程:

case class Receipt(id: Long, state: String) {
  def transitionTo(newState: String) = {
    if (!canTransitionTo(newState)) {
       throw new IllegalStateExcetion(s"cant transition from $state to $newState")
    }
    this.copy(state = newState)
  }
}
Run Code Online (Sandbox Code Playgroud)

我想canTransitionTo用scalachecks命令测试逻辑(这里不是为了简单起见),但是我在如何开始时遇到了一些麻烦.有任何想法吗?

scala state-machine scalacheck property-based-testing

5
推荐指数
1
解决办法
156
查看次数

如何使用FsCheck生成随机数作为基于属性的测试的输入

我认为现在是时候尝试FsCheck,但事实证明它比我想象的更难.有很多文档Arb,生成器等等,但似乎没有任何关于如何应用这些知识的指导.或者我只是没有得到它.

可能让人更难理解的是,测试,属性,生成器,仲裁,缩小以及在我的情况下,随机性(一些测试自动生成随机数据,其他测试没有)之间的关系对我来说并不清楚.我没有Haskell背景,所以也没有多大帮助.

现在问题是:如何生成随机整数?

我的测试场景可以用乘法的属性来解释,比如分配:

static member  ``Multiplication is distributive`` (x: int64) y z =
    let res1 = x * (y + z)
    let res2 = x * y + x * z

    res1 = res2

// run it:
[<Test>]
static member FsCheckAsUnitTest() =
    Check.One({ Config.VerboseThrowOnFailure with MaxTest = 1000 }, ``Multiplication is distributive``)
Run Code Online (Sandbox Code Playgroud)

当我使用Check.Verbose或NUnit集成运行时,我得到的测试序列如下:

0:
(-1L, -1L, -1L)
1:
(-1L, -1L, 0L)
2:
(-1L, -1L, -1L)
3:
(-1L, -1L, -1L)
4:
(-1L, 0L, -1L)
5:
(1L, …
Run Code Online (Sandbox Code Playgroud)

f# unit-testing fscheck property-based-testing

5
推荐指数
1
解决办法
646
查看次数

使用嵌套 forAll 在 ScalaCheck 中的生成对象之间共享元素

最近开始在 Scala 中编码,我尝试编写一些基于属性的测试用例。在这里,我试图生成模仿我正在测试的系统的原始数据。目标是首先生成基本元素(ctrlidz),然后使用这些值生成两个类(A1B1),最后检查它们的属性。我首先尝试了以下方法 -

import org.scalatest._
import prop._
import scala.collection.immutable._
import org.scalacheck.{Gen, Arbitrary}

case class A(
    controller: String,
    id: Double,
    x: Double
)

case class B(
    controller: String,
    id: Double,
    y: Double
)

object BaseGenerators {
    val ctrl = Gen.const("ABC")
    val idz = Arbitrary.arbitrary[Double]
}

trait Generators {
    val obj = BaseGenerators

    val A1 = for {
        controller <- obj.ctrl
        id <- obj.idz
        x <- Arbitrary.arbitrary[Double]
    } yield A(controller, id, x)

    val …
Run Code Online (Sandbox Code Playgroud)

testing scala scalatest scalacheck property-based-testing

5
推荐指数
1
解决办法
589
查看次数

如何更改假设生成的最大测试用例数?

著名的基于属性的测试框架假设能够生成大量的测试用例。

但有没有办法限制假设生成的测试用例的数量,从而缩短测试周期呢?

例如,将特定的关键字参数提供给@given装饰器?

python automated-tests property-based-testing python-hypothesis

5
推荐指数
1
解决办法
1740
查看次数

在实现基于属性的测试时,何时应该在前置条件表达式上使用输入生成器?

在实现基于属性的测试时,何时应该在前置条件表达式上使用输入生成器?

选择特定选项时是否存在性能因素?

在内部,一种方法是否不可避免地使用另一种方法?

我认为与输入生成器相比,前置条件表达式需要更长的时间才能执行.有没有人测试过这个?

为什么我们需要两者?

f# fscheck property-based-testing

4
推荐指数
1
解决办法
171
查看次数

生成字符串时,Expecto FsCheck会出现堆栈溢出异常

我正在努力学习如何正确使用FsCheck,并将其与Expecto集成.如果我使用默认的FsCheck配置,我可以运行属性测试,但是当我尝试使用自己的Generator时,它会导致堆栈溢出异常.

这是我的发电机

type NameGen() =
    static member Name() =
        Arb.generate<string * string>
        |> Gen.where (fun (firstName, lastName) ->
            firstName.Length > 0 && lastName.Length > 0
        )
        |> Gen.map (fun (first, last) -> sprintf "%s %s" first last)
        |> Arb.fromGen
        |> Arb.convert string id
Run Code Online (Sandbox Code Playgroud)

而我正试图像这样使用它:

let config = { FsCheckConfig.defaultConfig with arbitrary = [typeof<NameGen>] }

let propertyTests input =
    let output = toInitials input
    output.EndsWith(".")

testPropertyWithConfig config "Must end with period" propertyTests
Run Code Online (Sandbox Code Playgroud)

在它进入Gen.where函数之前抛出异常

我究竟做错了什么?谢谢

f# fscheck property-based-testing expecto

4
推荐指数
1
解决办法
163
查看次数

FsCheck:如何生成依赖于其他测试数据的测试数据?

FsCheck具有一些简洁的默认Arbitrary类型来生成测试数据。但是,如果我的一个考试日期取决于另一个考试日期怎么办?

例如,考虑一下string.Substring()结果子字符串的属性永远不能长于输入字符串:

[Fact]
public void SubstringIsNeverLongerThanInputString()
{
    Prop.ForAll(
        Arb.Default.NonEmptyString(),
        Arb.Default.PositiveInt(),
        (input, length) => input.Get.Substring(0, length.Get).Length <= input.Get.Length
    ).QuickCheckThrowOnFailure();
}
Run Code Online (Sandbox Code Playgroud)

尽管Substring当然实现是正确的,但此属性会失败,因为最终PositiveInt会生成比生成的结果更长的a,NonEmptyString从而导致异常。

收缩:NonEmptyString“ a” PositiveInt 2,但例外:System.ArgumentOutOfRangeException:索引和长度必须引用字符串中的位置。

我可以if (input.Length < length) return true;用来保护比较,但是那样的话,即使没有检查该属性,我也会进行大量测试。

如何告诉FsCheck仅生成PositiveInt不超过输入字符串的?我想我必须使用Gen<T>该类,但是它的接口让我感到困惑……我尝试了以下操作,但仍然PositiveInt超出了字符串:

var inputs = Arb.Default.NonEmptyString();
// I have no idea what I'm doing here...
var lengths = inputs.Generator.Select(s => s.Get.Length).ToArbitrary();

Prop.ForAll(
    inputs,
    lengths,
    (input, length) => input.Get.Substring(0, length).Length <= input.Get.Length
).QuickCheckThrowOnFailure();
Run Code Online (Sandbox Code Playgroud)

c# fscheck property-based-testing

4
推荐指数
1
解决办法
429
查看次数

是否有更简单的方法来使用 Kotest 基于属性的测试来测试所有排列?

我正在使用 kotlin + Kotest 属性测试,并尝试使用列表生成器测试 2 个参数的所有排列,如下所示:

"Some test"{
        forAll(4 ,
                Exhaustive.collection(listOf(
                        "a",
                        "b")),
                Exhaustive.collection(listOf(
                        "1",
                        "2"))
        { begins_with, contains ->
            println("$begins_with:$contains")
            ... some validation code...
        }
Run Code Online (Sandbox Code Playgroud)

我希望使用穷举生成器能够以这样的方式生成它们:通过 4 次迭代,所有可能的排列都将被覆盖。像这样:

a:1
b:2
a:2
b:1
Run Code Online (Sandbox Code Playgroud)

相反,详尽的生成器总是按照列出的顺序排列,如下所示:

a:1
b:2
a:1
b:2
Run Code Online (Sandbox Code Playgroud)

这意味着我正在多次测试同一个案例。

我尝试过将一些生成器切换到 Arb,这确实会切换顺序,但不是最佳状态。为了增加命中所有情况的可能性,我必须进行比使用正确顺序时更多的测试。

我也考虑过像这样多次列出相同的元素

"Some test"{
        forAll(4 ,
                Exhaustive.collection(listOf(
                        "a",
                        "b")),
                Exhaustive.collection(listOf(
                        "1",
                        "1",
                        "2",
                        "2"))
        { begins_with, contains ->
            println("$begins_with:$contains")
            ... some validation code...
        }
Run Code Online (Sandbox Code Playgroud)

但这似乎不可持续,尤其是当我想稍后添加更多参数或值时。

有没有办法生成详尽的排列,而不是继续循环每个列表?

kotlin property-based-testing kotlintest kotest

4
推荐指数
1
解决办法
1463
查看次数