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}}}}

2 つの問題があります。

  1. テストされたクラスは安定しておらず、データは変更される可能性があります。その場合、出力が変更された場所をすばやく特定し、違いのみを検証したいと考えています。たとえば、次のような素敵な出力を探しています

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

    data['Instr5']: lhs にノードが見つかりません

    しかし同時に、構造のすべてのノードを手動でテストしたくありません。

  2. ご覧のとおり、一部の要素は float で、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 points 値をed 値に置き換えることで解決できます。round

私の知る限り、比較をこのレベルで細かく制御できるようなライブラリは存在しないため、堅牢なソリューションが必要な場合は、コード全体を自分で作成することをお勧めします。

また、このデータ構造をより構造化されたクラスにリファクタリングする必要があるかもしれないことも指摘しておきます。これにより、作業が簡単になります。

最後になりましたが、 s を使用して、 s を比較するときに呼び出しを確認できますunittest。手動でaddTypeEqualityFunc行う必要はありません。TestCaseassertAlmostEqualfloat


考えてみると、 s のaddTypeEqualityFuncカスタム比較を実行dictして、不一致に関する情報を追加できる可能性があります。すべての不一致を見つけるexcept AssertionError as e:には、カスタム関数にいくつかのブロックを使用し、常にすべてのサブ要素をチェックしてから、何らかの方法でエラー メッセージを「結合」する必要があります。しかし、解決策がそれほどきれいになるとは思いません。

于 2013-10-11T11:58:07.677 に答える
0

期待される引数と、構造内の各項目を個別にテストして教える引数を持つ関数を作成します。次に、テストする項目に適したエラーの説明を与えることができます。

上記の複雑な構造の場合、「深さ」ごとに 1 つずつ、そのような関数を複数記述します。

例えば

AssertInstr を呼び出す 1 つのデータをチェックする AssertEqualData(DataToTest, expectedData)

AssertEqualInstr(InstrToTest, expectedInstr) は、1 つの 'InstrX' 要素をチェックし、各アイテムに対して AssertEqualYield を呼び出します

1 つの Base または UP 要素をチェックする AssertEqualYield(yieldToTest, expectedYield)

Base アイテムと Up アイテムをチェックする AssertEqualScenario(scenarioToTest, expectedScenario)。

于 2013-10-11T10:19:46.103 に答える