web-dev-qa-db-ja.com

ユニットテストで文字列の切り捨てを防ぐ方法python

プログラムのpythonで単体テストを行っていますが、assertEqualsテストを行いたいと思います。

私のコードは次のようになります。

class UnitTest(unittest.TestCase):
      def test_parser(self):
          self.assertEquals(parser,"some long string", "String is not equal")

ただし、文字列が長すぎるため、testing [471 chars] 0!= tests [473chars]のようなものが得られました。切り捨てられた文字列を表示する代わりに、両方の文字列の正確な違いを確認したいと思います。

誰もがこの問題に対処する方法を知っていますか?

9
decemberrobot

それで、assertEqual()を使用していて、「self.maxDiff = None」を使用しても完全な出力が表示されないという問題があったため、この質問にたどり着きました。トレースすると、2つのオブジェクトのタイプが異なるため(1つはリスト、もう1つはジェネレーター)、「self.maxDiff」を使用するコードパスは使用されていないことがわかりました。したがって、完全な差分が必要で「self.maxDiff」が機能しないという問題が発生した場合は、比較する2つのオブジェクトのタイプが同じであることを確認してください。

6
Robert Thille

unittest.TestCase.assertEqualsは、文字列の実際の違いを提供すると同時に、テキストを画面に合わせようとします。

これを行うために、共通のセクションが切り捨てられるため、差異がないセクションは、[<count> chars]チャンクに置き換えることで切り捨てられます。

>>> case.assertEqual('foo' * 200, 'foo' * 100 + 'bar' + 'foo' * 99)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 821, in assertEqual
    assertion_func(first, second, msg=msg)
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 1194, in assertMultiLineEqual
    self.fail(self._formatMessage(msg, standardMsg))
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 666, in fail
    raise self.failureException(msg)
AssertionError: 'foof[291 chars]oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo[255 chars]ofoo' != 'foof[291 chars]oofoobarfoofoofoofoofoofoofoofoofoofoofoofoofo[255 chars]ofoo'
Diff is 1819 characters long. Set self.maxDiff to None to see it.

上記の例では、2つの文字列が長いプレフィックスを共有していますが、両方のプレフィックスで291文字を[291 chars]に置き換えることで短縮されています。また、長い接尾辞を共有し、テキストを[255 chars]に置き換えることで両方の場所で短縮されています。

actualの違いは、真ん中に表示されたままです。

もちろん、その違いを長くしすぎると、違いさえも切り捨てられます。

>>> case.assertEqual('foo' * 200, 'foo' * 80 + 'bar' * 30 + 'foo' * 80)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 821, in assertEqual
    assertion_func(first, second, msg=msg)
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 1194, in assertMultiLineEqual
    self.fail(self._formatMessage(msg, standardMsg))
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 666, in fail
    raise self.failureException(msg)
AssertionError: 'foof[231 chars]oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo[315 chars]ofoo' != 'foof[231 chars]oofoobarbarbarbarbarbarbarbarbarbarbarbarbarba[285 chars]ofoo'
Diff is 1873 characters long. Set self.maxDiff to None to see it.

ここでは、一般的な接尾辞が異なり始めていますが、違いの始まりはまだ表示されており、テキストがどこで間違っていたかを理解するのに役立つはずです。

それでも不十分な場合は、差分制限を増やすか削除することができます。 TestCase.maxDiff属性 をより大きな数値(デフォルトは8 * 80、80行のテキスト)に設定するか、Noneに設定して完全に削除します。

self.maxDiff = None

文字列にnewlinesが含まれていない限り、差分が読み取れない可能性があることに注意してください。

AssertionErrorが 'foof [231文字] [315の文字] ofoo oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo' = 'foof [231の文字] oofoobarbarbarbarbarbarbarbarbarbarbarbarbarba [285の文字] ofoo' - foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo!?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ + foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoobarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarfoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

その場合、入力テキストと出力テキストをwrapする方が便利な場合があります。

from textwrap import wrap

self.maxDiff = None
self.assertEquals(wrap(parser), wrap("some long string"), "String is not equal")

ちょうどあなたがより良くそしてより読みやすいdiff出力を得るように:

>>> from textwrap import wrap
>>> case.assertEqual(wrap('foo' * 200), wrap('foo' * 80 + 'bar' * 30 + 'foo' * 80))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 821, in assertEqual
    assertion_func(first, second, msg=msg)
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 1019, in assertListEqual
    self.assertSequenceEqual(list1, list2, msg, seq_type=list)
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 1001, in assertSequenceEqual
    self.fail(msg)
  File "/Users/mjpieters/Development/Library/buildout.python/parts/opt/lib/python3.6/unittest/case.py", line 666, in fail
    raise self.failureException(msg)
AssertionError: Lists differ: ['foo[244 chars]oofoofoofoofoofoofoofoofoofoofoofoofoofoofoof'[336 chars]foo'] != ['foo[244 chars]oofoobarbarbarbarbarbarbarbarbarbarbarbarbarb'[306 chars]foo']

First differing element 3:
'foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof'
'foofoofoofoofoofoofoofoofoofoobarbarbarbarbarbarbarbarbarbarbarbarbarb'

  ['foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof',
   'oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo',
   'ofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo',
-  'foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof',
-  'oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo',
+  'foofoofoofoofoofoofoofoofoofoobarbarbarbarbarbarbarbarbarbarbarbarbarb',
+  'arbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarfoofoofoofoofoofoofo',
   'ofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo',
   'foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoof',
   'oofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofo',
-  'ofoofoofoofoofoofoofoofoofoofoofoofoofoo']
+  'ofoofoofoo']
4
Martijn Pieters

[... chars][truncated]...を実際の文字に置き換えるには(長さに関係なく、比較される値のタイプに関係なく)、これを*_test.pyファイルに追加します。

if 'unittest.util' in __import__('sys').modules:
    # Show full diff in self.assertEqual.
    __import__('sys').modules['unittest.util']._MAX_LENGTH = 999999999

実際、他の回答が指摘しているように、self.maxDiff = Noneを設定しても効果はなく、[... chars]が消えることはありません。ただし、この設定は他のタイプの長い差分を表示するのに役立つため、両方を実行することをお勧めします。

0
pts