【问题标题】:What unit testing frameworks are available for F#哪些单元测试框架可用于 F#
【发布时间】:2011-04-14 17:49:16
【问题描述】:

我正在专门寻找能够让我利用该语言独特功能的框架。我知道FsUnit。你会推荐其他东西吗?为什么?

【问题讨论】:

  • 这里也有一些建议:stackoverflow.com/questions/1468772/…
  • 没有时间进行广泛的回答,但是 IIRC 你也可以将 Pex 与 F# 一起使用(我什至问过一次关于它的问题)。我目前最喜欢的是 Xunit。
  • 你是说 Pex 可以生成 F# 代码吗?你能提供一个链接吗?最初,我希望用 F# 编写测试代码,以供测试人员阅读。
  • 这里也有很好的建议:stackoverflow.com/questions/1989487/…

标签: unit-testing f# fsunit f#-unquote


【解决方案1】:

我自己的单元测试库 Unquote 利用 F# quotations 允许您将测试断言编写为简单的、静态检查的 F# 布尔表达式,并自动生成漂亮的逐步测试失败消息。例如,以下失败的 xUnit 测试

[<Fact>]
let ``demo Unquote xUnit support`` () =
    test <@ ([3; 2; 1; 0] |> List.map ((+) 1)) = [1 + 3..1 + 0] @>

产生以下失败消息

Test 'Module.demo Unquote xUnit support' failed: 

([3; 2; 1; 0] |> List.map ((+) 1)) = [1 + 3..1 + 0]
[4; 3; 2; 1] = [4..1]
[4; 3; 2; 1] = []
false

        C:\File.fs(28,0): at Module.demo Unquote xUnit support()

FsUnit 和 Unquote 具有相似的任务:允许您以惯用的方式编写测试,并生成信息丰富的失败消息。但是 FsUnit 实际上只是 NUnit 约束的一个小包装器,它创建了一个 DSL,它将对象构造隐藏在可组合的函数调用之后。但这是有代价的:你失去了断言中的静态类型检查。例如,以下在 FsUnit 中有效

[<Test>]
let test1 () =
    1 |> should not (equal "2")

但是使用 Unquote,您可以获得 F# 的所有静态类型检查功能,因此等效的断言甚至无法编译,从而防止我们在测试代码中引入错误

[<Test>] //yes, Unquote supports both xUnit and NUnit automatically
let test2 () =
    test <@ 1 <> "2" @> //simple assertions may be written more concisely, e.g. 1 <>! "2"
    //           ^^^
    //Error 22 This expression was expected to have type int but here has type string

此外,由于引用能够在编译时捕获有关断言表达式的更多信息,因此失败消息也更加丰富。例如,失败的 FsUnit 断言 1 |&gt; should not (equal 1) 会生成消息

Test 'Test.Swensen.Unquote.VerifyNunitSupport.test1' failed: 
  Expected: not 1
  But was:  1
    C:\Users\Stephen\Documents\Visual Studio 2010\Projects\Unquote\VerifyNunitSupport\FsUnit.fs(11,0): at FsUnit.should[a,a](FSharpFunc`2 f, a x, Object y)
    C:\Users\Stephen\Documents\Visual Studio 2010\Projects\Unquote\VerifyNunitSupport\VerifyNunitSupport.fs(29,0): at Test.Swensen.Unquote.VerifyNunitSupport.test1()

而失败的 Unquote 断言 1 &lt;&gt;! 1 会产生以下失败消息(也请注意更清晰的堆栈跟踪)

Test 'Test.Swensen.Unquote.VerifyNunitSupport.test1' failed: 

1 <> 1
false

    C:\Users\Stephen\Documents\Visual Studio 2010\Projects\Unquote\VerifyNunitSupport\VerifyNunitSupport.fs(29,0): at Test.Swensen.Unquote.VerifyNunitSupport.test1()

当然,从我在这个答案开头的第一个示例中,您可以看到 Unquote 表达式和失败消息是多么丰富和复杂。

在 FsUnit DSL 上使用纯 F# 表达式作为测试断言的另一个主要好处是,它非常适合开发单元测试的 F# 流程。我认为很多 F# 开发人员都是在 FSI 的帮助下开发和测试代码开始的。因此,从临时 FSI 测试转到正式测试非常容易。事实上,除了对 xUnit 和 NUnit 的特殊支持(尽管也支持任何基于异常的单元测试框架),所有 Unquote 操作符也在 FSI 会话中工作。

【讨论】:

  • 我尝试了 Unquote,因为这里有很多赞成票,一周后我就被它卖掉了。到目前为止,我发现了有价值的东西:在 fsi 中编写测试,然后将它们移动到 NUnit;与 NUnit 的集成;测试表达式的强类型(Unquote 发现我的测试只是偶然通过);报价实用程序,例如“eval”。如果您有 Nuget,则可以使用“install-package Unquote”安装 Unquote。
【解决方案2】:

我还没有尝试过Unquote,但我觉得我不得不提到FsCheck: http://fscheck.codeplex.com/ 这是 Haskells QuickCheck 库的一个端口,您无需指定要执行的特定测试,而是指定有关您的函数的哪些属性应该成立。 对我来说,这比使用传统测试要难一些,但是一旦你弄清楚了属性,你就会有更可靠的测试。请阅读介绍:http://fscheck.codeplex.com/wikipage?title=QuickStart&referringTitle=Home

我猜 FsCheck 和 Unquote 的组合是理想的。

【讨论】:

  • 我自己还没有尝试过,但我听说 FsCheck 和 Unquote 确实可以很好地混合在一起。
【解决方案3】:

你可以试试我的单元测试库Expecto;它有一些您可能喜欢的功能:

  • F# 语法,测试作为值;编写普通的 F# 来生成测试
  • 使用内置的 Expect 模块,或像 Unquote 这样的外部库进行断言
  • 默认并行测试
  • 测试您的 Hopac 代码或异步代码; Expecto 始终是异步的
  • 通过 Logary Facade 的可插入日志记录和指标;轻松为构建系统编写适配器,或使用计时机制构建测试执行时间的 InfluxDB+Grafana 仪表板
  • 内置对 BenchmarkDotNet 的支持
  • 内置对 FsCheck 的支持;使使用生成的/随机数据构建测试或构建对象/参与者状态空间的不变模型变得容易

你好世界是这样的

open Expecto

let tests =
  test "A simple test" {
    let subject = "Hello World"
    Expect.equal subject "Hello World" "The strings should equal"
  }

[<EntryPoint>]
let main args =
  runTestsWithArgs defaultConfig args tests

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    相关资源
    最近更新 更多