django-noseで気になった点

django-noseを使っていたら、あるときから急に「AttributeError: 'function' object has no attribute 'im_class'」というエラーがでるようになってしまいました。調べてみると、どうやらテストとして認識されるクラスが「unittest.TestCase」を継承しておらず、メソッド名に「test」が含まれているスタティックなメソッドがある場合に発生していました。その他にも条件があるかもしれませんが、私の環境下では上記を満たしたら発生しました。

AttributeError: 'function' object has no attribute 'im_class'が発生する例

私の環境では、以下のようなテストクラスがあると、エラーが設定してしまいました。

from django.test import TestCase


class TestHoge(TestCase):
    def test_hoge01(self):
        self.assertEqual(u'HOGE', TestUtils.test_get_hoge())


class TestUtils(object):

    @staticmethod
    def test_get_hoge():
        return u'HOGE'

※ test_hoge.pyは、Djangoのテスト用ディレクトリの下に置いています。

これで実行すると、以下のようなエラーが表示されてしまいます。

python manage.py test hoge
Traceback (most recent call last):
...
...
AttributeError: 'function' object has no attribute 'im_class'

なお「AttributeError: 'function' object has no attribute 'im_class'」はテストケースに限らず、スタティックメソッドのim_classを参照しようとすると発生するみたいです。

$ python
>>> class Hoge(object):
...     def hoge1(self):
...         return u'HOGE1'
... 
...     @staticmethod
...     def hoge2():
...         return u'HOGE2'
... 
>>> hoge = Hoge()
>>> hoge.hoge1.im_class.__name__
'Hoge'
>>> hoge.hoge2.im_class
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'function' object has no attribute 'im_class'

上記の場合の対策は、「TestUtilsのクラス名からTestを外す」や「test_get_hogeをget_hogeに名称変更する」などがあります。なお、「TestUtilsをunittest.TestCase(django.test.TestCaseでも可)のサブクラスにする」という解決方法は上記では大丈夫ですが、駄目なケースもあったのでやめておいた方がよさそうです。

この記事が役に立った場合、シェアしていただけると励みになります!!