我在F#中编写了一个大型模块,恰好有一个简单的界面.该模块包含大约1000行代码,50个单元测试,并只导出一个易于理解的功能.
接下来要做的就是编写一个小的fsi文件.这有许多优点,包括防止命名空间污染,为文档提供明显的位置,确保如果有人决定重用内部,他们将有动力干净地将它们分解出来,毫无疑问,许多其他人.我相信我在这里向合唱团讲道,但仍然觉得值得解释为什么我认为有fsi文件是有帮助的.
现在问题.NUnit将不再运行单元测试,谴责声称它们不公开.那么,那将是因为它们不以任何方式成为界面的一部分.我并不特别希望将它们添加到界面中,尽管如此,因为它意味着每次添加另一个测试时都会更新它,并且它会使fsi文件膨胀一个数量级.
我想一个简单的解决方法是将代码移动到其他地方,将其导入到一个很小的.fs文件中,然后转发一个函数.幸运的是,每个人都会认为这只是令人反感.请问有更好的方法吗?
编辑:非常感谢所有回复的人.我赞同这两个答案.我本来想分开赏金,但是因为这似乎不可能(我有点随意)接受Tomas的回答.
如果要添加fsi文件以指定源中模块和函数的可见性,则需要包含应公开访问的所有函数的声明.这意味着如果NUnit要求测试是公共函数,则需要将它们包含在fsi文件中.
但是,还有另一种在F#中指定可见性的方法 - fsi您可以只在声明中添加适当的可见性修饰符,而不是使用文件.这样,您可以隐藏所有实现细节并仅导出main函数和测试:
namespace MyLibrary
open NUnit.Framework
// Implementation details can be in this module
// (which will not be visible outside of the library)
module private Internal =
let foo n = n * 2
let bar n = n + 1
// A public module can contain the public API (and use internal implementation)
module public MyModule =
open Internal
let doWork n = foo (bar n)
// To make the tests visible to NUnit, these can be placed in a public module
// (but they can still access all functions from 'Internal')
module public Tests =
open MyModule
[<Test>]
let ``does work for n = 1``() =
Assert.Equals(doWork 1, 4)
Run Code Online (Sandbox Code Playgroud)
与使用fsi文件相比,这样做的缺点是您没有单独的文件,只能很好地描述API的重要部分.但是,您将获得所需内容 - 隐藏实现细节并仅显示单个函数和测试.
| 归档时间: |
|
| 查看次数: |
1162 次 |
| 最近记录: |