Using F# for testing

https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/posts/low-risk-ways-to-use-fsharp-at-work-3.html

如果您想在不接触核心代码的情况下开始使用 F# 编写有用的代码,那么编写测试是一个很好的开始方式。

F# 不仅具有更紧凑的语法,而且还具有许多不错的功能,例如“双反引号”语法,可使测试名称更具可读性。

与本系列中的所有建议一样,我认为这是一个低风险的选择。测试方法往往很简短,因此几乎任何人都可以阅读它们而无需深入了解 F#。在最坏的情况下,您可以轻松地将它们移植回 C#。

10. 使用 F# 编写具有可读名称的单元测试

The code for this section is available on githubarrow-up-right.

就像 C# 一样,F# 可用于使用 NUnit、MsUnit、xUnit 等标准框架编写标准单元测试。

下面是为与 NUnit 一起使用而编写的测试类的示例。

[<TestFixture>]
type TestClass() = 

    [<Test>]
    member this.When2IsAddedTo2Expect4() = 
        Assert.AreEqual(4, 2+2)

如您所见,有一个具有 TestFixture 属性的类和一个具有 Test 属性的 public void 方法。都非常标准。

但是,当您使用 F# 而不是 C# 时,您会得到一些不错的附加功能。首先,您可以使用双反引号语法来创建更具可读性的名称,其次,您可以在模块而不是类中使用 let 绑定函数,从而简化代码。

[<Test>]
let ``When 2 is added to 2 expect 4``() = 
    Assert.AreEqual(4, 2+2)

双反引号语法使测试结果更易于阅读。这是具有标准类名的测试输出:

与使用更友好名称的输出的对比:

因此,如果您想编写非程序员也可以看懂的测试名称,请试试 F#!

11. 使用 F# 以编程方式运行单元测试

通常,你可能想以编程方式运行单元测试。这可能是出于各种原因,如使用自定义过滤器,或做自定义日志,或不想在测试机器上安装NUnit。

一种简单的方法是使用 Fuchu库(译:停止更新于Nov 24, 2020,我看到这里有点不想继续翻了,这都什么啊,啥啥都是过期的,啥啥都是无人更新的,啥啥都是过期的),它可以让您直接组织测试,尤其是参数化测试,而无需任何复杂的测试属性。

这是一个例子:

您可以使用如下代码直接在 F# 交互式中运行这些测试:run simpleTest

您还可以将这些测试组合成一个或多个列表,或列表的分层列表:

The code above is available on githubarrow-up-right.

最后,有了 Fuchu,测试组件就变成了自己的测试运行器。只需将程序集设为控制台应用程序而不是库并将此代码添加到 program.fs 文件:

More on Fuchu herearrow-up-right.

Using the NUnit test runner

如果您确实需要使用现有的测试运行器(例如 NUnit 测试运行器),那么将一个简单的脚本放在一起来执行此操作非常简单。

我在下面使用 Nunit.Runners 包做了一个小例子。

好吧,这可能不是最令人兴奋的 F# 用法,但它确实展示了 F# 的“对象表达式”语法来创建 NUnit.Core.EventListener 接口,所以我想我应该把它作为演示。

The code above is available on githubarrow-up-right.

12. Use F# to learn to write unit tests in other ways

上面的单元测试代码我们都很熟悉,但是还有其他的方式来编写测试。学习以不同的风格编写代码是将一些新技术添加到您的技能库和扩展您的一般思维的好方法,所以让我们快速浏览一下其中的一些。

首先是 FsUnit,它用更流畅和惯用的方法(自然语言和管道)取代了 Assert。

这是一个片段:

The above code is available on githubarrow-up-right.

Unquote使用的是一种非常不同的方法。Unquote的方法是将任何F#表达式包裹在F#引号中,然后对其进行评估。如果一个测试表达式抛出了一个异常,测试就会失败,并且不仅打印出这个异常,还打印出到异常发生时的每一步。这些信息有可能让你对断言失败的原因有更多的了解。(译:这个库也停更了)

这是一个非常简单的例子:

还有一些快捷运算符,例如 =?和 >?这使您可以更简单地编写测试 - 没有任何地方断言!

The above code is available on githubarrow-up-right.

13. Use FsCheck to write better unit tests(该库最后一次更新在Nov 7, 2022,不翻译该部分)

14. Use FsCheck to create random dummy data(该库最后一次更新在Nov 7, 2022,不翻译该部分)

15. Use F# to create mocks

如果您使用 F# 为用 C# 编写的代码编写测试用例,您可能希望为接口创建模拟和存根。

In C# you might use Moqarrow-up-right or NSubstitutearrow-up-right. In F# you can use object expressions to create interfaces directly, or the Foq libraryarrow-up-right.

在 C# 中,您可以使用 Moqarrow-up-rightNSubstitutearrow-up-right。在 F# 中,您可以使用对象表达式直接创建接口,也可以使用 Foq 库。(也停更了Jun 29, 2018)

两者都很容易用,而且方式类似于Moq.

这是 C# 中的一些 Moq 代码:

下面是 F# 中等效的 Foq 代码:

有关 F# 中使用 Mock 的更多信息,请参阅:

And you need to mock external services such as SMTP over the wire, there is an interesting tool called mountebankarrow-up-right, which is easy to interact with in F#arrow-up-right.

16. Use F# to do automated browser testing(TODO:未来再翻,这段好无聊)

In addition to unit tests, you should be doing some kind of automated web testing, driving the browser with Seleniumarrow-up-right or WatiNarrow-up-right.

But what language should you write the automation in? Ruby? Python? C#? I think you know the answer!

To make your life even easier, try using Canopyarrow-up-right, a web testing framework built on top of Selenium and written in F#. Their site claims "Quick to learn. Even if you've never done UI Automation, and don't know F#.", and I'm inclined to believe them.

Below is a snippet taken from the Canopy site. As you can see, the code is simple and easy to understand.

Also, FAKE integrates with Canopy, so you can run automated browser tests as part of a CI buildarrow-up-right.

17. Use F# for Behaviour Driven Development(TODO:未来再翻,这段也好无聊,说实话我在现在的网上就没见过讨论BDD的,能给点案例么)

The code for this section is available on githubarrow-up-right.

If you're not familiar with Behaviour Driven Development (BDD), the idea is that you express requirements in a way that is both human-readable and executable.

The standard format (Gherkin) for writing these tests uses the Given/When/Then syntax -- here's an example:

If you are using BDD already with .NET, you're probably using SpecFlowarrow-up-right or similar.

You should consider using TickSpecarrow-up-right instead because, as with all things F#, the syntax is much more lightweight.

For example, here's the full implementation of the scenario above.

The C# equivalent has a lot more clutter, and the lack of double backtick syntax really hurts:

Examples taken from the TickSpecarrow-up-right site.

Summary of testing in F#

您当然可以结合我们迄今为止所见的所有测试技术(as this slide deck demonstratesarrow-up-right):

  • 单元测试(FsUnit、Unquote)和基于属性的测试(FsCheck)。【停更一堆】

  • 由浏览器自动化 (Canopy) 驱动的用 BDD (TickSpec) 编写的自动化验收测试(或至少是冒烟测试)。

  • 两种类型的测试都在每个构建上运行(使用 FAKE)。

那里有很多关于测试自动化的建议,您会发现很容易将概念从其他语言移植到这些 F# 工具。玩得开心!

Last updated