はじめに
Pythonのunittestを書いていて、同じはずのEnumオブジェクトの比較結果がなぜかFalseになってしまう事象で少し詰まった。結果的に凡ミスだったが、今後ハマる人のために共有しておく。
PythonのEnumやunittestについては詳しく触れないので、気になる人は以下の公式資料を参照すると良い。
TL;DR
importのパッケージ名を揃えれば解決する。
問題の再現
以下のようなディレクトリ構成を考える。
enumbug
├── b.py
├── enums.py
└── test.py
各ファイルの中身は以下の通り。
from enum import Enum
class Color(Enum):
RED = 1
BLUE = 2
GREEN = 3
from enums import Color
class B(object):
def __init__(self):
self.color = Color.RED
import unittest
from enumbug.b import B
from enumbug.enums import Color
class Test(unittest.TestCase):
def test(self):
b = B()
self.assertEqual(b.color, Color.RED)
ここでunittestを実行すると以下のようになり、b.color
とColor.RED
の比較がFalseになる。両方ともColor.REDなのに。
$ PYTHONPATH=<enumbugの親ディレクトリのフルパス> python -m unittest test 2>&1|pbcopy
F
======================================================================
FAIL: test (test.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<enumbugの親ディレクトリのフルパス>/enumbug/test.py", line 10, in test
self.assertEqual(b.color, Color.RED)
AssertionError: <Color.RED: 1> != <Color.RED: 1>
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
<Color.RED: 1> != <Color.RED: 1>
ってなんやねん、同じやろって10分くらいキレてた。
原因
いろいろ調べた結果以下の記事を見つけ、Colorをインポートしているパッケージが異なることが原因だと分かった。
上記のb.py
ではfrom enums import Color
としているのに対し、test.py
ではfrom enumbug.enums import Color
としてしまっており、比較している2つのEnumが別のパッケージのものになってしまっていたためにEnumの比較がFalseになってしまっていた。
パッケージのimportをIDEに頼って自動化してしまっていたためになかなかこれに気が付けなかったのが悔やまれる。ただこれ分かっていないと原因探るの難しい気はした。エラーメッセージでわかるようにしてほしい。