在F#(以及大多数函数式语言)中,某些代码非常短,如下所示:
let f = getNames
>> Observable.flatmap ObservableJson.jsonArrayToObservableObjects<string>
或:
let jsonArrayToObservableObjects<'t> =
JsonConvert.DeserializeObject<'t[]>
>> Observable.ToObservable
最后一个基于属性的测试我最终用于后一个函数:
testList "ObservableJson" [
testProperty "Should convert an Observable of `json` array to Observable of single F# objects" <| fun _ ->
//--Arrange--
let (array , json) = createAJsonArrayOfString stringArray
//--Act--
let actual = jsonArray
|> ObservableJson.jsonArrayToObservableObjects<string>
|> Observable.ToArray
|> Observable.Wait
//--Assert--
Expect.sequenceEqual actual sArray
]
无论安排部分如何,测试都不仅仅是被测功能,因此它比被测功能更难阅读!
另一方面:
答案 0 :(得分:1)
取决于您对功能编程的定义&#39;是。或者甚至更精确 - 你想要与功能编程的起源保持多近 - 数学具有广义和狭义的含义。
让我们采取一些与编程相关的东西。说,映射理论。你的问题可以用这样的方式翻译:从A到B的双射,以及从B到C的双射,我是否应该证明这两者的构成也是双射?答案是双重的:你绝对应该,而且你只做一次:你的证明足以涵盖所有可能的案例。
回归编程,这意味着必须仅对管道衬里进行一次测试(证明) - 我想这是在部署到生产之前。由于您作为程序员的工作来创建具有这种质量的函数(映射),由管道运算符或其他任何东西组成,保留所需的属性。再一次,坚持使用通用参数而不是写大量类似的测试会更好。
所以,最后,我们得出一个更有价值的问题:如何保证某些操作可以保留一些财产?事实证明,承认这一事实的最简单方法是处理来自伟大的Haskell的Monoid
类型:例如,Monoind
代表任何关联二进制文件操作A -> A -> A
以及类型A
的一些标识元素。拥有这样的通用容器是非常有利可图的,并且是明确知道代码设计的内容和方式的明确方式。
答案 1 :(得分:0)
我个人不会测试它。
事实上,对测试的需求较少,而更多地依赖更严格的编译器规则,无副作用函数,不变性等是我更喜欢F#而不是C#的一个主要原因。
当然,我继续(单位)测试&#34;自定义逻辑&#34; ...例如算法代码