Python中的单元测试对象-对象在安装程序中没有过度编写

Python中的单元测试对象-对象在安装程序中没有过度编写,python,unit-testing,unittest2,Python,Unit Testing,Unittest2,我正在使用unittest对Python中的类进行单元测试。据我所知,unittest在每次测试之前调用setUp函数,这样单元测试对象的状态是相同的,并且测试的执行顺序无关紧要 现在我有一门课我正在测试 #! usr/bin/python2 class SpamTest(object): def __init__(self, numlist = []): self.__numlist = numlist @property def numlist(

我正在使用
unittest
对Python中的类进行单元测试。据我所知,
unittest
在每次测试之前调用
setUp
函数,这样单元测试对象的状态是相同的,并且测试的执行顺序无关紧要

现在我有一门课我正在测试

#! usr/bin/python2

class SpamTest(object):

    def __init__(self, numlist = []):
        self.__numlist = numlist

    @property
    def numlist(self):
        return self.__numlist

    @numlist.setter
    def numlist(self, numlist):
        self.__numlist = numlist

    def add_num(self, num):
        self.__numlist.append(num)

    def incr(self, delta):
        self.numlist = map(lambda x: x + 1, self.numlist)

    def __eq__(self, st2):
        i = 0
        limit = len(self.numlist)

        if limit != len(st2.numlist):
            return False

        while i < limit:
            if self.numlist[i] != st2.numlist[i]:
                return False

            i += 1

        return True
#!usr/bin/python2
类SpamTest(对象):
定义初始化(self,numlist=[]):
self.\uu numlist=numlist
@财产
def numlist(自我):
返回自我
@努姆利斯特塞特
def numlist(自我,numlist):
self.\uu numlist=numlist
def add_num(self,num):
self.\uu numlist.append(num)
def增量(自身,增量):
self.numlist=map(λx:x+1,self.numlist)
定义(自我,st2):
i=0
限制=len(self.numlist)
如果限制!=len(st2.numlist):
返回错误
而我认为:
如果self.numlist[i]!=st2.数字列表[i]:
返回错误
i+=1
返回真值
通过以下单元测试

#! usr/bin/python2

from test import SpamTest

import unittest

class Spammer(unittest.TestCase):

    def setUp(self):
        self.st = SpamTest()
        #self.st.numlist = [] <--TAKE NOTE OF ME!
        self.st.add_num(1)
        self.st.add_num(2)
        self.st.add_num(3)
        self.st.add_num(4)

    def test_translate(self):
        eggs = SpamTest([2, 3, 4, 5])
        self.st.incr(1)
        self.assertTrue(self.st.__eq__(eggs))

    def test_set(self):
        nl = [1, 4, 1, 5, 9]
        self.st.numlist = nl
        self.assertEqual(self.st.numlist, nl)

if __name__ == "__main__":
    tests = unittest.TestLoader().loadTestsFromTestCase(Spammer)
    unittest.TextTestRunner(verbosity = 2).run(tests)
#!usr/bin/python2
从测试导入SpamTest
导入单元测试
类垃圾邮件发送者(unittest.TestCase):
def设置(自):
self.st=SpamTest()

#self.st.numlist=[]这是由于在Python中使用列表等可变对象时默认参数的行为方式所致

行中:

def __init__(self, numlist = []):
numlist的默认参数只计算一次,因此您只有列表的一个实例,该实例在
SpamTest
类的所有实例中共享

因此,即使每次测试都调用test
setUp
,它也不会创建一个新的空列表,并且在该列表实例上工作的测试最终会相互影响

解决方法是使用不可变对象(如
None
)来实现类似的功能:

def __init__(self, numlist = None):
    if numlist is None:
        numlist = []
    self.__numlist = numlist


设置属性时它起作用的原因是,您在那里提供了一个全新的空列表,替换在构造函数中创建的列表

在不研究解决方案细节的情况下,您应该阅读Fredrik Lundh的

它很可能解释了空列表作为默认参数的问题。原因是列表仅在第一次为空,除非以后显式将其设为空。初始值为空的默认列表是列表类型的单个实例,在没有传递显式参数时将重用该列表类型

阅读上面的文章来修正您对默认参数的想法是个好主意。原因是合乎逻辑的,但可能出乎意料

通常建议的修复方法是使用
None
作为
\uuuu init\uuuu
的默认值,并在未传递参数的情况下在正文中设置空列表,如下所示:

class SpamTest(object):

    def __init__(self, numlist=None):
        if numlist is None:
            numlist = []         # this is the new instance -- the empty list
        self.__numlist = numlist

哦,妈的。My+1>:)看起来好像我复制/粘贴了您的解决方案。但这真的只是巧合。也许只有
numlist是None
会更好。@pepr没问题+1从我这里也给你一个好的形式,正确的答案也是:)Fredrik Lundh的文章真的很棒,所以毫不奇怪我们都提到了它。所以…多教育我一点。
是无
==None
之间有什么区别?我一直使用的
是None
;不知道
==None
工作。@skytreader:操作员
正在测试对象标识。
None
值由非类型类的单个实例表示。值为
None
表示您正在共享对相同对象的引用。
numlist为None
表示您正在测试是否共享相同的对象。
=
运算符更复杂。如果
numlist
是定义自己的
方法的类的(引用)实例,
=
可能会产生意外的布尔值。然而,在简单的情况下,情况大致相同。