53

抽象基本クラスで定義されたメソッドをテストする方法/ベストプラクティスを探しています。私が直接考えることができることの1つは、基本クラスのすべての具象サブクラスでテストを実行することですが、それは時々過度に思えます。

この例を考えてみましょう。

import abc

class Abstract(object):

    __metaclass__ = abc.ABCMeta

    @abc.abstractproperty
    def id(self):
        return   

    @abc.abstractmethod
    def foo(self):
        print "foo"

    def bar(self):
        print "bar"

barサブクラス化せずにテストすることは可能ですか?

4

6 に答える 6

66

Pythonの新しいバージョンでは、使用できますunittest.mock.patch()

class MyAbcClassTest(unittest.TestCase):

    @patch.multiple(MyAbcClass, __abstractmethods__=set())
    def test(self):
         self.instance = MyAbcClass() # Ha!
于 2015-02-26T08:58:21.080 に答える
25

lunaryon が適切に述べているように、それは不可能です。抽象メソッドを含む ABC のまさにその目的は、宣言されたようにインスタンス化できないことです。

ただし、ABC をイントロスペクトし、その場でダミーの非抽象クラスを作成するユーティリティ関数を作成することは可能です。この関数は、テスト メソッド/関数内で直接呼び出すことができ、いくつかのメソッドをテストするためだけに、テスト ファイルにボイラー プレート コードを書く必要がなくなります。

def concreter(abclass):
    """
    >>> import abc
    >>> class Abstract(metaclass=abc.ABCMeta):
    ...     @abc.abstractmethod
    ...     def bar(self):
    ...        return None

    >>> c = concreter(Abstract)
    >>> c.__name__
    'dummy_concrete_Abstract'
    >>> c().bar() # doctest: +ELLIPSIS
    (<abc_utils.Abstract object at 0x...>, (), {})
    """
    if not "__abstractmethods__" in abclass.__dict__:
        return abclass
    new_dict = abclass.__dict__.copy()
    for abstractmethod in abclass.__abstractmethods__:
        #replace each abc method or property with an identity function:
        new_dict[abstractmethod] = lambda x, *args, **kw: (x, args, kw)
    #creates a new class, with the overriden ABCs:
    return type("dummy_concrete_%s" % abclass.__name__, (abclass,), new_dict)
于 2012-03-18T14:57:34.830 に答える
4

いいえ、ちがいます。の目的は、abcすべての抽象属性が具体的な実装でオーバーライドされない限り、インスタンス化できないクラスを作成することです。したがって、抽象基本クラスから派生させ、すべての抽象メソッドとプロパティをオーバーライドする必要があります。

于 2012-03-18T09:45:03.960 に答える