【发布时间】:2019-12-07 08:01:12
【问题描述】:
我正在尝试找出正确的思考方式。我正在尝试在 python 中使用一些函数式编程范例。我知道它不是函数式语言,但概念可以翻译。
假设我有一组函数,例如:
def add(x: int, y: int) -> int:
return x + y
add_one = partial(add, y=1)
add_two = partial(add, y=2)
add_three = partial(add, y=3)
fut = lambda x: add_three(add_one(add_two(x)))
问题是,我是否对被测函数 (fut) 进行单元测试?我会对add_one、add_two 和add_three 进行单元测试吗?
在我看来,add_one 是add 的一部分,这是一个实现细节,但是如果我“完整”地覆盖了add,那么进行单元测试会感觉很奇怪。
让我们将其扩展一分钟,并将其扩展到更现实的系统。
class Save(Protocol):
def __call__(self, x: int): ...
def save_to_disk(x: int, file_name:str) -> None:
"""
Implementation of saving something to a disk
"""
...
save: Save = partial(save_to_disk, file_name="random_file")
def add(x: int, y: int) -> int:
return x + y
add_one = partial(add, y=1)
fut: Save = lambda x: save(add_one(x))
我现在有一个函数来处理 IO 和一些生成要保存的数据的工作。我在这里对fut 进行单元测试吗?我是否认为柯里化只是实现细节并将其留给集成测试?
我对此感到有些迷茫,因为在 OO 世界中,我知道如何使用模拟对其中的一些链接进行单元测试,但它似乎是倒退的,并且违背了一些功能范式以及我正在积极尝试避免的事情玩弄它。
我现在的直觉是,柯里化函数是集成测试,只要所有内容都经过单独测试,显示组件工作,而不是链,我可以留给集成测试,我可以证明整个系统工作正常。
【问题讨论】:
-
您不需要单独对部分应用的柯里化函数进行单元测试。但是,一旦您编写了此类功能(无论是否部分应用),我都会考虑另一个单元的结果并对其进行测试。
-
你在哪里画线我想这将是我的后续问题。如果子函数具有复杂的逻辑,则似乎有很多复制单元测试。而不是像我那样组合函数,我也可以嵌套函数。我一直在尝试接受
Save作为函数参数,并将实现设置为默认值,这样我就可以在测试时将其存根。这就是你处理函数链的方式吗? -
我实际上不会画一条线:如果你对一个柯里化函数进行单元测试,你不需要测试这个函数的部分应用变体。但是,如果您组合函数 - 组合我的意思是组合两个函数以产生另一个函数,那么您也需要测试这个结果函数。因此,接受函数参数的高阶函数必须使用可能传递给它的任何函数进行单元测试。
标签: python unit-testing functional-programming