总结
是否有任何事件可以在每个属性案例之前运行,以便我可以为属性的每次运行运行设置和拆卸?
完整版
我希望能够测试成对的行为,例如“我总是可以获取写入的记录”或“readAllLines 的输出等于 writeAllLines 的输入”和属性。我还希望该属性不关心操作集是如何实现的(即是否需要清理任何资源)。
每次运行的属性都应该
- 独立于其他运行
- 在单次运行中维护操作调用之间的状态
- 不知道操作如何维护状态
- 不是资源泄漏
我正在使用 FsCheck 和 expecto。示例将在 expecto 中,但问题并非特定于框架。
使用基于示例的测试编写这种设置和拆卸非常容易。它们采用可预测的参数集,因此我可以在添加前后事件的包装器中运行它们。
let testWithEnv setup cleanup name test =
let testWrap () =
let (api,env) = setup ()
test api
cleanup env
testCase name testWrap
属性测试无法做到这一点。它们有未知数量的参数,这些参数将主要由随机数据填充。
我可以很容易地应用这组配对行为,但任何创建的资源(如流)都不会被处理。
let testPropertyWithEnv setup cleanup name test =
let testWrap () =
let (api,env) = setup () // this is actually run once,but immutable so the individual runs don't leak state
test api // have to return this to pass along unapplied parameters
testProperty name testWrap
我看过
跑者活动看着 how to run FsCheck tests 最接近的钩子似乎是
-
OnStartFixture
每个测试类只运行一次 -
OnArguments
在每次通过后运行,并可能用于运行清理
还有可以工作的实验性 Model-based testing features。但是,考虑到我只关心操作的外部一致性,这似乎很重。我不想访问后备状态。
放弃和内联我总是可以写
testProperty "name" (fun arg1 arg2 ->
let (api,env) = setup ()
//test code here
cleanup env
)
但我想避免每个属性中的样板文件和支持状态的暴露。
一次性用品一次性物品也没有解决缺少设置挂钩的问题。
更多实践运行循环我研究了在我的包装器中运行属性测试的方法,但最小的运行器 Check.one
用于单个属性,在属性的运行之间没有挂钩。
使包装器懒惰也不起作用testProperty name lazy(testWithSetup)