在单元测试中比较字典时如何忽略某些值?

How can I ignore certain values when comparing dictionaries in unittest?

我想断言两个字典是相等的,使用 Python 的 unittest,但忽略字典中某些键的值,在一个方便的语法中,像这样:

from unittest import TestCase

class Example(TestCase):
    def test_example(self):
        result = foobar()
        self.assertEqual(
            result,
            {
                "name": "John Smith",
                "year_of_birth": 1980,
                "image_url": ignore(), # how to do this?
                "unique_id": ignore(), #
            },
        )

明确地说,我想检查所有四个键是否存在,我想检查 "name""year_of_birth" 的值,(但不是 "image_url""unique_id"),我想检查是否不存在其他键。

我知道我可以将此处的 result 修改为 "image_url""unique_id" 的键值对,但我想要更方便的东西,不修改原始字典.

(这是受 Perl 5 的 Test::Deep 的启发。)

您可以简单地忽略 result 字典中的选定键。

self.assertEqual({k: v for k, v in result.items()
                  if k not in ('image_url', 'unique_id')},
                 {"name": "John Smith",
                  "year_of_birth": 1980})

unittest.mock.ANY比较等于一切。

from unittest import TestCase
import unittest.mock as mock

class Example(TestCase):
    def test_happy_path(self):
        result = {
            "name": "John Smith",
            "year_of_birth": 1980,
            "image_url": 42,
            "unique_id": 'foo'
        }
        self.assertEqual(
            result,
            {
                "name": "John Smith",
                "year_of_birth": 1980,
                "image_url": mock.ANY,
                "unique_id": mock.ANY
            }
        )

    def test_missing_key(self):
        result = {
            "name": "John Smith",
            "year_of_birth": 1980,
            "unique_id": 'foo'
        }
        self.assertNotEqual(
            result,
            {
                "name": "John Smith",
                "year_of_birth": 1980,
                "image_url": mock.ANY,
                "unique_id": mock.ANY
            }
        )

    def test_extra_key(self):
        result = {
            "name": "John Smith",
            "year_of_birth": 1980,
            "image_url": 42,
            "unique_id": 'foo',
            "maiden_name": 'Doe'
        }
        self.assertNotEqual(
            result,
            {
                "name": "John Smith",
                "year_of_birth": 1980,
                "image_url": mock.ANY,
                "unique_id": mock.ANY
            }
        )

    def test_wrong_value(self):
        result = {
            "name": "John Smith",
            "year_of_birth": 1918,
            "image_url": 42,
            "unique_id": 'foo'
        }
        self.assertNotEqual(
            result,
            {
                "name": "John Smith",
                "year_of_birth": 1980,
                "image_url": mock.ANY,
                "unique_id": mock.ANY
            }
        )