Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 通过设置和拆卸进行FsCheck 总结_F#_Fscheck_Property Based Testing_Expecto - Fatal编程技术网

F# 通过设置和拆卸进行FsCheck 总结

F# 通过设置和拆卸进行FsCheck 总结,f#,fscheck,property-based-testing,expecto,F#,Fscheck,Property Based Testing,Expecto,是否有任何事件可以在每个属性案例之前运行,以便我可以为每个属性运行运行安装程序和拆卸 完整版本 我希望能够使用属性测试成对的行为,如“我总是可以获取书面记录”或“readAllLines的输出等于WriteAllines的输入”。我还希望属性不关心操作集是如何实现的(即,是否需要清理任何资源) 属性的每次运行都应 独立于其他运行 在此单一运行中维护操作调用之间的状态 不知道操作如何保持状态 不是资源泄漏 我正在使用FsCheck和Expecto。示例将在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