我最初尝试创建一个固定前5个元素的生成器(并且在使用Prop.forAll
前五个元素的任何测试中总是会运行),但是这样做失败了.
现在我试图通过为一个范围内的随机数据生成一个生成器,并为非随机数据生成一个生成器(即固定序列)来简化此操作.它类似于Gen.constant
,除了代替一个值,它是一系列值.
我有这个(简化的可重现的例子,适用于NUnit和xUnit):
[<Property(Verbose = true, MaxTest=5)>]
static member MultiplyIdentityCornerCases () =
Gen.elements [0L; -1L; 1L; Int64.MinValue; Int64.MaxValue]
|> Arb.fromGen
|> Prop.forAll <| fun x -> x = x * 1L
Run Code Online (Sandbox Code Playgroud)
输出是(不知道null
它来自哪里):
0:
<null>
9223372036854775807L
1:
<null>
-9223372036854775807L
2:
<null>
-9223372036854775807L
3:
<null>
1L
4:
<null>
-9223372036854775807L
Ok, passed 5 tests.
Run Code Online (Sandbox Code Playgroud)
我希望输出包含序列中的所有五个测试,最好是但不一定按顺序排列.我知道我可以使用测试数据提供程序使用NUnit(或任何单元测试系统),但我想知道我是否可以使用FsCheck(或者我是否应该这样做,也许这是一个坏主意).
我认为使用FsCheck是有用的,对于有多个函数参数的情况,我希望它能够详尽地测试我提供的极端情况参数的所有组合.使用FsCheck比使用testdata提供程序更容易.
我不知道那是可能的,但你可以这样做:
open System
open FsCheck
open FsCheck.Xunit
[<Property>]
let MultiplyIdentityCornerCases () =
Gen.oneof [
Gen.elements [Int64.MinValue; -1L; 0L; 1L; Int64.MaxValue]
Arb.generate ]
|> Arb.fromGen
|> Prop.forAll <| fun x -> x = x * 1L
Run Code Online (Sandbox Code Playgroud)
传递两个生成器Gen.oneof
,因此每个生成器将生成大约一半的值.
Gen.elements
应该从所提供的序列中的所有值中均匀地选取,因此它将使用例如0L
20%的时间,但仅在Gen.oneof
使用时的一半Gen.elements
.
换句话说,每个'特殊'值将产生50%*20%= 10%的时间.
默认情况下,属性运行100个测试用例,因此平均而言,它应生成10个0L
值,10个Int64.MinValue
值,依此类推.这通常应该足够好.
如果不是,您可以随时执行以下操作:
open System
open Xunit
open FsCheck
open FsCheck.Xunit
open Swensen.Unquote
[<Theory>]
[<InlineData(Int64.MinValue)>]
[<InlineData(-1L)>]
[<InlineData( 0L)>]
[<InlineData( 1L)>]
[<InlineData(Int64.MaxValue)>]
let MultiplyIdentityCornerCases x = x =! x * 1L
[<Property>]
let MultiplyIdentityCornerCasesProperty x =
MultiplyIdentityCornerCases x
Run Code Online (Sandbox Code Playgroud)
在这里,您使用xUnit.net的[<Theory>]
功能定义参数化测试,并将其提供给您关注的五个角落案例.运行测试时,测试运行器将运行这五个测试用例.
此外,它会运行,MultiplyIdentityCornerCasesProperty
因为它带有注释[<Property>]
,该函数只调用另一个函数.
归档时间: |
|
查看次数: |
251 次 |
最近记录: |