单元测试简单方法。。。一个健全的OOP/Python解决方案?
我试图以一种良好的面向对象的方式设计和测试类似于以下内容的代码?(还是一种蟒蛇式的方式?) 下面是一个工厂类,它决定一个人的名字是长是短:单元测试简单方法。。。一个健全的OOP/Python解决方案?,python,oop,unit-testing,Python,Oop,Unit Testing,我试图以一种良好的面向对象的方式设计和测试类似于以下内容的代码?(还是一种蟒蛇式的方式?) 下面是一个工厂类,它决定一个人的名字是长是短: class NameLengthEvaluator(object): def __init__(self, cutoff=10) self.cutoff = cutoff def evaluate(self, name): if len(self.name) > cutoff:
class NameLengthEvaluator(object):
def __init__(self, cutoff=10)
self.cutoff = cutoff
def evaluate(self, name):
if len(self.name) > cutoff:
return 'long'
else:
return 'short'
下面是一个person类,它对自己姓名的长度有自己的看法:
class Person(object):
def __init__(self, name=None, long_name_opinion=8):
self.name = name
def name_length_opinion(self):
return 'My names is ' + \
NameLengthEvaluator(long_name_opinion).evaluate(self.name)
有几个问题:
方法Person
是否值得进行单元测试,如果是这样,它会是什么样子name\u length\u opinion()
- 总的来说,有没有一种好方法可以测试具有完全外部功能的类的简单方法
(免责声明:代码未经测试,我是python新手)这实际上取决于代码的生命周期。很明显,在当前状态下,该方法显然是正确的,单元测试更像是对其行为的规范。如果您计划在将来进行更改(例如,以某种不同的方式重新实现
namelingtheevaluator
),那么进行单元测试是很好的,因为运行测试将捕获任何回归。但是在这种情况下,您似乎不太可能进行任何更改,因此测试可能过多(尽管进行了良好的健全性检查)。单元测试
Person方法name_length_opinion()是否值得进行单元测试,如果是,它会是什么样子
你想确保它做你认为它做的事情,并确保它在未来不会破裂吗?如果是这样,请为其编写一个单元测试
测试只是为了确认没有人碰过代码
单元测试更多的是确保类符合它指定的契约。您不必为所有内容编写单元测试,但是如果它是一个简单的方法,那么无论如何它都应该是一个简单的单元测试
重复
似乎对该方法的任何测试都只是重申其实现
你不应该重复这个算法,你应该使用用例。例如,截止值为10
的名称长度估价者
应具有以下短名称:
- 乔治
- 玛丽
- 麦基刀
- 千斤顶
名称长度,在4
截止值的情况下,评估者将报告Mary
为短,其他为长
一次性代码?
如果您曾经编写过一个类,然后又编写了一个主方法来运行该类,以确保该类执行它应该执行的操作(然后在转到另一个类时将该主方法扔掉),那么您已经编写了一个单元测试。但是不要扔掉它,而是保存它并将其转换为单元测试,这样将来您就可以确保没有破坏任何东西
外部代码
总的来说,有没有一种好方法可以测试具有完全外部功能的类的简单方法
如果它完全是外部的,那么为什么它是这个类上的一个方法呢?通常,您至少有一些可以测试的逻辑。在这种情况下,您可以测试name\u length\u opinion
是否在正确的情况下返回My names is long
或My names is short
。通常您会在此处使用模拟。您可以创建一个模拟的namelength评估器
,该评估器返回一个记录了连接内容的对象,当name\u length\u opinion
返回时,您应该检查以确保使用了正确的对象并连接了正确的对象
例如,使用:
然而,由于方法如此简单,我不确定你是否会那么在意
from unittest.mock import MagicMock, patch
@patch('your_module.NameLengthEvaluator', autospec=True)
def test_person_name_length_opinion(NameLengthEvaluator):
expected_result = object()
opinion = MagicMock(name='opinion')
opinion.__radd__.return_value = expected_result
name_length_evaluator = MagicMock(name='name_length_evaluator')
name_length_evaluator.evaluate.return_value = opinion
NameLengthEvaluator.return_value = name_length_evaluator
name = object()
length_limit = object()
person = Person(name, long_name_opinion=length_limit)
result = person.name_length_opinion()
NameLengthEvaluator.assert_called_with(length_limit)
name_length_evaluator.evaluate.assert_called_with(name)
opinion.__radd__.assert_called_with('My names is ')
assert result is expected_result