F# 通过设置和拆卸进行FsCheck 总结
是否有任何事件可以在每个属性案例之前运行,以便我可以为每个属性运行运行安装程序和拆卸 完整版本 我希望能够使用属性测试成对的行为,如“我总是可以获取书面记录”或“readAllLines的输出等于WriteAllines的输入”。我还希望属性不关心操作集是如何实现的(即,是否需要清理任何资源) 属性的每次运行都应F# 通过设置和拆卸进行FsCheck 总结,f#,fscheck,property-based-testing,expecto,F#,Fscheck,Property Based Testing,Expecto,是否有任何事件可以在每个属性案例之前运行,以便我可以为每个属性运行运行安装程序和拆卸 完整版本 我希望能够使用属性测试成对的行为,如“我总是可以获取书面记录”或“readAllLines的输出等于WriteAllines的输入”。我还希望属性不关心操作集是如何实现的(即,是否需要清理任何资源) 属性的每次运行都应 独立于其他运行 在此单一运行中维护操作调用之间的状态 不知道操作如何保持状态 不是资源泄漏 我正在使用FsCheck和Expecto。示例将在Expecto中,但问题并不特定于框架
- 独立于其他运行
- 在此单一运行中维护操作调用之间的状态
- 不知道操作如何保持状态
- 不是资源泄漏
让testWithEnv设置清理名称测试=
让testWrap()=
let(api,环境)=设置()
测试api
净化环境
testCase名称testWrap
属性测试不能做到这一点。他们有数量未知的参数,这些参数大部分都是随机数据
我可以很容易地应用成对的行为集,但是任何创建的资源(如流)都没有被公开
让testPropertyWithEnv设置清理名称测试=
让testWrap()=
let(api,env)=setup()//这实际上只运行一次,但不可变,因此单个运行不会泄漏状态
测试api//必须返回此值才能传递未应用的参数
testProperty名称testWrap
我已经调查过了
跑步项目
查看最近的钩子似乎是
每个测试类只运行一次OnStartFixture
在每次传递后都会运行,可能会运行清理OnArguments
testProperty“name”(趣味arg1 arg2->
let(api,环境)=设置()
//测试代码在这里
净化环境
)
但我想避免在每一个财产中都出现样板戏,避免支持国的曝光
IDisposables
一次性对象也不能解决缺少设置挂钩的问题
更多亲身体验跑步循环
我研究了在包装器中运行属性测试的方法,但是最小的运行程序检查。一个用于单个属性,在属性运行之间没有挂钩
懒散包装
使包装器懒惰也不起作用testProperty name lazy(testWithSetup)
FsCheck中没有任何东西可以帮助您,即使有,我也不认为它会在Expecto中直接暴露出来。我也不认为在FsCheck方面添加内容是那么简单,也就是说,如果你在FsCheck回购协议中提出问题,我很高兴进一步讨论这个问题
在任何情况下,通过巧妙地使用部分应用程序,并以一些简单的样板文件为代价,实际上可以包装“可变”函数,我认为这基本上就是您所要求的
瞧,代码:
//这些类型是为了让签名看起来更漂亮
类型Api=Api
类型Env=Env
设testProperty k=
//使用“随机”参数调用属性
因为我在0..2做什么
k i(字符i)(字符串i)
让安装程序()
printfn“安装程序已运行”
(Api,环境)
让拆卸环境=
打印fn“拆卸运行”
让test0 Api arg1=
printfn“test0%A”arg1
让test1api(arg1:int)(arg2:char)=
printfn“test1%A%A”arg1 arg2
让test2 Api arg1 arg2 arg3=
打印fn“testFun%A%A”arg1 arg2 arg3
让testWithEnv(设置:unit->Api*Env)(拆卸:Env->unit)(测试:Api->a)(k:'a->unit):unit=
let(api,env)=setup()
k(测试api)
拆卸环境
let()(f,k)arg=
f、 (趣味c->k c arg)
let()f arg=
f、 (趣味k->k arg)
让我们运行(f,k)=fk
testProperty(乐趣arg1 arg2 arg3->
testWithEnv安装程序拆卸test2 arg1 arg2 arg3 |>运行
)
这里的想法是使用运算符
和
将任意数量的任何类型的参数串在一起,将其传递给testWithEnv
函数,然后对结果调用run
。基本上需要运算符和run
来建立并应用可变参数列表
它是类型安全的,也就是说,如果您忘记传递参数或参数的类型错误,您将得到一个类型错误,尽管不可否认,它可能不像普通函数应用程序那样清晰
我建议将其粘贴到IDE中并检查类型,这将大大有助于理解正在发生的事情
有一些其他的风格,你可以写这个。例如,使用稍有不同的定义和函数,您可以编写如下内容
let()k arg=
乐趣c->k c参数
让阿格=
乐趣k->k arg
testWithEnv安装程序拆卸test2(arg1 arg2 arg3)
这将运行
功能替换为运行
,只需要一名操作员
。也许还有其他方法可以减少它,选择你的毒药。这是我喜欢的功能社区。总是看到潜在的一般问题。让我们看看我是否做对了。它允许延迟执行任意数量的参数,方法是要求调用方将参数包装在一系列函数元组中,这些元组一次应用一个参数<编码>运行
然后解开链条。这将需要我的每个属性测试嵌套一个testWithE