我正在使用尚未发布的书“F#Deep Dives Version 12”中提出的NUnit测试技术(第2.2节“添加测试”)
以下代码使用 MEMOIZE 定义/未定义执行精细编译或交互。但是,从GUI NUnit执行单元测试可以正常工作 MEMOIZE 未定义,但是当定义 MEMOIZE 时,它会因“空引用异常”而失败。注意memorize()使用 Closure 。我怀疑发生了异常,因为当NUnit启动时,编译器生成的某些初始化代码没有被执行。你觉得怎么样?
open System
open System.Collections.Generic
open NUnit.Framework
open FsUnit
let memoize (f: 'T -> 'U) =
let t = new Dictionary<'T, 'U>(HashIdentity.Structural)
fun n ->
if t.ContainsKey n then t.[n]
else let res = f n
t.Add(n, res)
res
//TODO: Insure J>0 & K>0 & J<K
let isMult =
#if MEMOIZE
memoize (fun (j,k) -> k % j = 0)
#else
(fun (j,k) -> k % j = 0)
#endif
type ``Given the isMult function``() =
[<TestCase(3,1,false)>]
[<TestCase(3,2,false)>]
[<TestCase(3,3,true)>]
[<TestCase(5,10,true)>]
[<TestCase(3,15,true)>]
[<TestCase(5,13,false)>]
[<TestCase(5,15,true)>]
member t.``the result is calculated correctly``(j, k, expected) =
let actual = isMult (j,k)
actual |> should equal expected
更新
独立的NUnit应用程序是版本2.6.3.13283。
“FinnNk”给了我一个主意!我安装了Nuget包“NUnitTestAdapter”。现在我可以在VS 2013中直接测试。但是,没有惊喜。当MEMORIZE未定义时,我将所有测试设为“绿色”,并且在定义时,所有测试都为“红色”。
异常仍然相同:“空引用异常”。但是,现在它在IDE中执行,我可以让调试器停止在异常上。到目前为止我在断点处可以确定的是它需要以下符号:
C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.pdb
我安装了新的VS 2015预览版。在那种环境中没有任何不同。既然.NET Framework是开源的,也许我可以使用“mscorlib”的源代码精确地将调试器归零。
答案 0 :(得分:0)
您是否在多个线程中运行NUnit测试?普通字典不是线程安全的,因此可能会发生奇怪的事情。如果你使用ConcurrentDictionary,它会给出相同的结果吗?
let memoize (f: 'T -> 'U) =
let t = System.Collections.Concurrent.ConcurrentDictionary<'T, 'U>()
fun n -> t.GetOrAdd(n, f)