首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python:比较单元测试中的嵌套数据结构

Python:比较单元测试中的嵌套数据结构
EN

Stack Overflow用户
提问于 2016-03-19 03:02:09
回答 3查看 1.6K关注 0票数 5

有没有一种方法可以比较unittest中的嵌套数据结构,但忽略具体类型的对象,例如assertSequenceEqual但递归:

#!/usr/bin/env python

import unittest

class DeepCompareTestCase(unittest.TestCase):

    def test_compare(self):
        # this test fails
        self.assertSequenceEqual(
            [['abc', 'def']],
            (('abc', 'def'),)
        )

unittest.main()

(类似Perl中的Test::Deep )

EN

回答 3

Stack Overflow用户

发布于 2016-03-19 03:15:12

像这样的东西可以工作吗?

import unittest
from itertools import zip_longest

class RecursiveTestCase(unittest.TestCase):
    def assertSequenceDeepEqual(self, x, y):
        MissingValue = MissingValueSentinel()
        for x, y, in zip_longest(x, y, fillvalue=MissingValue):
            try:
                self.assertSequenceDeepEqual(self, x, y)
            except TypeError:
                self.assertEqual(x, y)

                self.assertIsNot(x, MissingValue)
                self.assertIsNot(y, MissingValue)

class MissingValueSentinel(object):
    pass

如果一个或多个项目不是迭代器,则zip_longest将引发TypeError,这表明您处于递归的底部。

如果其中一个迭代器比另一个短,我让它返回一个自定义MissingValueSentinel对象,该对象由函数末尾的assertIsNot调用检测到。这样做的唯一原因是,如果xy有一个类,无论出于什么原因,它都等同于像MissingValueSentinel这样的即席类,但assertEqual在该类的两个不同对象之间仍然有意义。这似乎是一种非常奇怪的边缘情况,您可以放心地忽略它。

使用zip_longest而不是zip可以防止[1, 2, 3][1, 2]不正确匹配。

票数 1
EN

Stack Overflow用户

发布于 2018-08-01 07:42:38

我遇到了与您类似的问题,但在我的例子中,我测试的是传递给API端点的数据结构。我最终做的是比较每个值的标准化JSON序列化。这不是一个通用的解决方案,因为它会在任何不能序列化为JSON的值上抛出异常,但在我的例子中,这是一个特性,而不是一个bug,它在你的例子中确实有效,所以我想我应该分享一下。

我创建了一个包含以下代码的tests/assertions.py文件:

import json

class ApiAssertionsMixin(object):

    def assertJsonEqual(self, first, second, msg=None):
        j1 = json.dumps(first, sort_keys=True, indent=4)
        j2 = json.dumps(second, sort_keys=True, indent=4)
        self.maxDiff = None
        self.assertEqual(j1, j2, msg)

在您的示例中,您将像这样使用它:

import unittest
from tests.assertions import ApiAssertionsMixin

class DeepCompareTestCase(ApiAssertionsMixin, unittest.TestCase):

    def test_compare(self):
        self.assertJsonEqual(
            [['abc', 'def']],
            (('abc', 'def'),)
        )

unittest.main()

应该会过去的。下面是一个失败测试的例子:

    def test_deep_compare(self):
        self.assertJsonEqual(
            { 'name': 'Bob', 'aliases': ['Kate', 'Robbie'], 'age': 19 },
            { 'name': 'Bob', 'age': 20, 'aliases': ['Robbie'] }
        )

输出如下所示:

.F
======================================================================
FAIL: test_deep_compare (__main__.DeepCompareTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_nested.py", line 18, in test_deep_compare
    { 'name': 'Bob', 'age': 20, 'aliases': ['Robbie'] }
  File "./tests/assertions.py", line 10, in assertJsonEqual
    self.assertEqual(j1, j2, msg)
AssertionError: '{\n    "age": 19,\n    "aliases": [\n        "Kate",\n [41 chars]"\n}' != '{\n    "age": 20,\n    "aliases": [\n        "Robbie"\n[24 chars]"\n}'
  {
-     "age": 19,
?            ^^
+     "age": 20,
?            ^^
      "aliases": [
-         "Kate",
          "Robbie"
      ],
      "name": "Bob"
  }

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)

正如您所看到的,在失败的情况下,您可以获得大量的上下文来找出哪里出了问题。

这种方法的一个缺点是,测试的输出是JSON而不是Python,所以如果你从输出中复制/粘贴来修复测试,你需要翻译:true => Truefalse => Falsenull => None

票数 1
EN

Stack Overflow用户

发布于 2019-01-24 23:21:13

也许deepdiff模块有帮助,但我没有测试它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36092399

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档