unit-testing - 什么是针对 F# 中的 nan 值进行属性测试的简洁通用方法?

标签 unit-testing f# fscheck

我正在使用 FsCheck 在 F# 中进行一些属性测试。因此,我希望保证某些条件始终成立,无论输入参数如何。

考虑我为 float 定义了一个平凡的恒等函数。值(value)观。

let floatId (x : float) = x

然后我定义了一个我知道应该始终持有的函数的测试:
let ``floatId returns input float`` x = floatId x = x

这是一个微不足道的测试,我只是检查调用我的浮点标识函数是否返回与输入浮点数相同的结果。

然后我将此函数插入​​ FsCheck:
Check.Quick ``floatId returns input float``

不幸的是,这个属性测试失败了!

Falsifiable, after 21 tests (0 shrinks) (StdGen (1872424299,296201373)):
Original: 
nan


当然,回头看,很明显这会发生,我们知道 nan <> nan .

由于 F# 中的结构比较,这也可能会困扰(稍微)更复杂的涉及集合的测试用例。

如果我为 float 列表设计类似的功能:
let listFloatId (lst : float list) = lst

let ``listFloatId returns input float list`` lst = listFloatId lst = lst

Falsifiable, after 6 tests (3 shrinks) (StdGen (1874889363,296201373)):
Original:
[nan; 2.0; 2.25; 4.940656458e-324]
Shrunk:
[nan]


又是同样的问题!

显然,我可以通过创建自己的相等测试函数来解决这个问题,这对 float 来说很好。值,但扩展到像 list 这样的集合变得更加复杂因为我必须开始使用 List.forall2使用我的自定义相等函数,并且通常将我的代码专门用于每个单独的集合类型。

在 F# 中是否有解决此问题的一般方法?

最佳答案

您可以使用 LanguagePrimitives.GenericEqualityER 解决此问题。功能。这使用等价关系语义检查相等性。这个函数其实是网站比较的具体例子[nan]列表。

测试用例可以这样定义:

let ``ER : floatId returns input float`` x = LanguagePrimitives.GenericEqualityER (floatId x)  x

let ``ER : listFloatId returns input float list`` lst = LanguagePrimitives.GenericEqualityER (listFloatId lst)  lst

这次:

Ok, passed 100 tests.
Ok, passed 100 tests.


(我问并回答了这个问题,因为上述属性是在 FSharp Software Foundation Slack channel 中提出的,我认为将此解决方案记录在案会很有用。除了文档之外,我几乎找不到在线提及此功能在 LanguagePrimitives 模块上)。

关于unit-testing - 什么是针对 F# 中的 nan 值进行属性测试的简洁通用方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39347761/

相关文章:

swift - 单元测试单元格为零

unit-testing - 单元测试示例?

java - 为 Maven 插件运行单元测试时抛出异常 - ComponentLookupException::NoSuchElementException::RepositorySystem

asynchronous - AsyncSeq 未在交互式中打印到控制台

java - 这是 HashMap 的有效单元测试吗?

generics - F# 泛型编程 - 使用成员

f# - F# 中的不可变 Trie 结构

f# - FsCheck DataGen 为空

.net - FsCheck 和 NUnit 集成

f# - 使用 FsCheck 生成记录