我有一个包含以下属性clusters
的类:
import numpy as np
class ClustererKmeans(object):
def __init__(self):
self.clustering = np.array([0, 0, 1, 1, 3, 3, 3, 4, 5, 5])
@property
def clusters(self):
assert self.clustering is not None, 'A clustering shall be set before obtaining clusters'
return np.unique(self.clustering)
我现在想为这个简单的属性编写一个单元测试。我从以下开始:
from unittest import TestCase, main
from unittest.mock import Mock
class Test_clusters(TestCase):
def test_gw_01(self):
sut = Mock()
sut.clustering = np.array([0, 0, 1, 1, 3, 3, 3, 4, 5, 5])
r = ClustererKmeans.clusters(sut)
e = np.array([0, 1, 3, 4, 5])
# The following line checks to see if the two numpy arrays r and e are equal,
# and gives a detailed error message if they are not.
TestUtils.equal_np_matrix(self, r, e, 'clusters')
if __name__ == "__main__":
main()
但是,这不会运行。
TypeError: 'property' object is not callable
我接下来将行r = ClustererKmeans.clusters(sut)
更改为以下内容:
r = sut.clusters
但同样,我得到了一个意想不到的错误。
AssertionError: False is not true : r shall be a <class 'numpy.ndarray'> (is now a <class 'unittest.mock.Mock'>)
有没有一种简单的方法可以使用unittest框架在Python中测试属性的实现?
答案 0 :(得分:2)
直接发送到call property,您可以在原始代码ClustererKmeans.clusters(sut)
中替换ClustererKmeans.clusters.__get__(sut)
。
即使我是一个嘲讽热情的恕我直言,这个案子并不是一个很好的例子来应用它。模拟对于从类和资源中删除依赖项非常有用。在你的情况下ClustererKmeans
有一个空的构造函数,并且没有任何依赖断开。您可以通过以下方式完成:
class Test_clusters(TestCase):
def test_gw_01(self):
sut = ClustererKmeans()
sut.clustering = np.array([0, 0, 1, 1, 3, 3, 3, 4, 5, 5])
np.testing.assert_array_equal(np.array([0, 1, 2, 3, 4, 5]),sut.clusters)
如果您使用模拟,可以使用ClustererKmeans()
修补unittest.mock.patch.object
个对象:
def test_gw_01(self):
sut = ClustererKmeans()
with patch.object(sut,"clustering",new=np.array([0, 0, 1, 1, 3, 3, 3, 4, 5, 5])):
e = np.array([0, 1, 3, 4, 5])
np.testing.assert_array_equal(np.array([0, 1, 2, 3, 4, 5]),sut.clusters)
...但是为什么在python给你一个简单直接的方法时使用补丁?
使用模拟框架的另一种方法应该是trust numpy.unique
并检查属性是否存在
正确的工作:
@patch("numpy.unique")
def test_gw_01(self, mock_unique):
sut = ClustererKmeans()
sut.clustering = Mock()
v = sut.clusters
#Check is called ....
mock_unique.assert_called_with(sut.clustering)
#.... and return
self.assertIs(v, mock_unique.return_value)
#Moreover we can test the exception
sut.clustering = None
self.assertRaises(Exception, lambda s:s.clusters, sut)
我为一些错误道歉,但我没有测试代码。我告诉你,我会尽快解决所有问题。