はじめに
pythonのunittestでDict型の中にList型があって,テストをするたびに通ったり通らなかったりすることってありませんか?
私はあって悩んだのでここに書き残しておきます.
解決の糸口はこのサイト(1)からいただきました.ありがとうございます.
assertEqualで対応できないところ
ここ(2)を参考にしながら以下のようなテストを書きました.
import unittest
class VTest(unittest.TestCase):
maxDiff = None
def setUp(self):
pass
def tearDown(self):
pass
def test_v(self):
first_json = {
'kind': 'voiceroid',
'items': [
{'name': 'aoi'},
{'name': 'akane'},
{'name': 'yukari'}
]
}
second_json = {
'kind': 'voiceroid',
'items': [
{'name': 'yukari'},
{'name': 'aoi'},
{'name': 'akane'},
]
}
self.assertEqual(first_json, second_json)
if __name__ == "__main__":
unittest.main()
この時itemsの順序はどうでもいいよ~中身さえあってればね・・・みたいな状況になったとします.なので,個人的にはこれはテストOKです.ですが実際に動かすと
F
======================================================================
FAIL: test_v (__main__.VTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File ".\v_test.py", line 34, in test_v
self.assertEqual(first_json, second_json)
AssertionError: {'kin[20 chars]ems': [{'name': 'aoi'}, {'name': 'akane'}, {'name': 'yukari'}]} != {'kin[20 chars]ems': [{'name': 'yukari'}, {'name': 'aoi'}, {'name': 'akane'}]}
- {'items': [{'name': 'aoi'}, {'name': 'akane'}, {'name': 'yukari'}],
+ {'items': [{'name': 'yukari'}, {'name': 'aoi'}, {'name': 'akane'}],
'kind': 'voiceroid'}
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
こんな風に怒られちゃいます.
いやでも個人的には・・・・とか言ってもダメなものはダメです.というのがassertEqual関数
です.
そこで,値は大事だけど順序はいらないという要望に柔軟に応えてくれるライブラリがPyHamcrest(3)です.
外部ライブラリなので
pip install PyHamcrest
でインストールしたのち先ほどのコードを以下のように書き換えます.
from hamcrest import *
import unittest
class VTest(unittest.TestCase):
maxDiff = None
def setUp(self):
pass
def tearDown(self):
pass
def test_v(self):
first_json = {
'kind': 'voiceroid',
'items': [
{'name': 'aoi'},
{'name': 'akane'},
{'name': 'yukari'}
]
}
second_json = {
'kind': 'voiceroid',
'items': [
{'name': 'yukari'},
{'name': 'aoi'},
{'name': 'akane'}
]
}
# self.assertEqual(first_json, second_json)
assert_that(first_json, second_json)
if __name__ == "__main__":
unittest.main()
これはassertEqual関数
をassert_that関数
に変えただけです.それではテストしてみると・・・
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
きれいに通りましたね.
さいごに
要素は大事だけど順序はあんまり重要でないのに怒られて困ったーって方は一度試してみてはどうでしょうか?PyHamcrestのチュートリアル(4)はこちらですいろいろあるので他にも試してみてくださいきっとテストが柔軟になると思います!
参考
(1) Python unittest - asserting dictionary with lists
(2) 最短で試すPythonテストコード
(3) PyHamcrest
(4) PyHamcrest Tutorial