以艰难的方式学习Python,例49:使用assert_equal比较对象

时间:2012-02-16 05:54:34

标签: python unit-testing

是否可以使用assert_equal来比较对象?我一直看到这个错误:

AssertionError: <ex49.parser.Sentence object at 0x01F1BAF0> !=
<ex49.parser.Sentence object at 0x01F1BB10>

相关代码片段:

def test_parse_subject():

    testsentence = "princess go east"
    result = lexicon.scan(testsentence)
    Sent = parse_sentence(result)
    ResultSent = Sentence(('subject', 'princess'),
                      ('verb', 'go'),
                      ('object', 'east'))
    print ResultSent.subject
    print ResultSent.verb
    print ResultSent.object
    print Sent.subject
    print Sent.verb
    print Sent.object
    assert_equal(Sent, ResultSent)

屏幕上的打印输出表明对象具有相同的内容 - 但断言错误显示出来。为什么是这样?有没有办法使用assert_equal来覆盖它?

3 个答案:

答案 0 :(得分:6)

我相信你需要在Sentence类上实现__eq__方法。

  

assertEqual(first,second,msg = None)¶   测试第一和第二是相等的。如果值不相等,则测试将失败。

     

此外,如果第一个和第二个是完全相同的类型,并且是list,tuple,dict,set,frozenset或unicode之一或子类向addTypeEqualityFunc()注册的任何类型,则将调用特定于类型的相等函数为了生成更有用的默认错误消息(另请参见特定于类型的方法列表)。

Python unittest documentation

  

运算符符号和方法名称之间的对应关系如下:xlt(y),x&lt; = y调用x。 le (y),x == y调用x。 eq (y),x!= y和x&lt;&gt; y调用x。 ne (y),x&gt; y调用x。 gt (y) ,x&gt; = y称x。 ge (y)。

Python data model documentation

一个例子:

import unittest


class A:

    def __init__(self, num):
        self.num = num

    def __eq__(self, other):
        return self.num == other.num


class Test(unittest.TestCase):

    def test(self):
        a1 = A(1)
        a12 = A(1)
        a2 = A(2)

        self.assertEqual(a1, a1, 'a1 != a1')
        self.assertEqual(a1, a12, 'a1 != a12')
        self.assertEqual(a1, a2, 'a1 != a2')

def main():
    unittest.TestRunner(Test())

if __name__ == '__main__':
    unittest.main()

现在评论__eq__方法并查看差异。

答案 1 :(得分:1)

这是一个很好的信息,对我来说,我懒得搜索所以我只是比较了两个对象的变量,如下所示:

def test_parse_subject():
    word_list_a = lexicon.scan("eat the bear")
    Sentence1 = Sentence(('noun','player'),('verb', 'eat'),('noun', 'bear'))
    Sentence2 = parse_subject(word_list_a,('noun','player'))

    assert_equal(Sentence2.subject, Sentence1.subject)  
    assert_equal(Sentence2.verb, Sentence1.verb)
    assert_equal(Sentence2.object, Sentence1.object)

答案 2 :(得分:0)

我也在使用LPTHW ex49。特别是对于这个例子的上下文,我能够通过将__eq __()方法添加到Sentence类来实现它,如下所示:

Class Sentence(object):

    def __init__(self, subject, verb, object_)
        ...

    def __eq__(self, other):
        return (self.subject == other.subject and
                self.verb == other.verb and
                self.object_ == other.object_)

然后,在测试文件中,我做了:

# where LIST5 is defined above to give list of two tuples, [('verb', 'go'), ('direction', 'east')]
def test_parse_subject():
    wordlist = list(LIST5) 
    sent = parse.Sentence(('noun', 'person'), ('verb'), ('go'), ('direction', 'east))
    newsent = parse.parse_subject(wordlist, ('noun', 'person'))
    assert_equal(newsent, sent)

据我所知(对此新),assert_equal with nose和unittest将调用__eq __()方法(如果存在)。在这种情况下,只要两个对象具有subject,verb,object_的相同三个值,测试就可以。然而,这花了我一段时间才弄清楚,因为我的代码中有一个错误,而且鼻子提供的唯一东西就是你收到的同样的错误信息,即使我有__eq __()方法。也就是说,它提供了“AssertionError:...对象在0x ...!=对象在0x ...”这误导我认为__eq __()方法不起作用,因为它看起来像是比较地址。不确定是否有更好的方法来做到这一点。

注意:我将对象重命名为object_,因为gedit将对象突出显示为python关键字。不确定是否建议使用尾随下划线。