我有以下代码:
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
不适用于这样的字典。有什么建议吗?
答案 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)