gpt4 book ai didi

python - 如何对设置内部数据但不返回的方法进行单元测试?

转载 作者:太空狗 更新时间:2023-10-29 20:49:13 26 4
gpt4 key购买 nike

据我所知,单元测试应该一次只测试一个函数/方法。但是我不清楚如何测试只设置没有返回值的内部对象数据的方法,比如下面的 Python 类中的 setvalue() 方法(这是更复杂的简单表示):

class Alpha(object):

def __init__(self):
self.__internal_dict = {}

def setvalue(self, key, val):
self.__internal_dict[key] = val

def getvalue(self, key):
return self.__internal_dict[key]

如果单元测试法规定我们应该测试每个函数,一次一个,那么我该如何单独测试 setvalue() 方法?一种“解决方案”是将我传递给 setvalue() 的内容与 getvalue() 的返回值进行比较,但是如果我的断言失败,我不知道哪个方法失败了——是 setvalue() 还是 getvalue()?另一个想法是将我传递给 setvalue() 的内容与对象的私有(private)数据 __internal_dict[key] 进行比较——一个巨大的令人作呕的 hack!

截至目前,这是我针对此类问题的解决方案,但如果出现断言,那只会表明我的 2 个主要方法中的 1 个无法正常工作。

import pytest

def test_alpha01():
alpha = Alpha()
alpha.setvalue('abc', 33)

expected_val = 33
result_val = alpha.getvalue('abc')

assert result_val == expected_val

感谢帮助

最佳答案

误解

你在这里遇到的真正问题是你在一个错误的前提下工作:

If unit test law dictates that we should test every function, one at a time...

这根本不是什么好的单元测试。

好的单元测试是将您的代码分解为逻辑组件,将它们置于受控环境中并测试它们的实际行为是否符合它们的预期行为 - 来自消费者的观点

这些“单元”可能是(取决于您的环境)匿名函数、单个类或紧密耦合类的集群(并且不要让任何人告诉您类耦合本质上是不好的;有些类被设计成一起去).

重要的是要问自己 - 消费者关心什么

他们当然关心的是 - 当他们调用 set 方法时 - 设置了一些他们甚至无法访问的内部私有(private)成员。

解决方案

从天真地看,从您的代码来看,消费者似乎关心的是当他们为特定键调用 setvalue 时,为同一键调用 getvalue返回他们输入的值。如果这是单元(类)的预期行为,那么这就是您应该测试的内容。

只要行为正确,没有人应该关心幕后发生的事情。

但是,我还会考虑这是否真的是这个类的全部目的 - 这个值还有什么影响?从你问题中的例子中不可能说出来,但不管它是什么,也应该进行测试。

或者,如果这很难定义,那么这个类本身并不是很有意义,您的“单元”实际上应该是一组独立的小类,只有当它们放在一起时才真正具有有意义的行为,并且应该是如此测试。

不过,这里的平衡很微妙,如果没有更多背景信息,很难做到不那么隐晦。

陷阱

您当然不应该(永远永远)做的是让您的测试围绕对象的内部状态进行检查。这有两个非常重要的原因:

首先,如前所述,单元测试是关于客户感知的单元行为。测试它是否做了我认为作为消费者应该做的事情。我不 - 也不应该 - 关心它是如何在引擎盖下工作的。那本词典与我无关。

其次,良好的单元测试允许您验证行为,同时仍然让您自由地更改该行为的实现方式 - 如果您将测试绑定(bind)到该字典,它就不再是实现细节,而是成为契约(Contract)的一部分,这意味着对该单元的实现方式的任何更改都会迫使您保留该字典或更改您的测试。

这是一条与单元测试旨在实现的目标相反的道路 - 无痛维护。

底线是消费者 - 以及您的测试 - 不关心 setvalue 是否更新内部字典。弄清楚他们真正关心的是什么,然后进行测试。

顺便说一句,这就是 TDD(特别是测试优先)真正发挥作用的地方 - 如果您预先通过测试陈述预期行为,就很难发现自己陷入“我想做什么”测试?”车辙。

关于python - 如何对设置内部数据但不返回的方法进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38529807/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com