0

我正在对一个函数进行单元测试,该函数返回一个非常复杂的数据结构(集合列表列表的字典等)。我手动验证了输出,现在我想确保它不会在我没有注意到的情况下发生变化。

现在我有:

   self.assertEquals(data,
        {'Instr1': {'COUPON_LIST': '0 % SEMI 30/360',
                    'LEGAL_ENTITY': 'LE_XS0181523803',
                    'MATURITY_DATE': '2014/12/31',
                    'scenarios': {'Base': {'Spread Over Yield': -1.9/100,
                                           'THEO/PV01': -1500.15,
                                           'THEO/Value': 0.333,
                                           'THEO/Yield': 3.3/100},
                                  'UP': {'Spread Over Yield': -2.2/100,
                                         'THEO/PV01': -1000.1,
                                         'THEO/Value': 0.111,
                                         'THEO/Yield': 5.5/100}}},
         'Instr2': {'COUPON_LIST': None,
                    'LEGAL_ENTITY': 'LE_US059512AJ22',
                    'MATURITY_DATE': '2014/12/31',
                    'scenarios': {'Base': {'Spread Over Yield': None,
                                           'THEO/PV01': None,
                                           'THEO/Value': 1.0,
                                           'THEO/Yield': 0.0},
                                  'UP': {'Spread Over Yield': None,
                                         'THEO/PV01': -15.15,
                                         'THEO/Value': 4055.344,
                                         'THEO/Yield': 4.4/100}}},
         'Instr3': {'COUPON_LIST': '0 % SEMI 30/360',
                    'LEGAL_ENTITY': 'LE_XS0181523803',
                    'MATURITY_DATE': '2014/12/31',
                    'scenarios': {'Base': {'Spread Over Yield': -1.9/100,
                                           'THEO/PV01': -1500.15,
                                           'THEO/Value': 0.333,
                                           'THEO/Yield': 3.3/100},
                                  'UP': {'Spread Over Yield': -2.2/100,
                                         'THEO/PV01': -1000.1,
                                         'THEO/Value': 0.111,
                                         'THEO/Yield': 5.5/100}}},
         'Instr4': {'COUPON_LIST': None,
                    'LEGAL_ENTITY': 'LE_US059512AJ22',
                    'MATURITY_DATE': '2014/12/31',
                    'scenarios': {'Base': {'Spread Over Yield': None,
                                           'THEO/PV01': None,
                                           'THEO/Value': 1.0,
                                           'THEO/Yield': 0.0},
                                  'UP': {'Spread Over Yield': None,
                                         'THEO/PV01': -15.15,
                                         'THEO/Value': 4055.344,
                                         'THEO/Yield': 4.4/100}}}}

我有两个问题:

  1. 测试类不稳定,数据可能会发生变化。在这种情况下,我想快速查明输出更改的位置,并且只验证差异。例如,我正在寻找一个不错的输出说

    数据['Instr1']['MATURITY_DATE']: '2014/12/31' != '31/12/2014'

    数据['Instr5']:在 lhs 中找不到节点

    但同时我不想手动测试结构的每个节点。

  2. 如您所见,有些元素是浮动的,并且 4.4/100 != 0.044。我需要在浮点节点上运行 AssertAlmostEqual 并在其他所有节点上运行 AssertEqual 的逻辑。

有没有这样做的图书馆,还是我必须自己写?

4

2 回答 2

1

一个快速而肮脏的解决方案是使用difflib. 但是,此解决方案绝对可靠:

In [22]: import copy
    ...: import difflib
    ...: import pprint
    ...:
In [23]: data = {'Instr1': {'COUPON_LIST': '0 % SEMI 30/360',
    ...:                     'LEGAL_ENTITY': 'LE_XS0181523803',
    ...:                     'MATURITY_DATE': '2014/12/31',
    ...:                     'scenarios': {'Base': {'Spread Over Yield': -1.9/100,
    ...:                                            'THEO/PV01': -1500.15,
    ...:                                            'THEO/Value': 0.333,
    ...:                                            'THEO/Yield': 3.3/100},
    ...:                                   'UP': {'Spread Over Yield': -2.2/100,
    ...:                                          'THEO/PV01': -1000.1,
    ...:                                          'THEO/Value': 0.111,
    ...:                                          'THEO/Yield': 5.5/100}}},
    ...:          'Instr2': {'COUPON_LIST': None,
    ...:                     'LEGAL_ENTITY': 'LE_US059512AJ22',
    ...:                     'MATURITY_DATE': '2014/12/31',
    ...:                     'scenarios': {'Base': {'Spread Over Yield': None,
    ...:                                            'THEO/PV01': None,
    ...:                                            'THEO/Value': 1.0,
    ...:                                            'THEO/Yield': 0.0},
    ...:                                   'UP': {'Spread Over Yield': None,
    ...:                                          'THEO/PV01': -15.15,
    ...:                                          'THEO/Value': 4055.344,
    ...:                                          'THEO/Yield': 4.4/100}}},
    ...:          'Instr3': {'COUPON_LIST': '0 % SEMI 30/360',
    ...:                     'LEGAL_ENTITY': 'LE_XS0181523803',
    ...:                     'MATURITY_DATE': '2014/12/31',
    ...:                     'scenarios': {'Base': {'Spread Over Yield': -1.9/100,
    ...:                                            'THEO/PV01': -1500.15,
    ...:                                            'THEO/Value': 0.333,
    ...:                                            'THEO/Yield': 3.3/100},
    ...:                                   'UP': {'Spread Over Yield': -2.2/100,
    ...:                                          'THEO/PV01': -1000.1,
    ...:                                          'THEO/Value': 0.111,
    ...:                                          'THEO/Yield': 5.5/100}}},
    ...:          'Instr4': {'COUPON_LIST': None,
    ...:                     'LEGAL_ENTITY': 'LE_US059512AJ22',
    ...:                     'MATURITY_DATE': '2014/12/31',
    ...:                     'scenarios': {'Base': {'Spread Over Yield': None,
    ...:                                            'THEO/PV01': None,
    ...:                                            'THEO/Value': 1.0,
    ...:                                            'THEO/Yield': 0.0},
    ...:                                   'UP': {'Spread Over Yield': None,
    ...:                                          'THEO/PV01': -15.15,
    ...:                                          'THEO/Value': 4055.344,
    ...:                                          'THEO/Yield': 4.4/100}}}}

In [24]: data_repr = pprint.pformat(data)

In [25]: data2 = copy.deepcopy(data)

In [26]: data2['Instr1']['MATURITY_DATE'] = '31/12/2014'

In [27]: data2_repr = pprint.pformat(data2)

In [28]: def get_diff(a, b):
    ...:     differ = difflib.unified_diff(a.splitlines(True), b.splitlines(True))
    ...:     return ''.join(line for line in differ if not line.startswith(' '))

In [29]: print(get_diff(data_repr, data2_repr))
--- 
+++ 
@@ -1,6 +1,6 @@
-            'MATURITY_DATE': '2014/12/31',
+            'MATURITY_DATE': '31/12/2014',

然而,这并不能解决浮点数的问题。您可以通过首先使用简单的递归函数将floating 点值替换为 ed 值到某个有效数字来解决此问题。round

据我所知,没有这样的库可以对比较进行这种级别的精细控制,因此如果您想要一个强大的解决方案,您最好自己编写整个代码。

我还要指出,也许您应该将此数据结构重构为更结构化的类,这会使事情变得更容易。

最后但同样重要的是:您可以在比较 s 时使用unittest'saddTypeEqualityFunc来确保TestCase调用,而无需手动进行。assertAlmostEqualfloat


现在我考虑一下,您可以使用saddTypeEqualityFunc执行自定义比较,dict这可以添加更多关于不匹配的信息。要查找所有不匹配项,您必须except AssertionError as e:在自定义函数中使用一些块,始终检查所有子元素,然后以某种方式“加入”错误消息。但我认为解决方案不会那么干净。

于 2013-10-11T11:58:07.677 回答
0

我会编写一个具有预期参数和参数的函数,以单独测试和教授结构中的每个项目。然后,您可以提供适合要测试的项目的错误描述。

对于上面的复杂结构,编写多个这样的函数,每个“深度”一个。

例如

AssertEqualData(DataToTest, expectedData) 检查一个数据,调用 AssertInstr

AssertEqualInstr(InstrToTest, expectedInstr) 检查一个“InstrX”元素,该元素为每个项目调用 AssertEqualYield

AssertEqualYield(yieldToTest, expectedYield) 检查一个 Base 或 UP 元素

检测 Base 和 Up 项的 AssertEqualScenario(scenarioToTest, expectedScenario)。

于 2013-10-11T10:19:46.103 回答