AssertAlmostEqual等于字典中的值

时间:2018-06-19 18:58:20

标签: python unit-testing

我有以下代码:

def test_transformation_last_price(self):
    data_set = etl.fromdicts([{'MTDReturn': 4, 'EffectiveDate': '1992-06-30'},
                              {'MTDReturn': 3.2, 'EffectiveDate': '1992-07-31'}])
    last_price_dataset = self.parser.last_price_dataset(data_set)
    first_row = list(etl.dicts(last_price_dataset))[0]
    expected_row = {'TimeSeriesValue': 121.20923188958272,
                    'EffectiveDate': datetime.date(1992, 6, 30),
                    'FundID': self.parser.FUND_ID,
                    'TimeSeriesTypeID': self.parser.LAST_PRICE_ID}
    self.assertEqual(first_row, expected_row)

我的方法:last_price_dataset运行一些其他方法,这些方法实质上是从数据库中获取值并基于该值进行一些计算。目前,这是正确的。但是,该值可能在此处和此处变化一些小数点。

我可以使用单元测试来检查TimeSeriesValue是否接近该字典中的数字吗?

AssertAlmostEqual不适用于这样的字典。有什么建议吗?

3 个答案:

答案 0 :(得分:0)

您可以使用TestCase.assertAmostEqual(请在此处阅读更多信息-https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertAlmostEqual):

assertAlmostEqual(first, second, places=7, msg=None, delta=None)

例如,如果精度为0小数位,则以下测试通过:

from unittest import TestCase
from unittest import main

class Test(TestCase):
    def test_1(self):
        dict1 = {'TimeSeriesValue': 121.20923188958272}
        dict2 = {'TimeSeriesValue': 121.3}
        self.assertAlmostEqual(dict1['TimeSeriesValue'], dict2['TimeSeriesValue'], 1)

if __name__ == '__main__':
    main()
  

为了进行测试,它可能像:

# number of decimal places is 0
self.assertAlmostEqual(expected_row['TimeSeriesValue'], first_row[<your key here>], 0)

答案 1 :(得分:0)

我今天遇到了同样的问题。因此,我只是构建自己的方法assertDictAlmostEqual

def assertDictAlmostEqual(self, d1, d2, msg=None, places=7):

    # check if both inputs are dicts
    self.assertIsInstance(d1, dict, 'First argument is not a dictionary')
    self.assertIsInstance(d2, dict, 'Second argument is not a dictionary')

    # check if both inputs have the same keys
    self.assertEqual(d1.keys(), d2.keys())

    # check each key
    for key, value in d1.items():
        if isinstance(value, dict):
            self.assertDictAlmostEqual(d1[key], d2[key], msg=msg)
        else:
            self.assertAlmostEqual(d1[key], d2[key], places=places, msg=msg)

答案 2 :(得分:0)

FWIW,这是我刚才编写的包装函数,用于对dict / list进行“深度”声明。

import unittest
from collections.abc import Iterable, Mapping
from itertools import zip_longest

# thanks to https://stackoverflow.com/questions/32954486/zip-iterators-asserting-for-equal-length-in-python
def zip_equal(*iterables):
    sentinel = object()
    for combo in zip_longest(*iterables, fillvalue=sentinel):
        if sentinel in combo:
            raise ValueError('Iterables have different lengths')
        yield combo

def assert_deep(instance: unittest.TestCase, method, first, second, *args, path=tuple(), **kwargs):
    instance.assertIsInstance(second, type(first))
    if isinstance(first, Mapping):
        instance.assertEqual(first.keys(), second.keys())
        for key in first:
            subtest_path = path + (key,)
            with instance.subTest(subtest_path):
                assert_deep(instance, method, first[key], second[key], path=subtest_path, *args, **kwargs)
        return instance

    # thanks to https://stackoverflow.com/questions/1952464/in-python-how-do-i-determine-if-an-object-is-iterable
    if isinstance(first, Iterable):
        index = 0
        try:
            for first_el, second_el in zip_equal(first, second):
                # avoid infinite recursions on iterables that return themselves as elements, e.g. strings
                if first_el is first:
                    return method(first, second, *args, **kwargs)
                subtest_path = path + (index,)
                with instance.subTest(subtest_path):
                    assert_deep(instance, method, first_el, second_el, *args, path=subtest_path, **kwargs)
                index += 1
        except ValueError as e:
            instance.fail(e)
        return instance

    return method(first, second, *args, **kwargs)    

class AssertDeepTest(unittest.TestCase):
    def test_assert_deep_ok(self):
        assert_deep(self, self.assertAlmostEqual, 
            {'a': [0.100, 0.200], 'b': [0.300, 0.400, 0.500]}, 
            {'a': [0.101, 0.201], 'b': [0.301, 0.401, 0.501]}, 
            places=2)
        assert_deep(self, self.assertEqual,
            {'a': [1, 1.0, 'a'], 'foo': [2, 'bar']},
            {'foo': [2, 'bar'], 'a': [1, 1.0, 'a']})

    @unittest.expectedFailure
    def test_assert_deep_fail_method(self):
        assert_deep(self, self.assertAlmostEqual, 
            {'a': [0.100, 0.200], 'b': [0.300, 0.400, 0.500]}, 
            {'a': [0.101, 0.201], 'b': [0.301, 0.401, 0.501]}, 
            places=3)

    @unittest.expectedFailure
    def test_assert_deep_fail_keys(self):
        assert_deep(self, self.assertAlmostEqual, 
            {'a': [0.100, 0.200], 'b': [0.300, 0.400, 0.500]}, 
            {'a': [0.101, 0.201], 'c': [0.301, 0.401, 0.501]}, 
            places=2)

    @unittest.expectedFailure
    def test_assert_deep_fail_types(self):
        assert_deep(self, self.assertAlmostEqual, 
            {'a': [0.100, 0.200], 'b': [0.300, 0.400, 0.500]}, 
            {'a': [0.101, 0.201], 'b': (0.301, 0.401, 0.501)}, 
            places=2)

    @unittest.expectedFailure
    def test_assert_deep_fail_lens(self):
        assert_deep(self, self.assertAlmostEqual, 
            {'a': [0.100, 0.200], 'b': [0.300, 0.400, 0.500]}, 
            {'a': [0.101, 0.201], 'b': [0.301, 0.401, 0.501, 0.601]}, 
            places=2)