6

私のテストフレームワークは現在、Eclipse pydevpythontest-runnerから派生したtest-runnerユーティリティに基づいています。カスタムテストランナーの機能の多くを備えているが、より高品質のコードのように見えるNoseを使用するように切り替えています。

私のテストスイートには、これまで実行されたことのない抽象的なテストクラスがいくつか含まれています。標準のPythonテストランナー(および私のカスタムテストランナー)は、unittest.TestCaseおよびunittest.TestSuiteのインスタンスのみを実行しました。

Noseに切り替えてから、「test」という名前で始まるほとんどすべてが実行されていることに気付きました。これは、テストミックスインに使用した命名規則もNoseのテストクラスのように見えるためです。以前は、これらはTestCaseまたはTestSuiteのインスタンスではなかったため、テストとして実行されることはありませんでした。

明らかに、メソッドの名前を変更して、名前から「test」という単語を除外することができます...テストフレームワークが非常に大きく、多くの継承があるため、時間がかかります。一方、NoseがTestCasesとTestSuitesのみを実行可能であると見なす方法があれば、それは素晴らしいことです...そして他には何もありません。

これはできますか?

4

5 に答える 5

6

-mのオプションで遊んでみることができますnosetests。ドキュメントから:

テストクラスは、testMatchに一致するか、unittest.TestCaseのサブクラスであるテストモジュールで定義されたクラスです。

-mこれを設定すると、 testtestMatchで始まるもののテストを無効にできます。

もう1つは__test__ = False、テストケースクラス宣言に追加して、「テストではない」とマークできることです。

于 2010-06-25T13:57:25.523 に答える
2

真に抽象的なテストクラスが必要な場合は、オブジェクトから抽象クラスを継承し、後でテストケースに継承することができます。

例えば:

class AbstractTestcases(object):
    def test_my_function_does_something(self):
        self.assertEquals("bar", self.func())

そして、それを次のように使用します。

class TestMyFooFunc(AbstractTestcases, unittest.TestCase):
    def setUp(self):
        self.func = lambda: "foo"

次にnosetests、のテストケースのみを取得し、のテストケースは取得しTestMyFooFuncませんAbstractTestCases

于 2015-04-23T01:06:41.653 に答える
1

noseの--attr引数を使用して、unittest.TestCaseによって提示される属性を指定できます。たとえば、私は以下を使用します。

nosetests --attr="assertAlmostEqual"

and andまたはmatchingを使用すると、さらに注意を払うことができます。

nosetests -A "assertAlmostEqual or addTest"

メソッド/属性の完全なリストについては、unittestのドキュメントを参照してください。また、-attrプラグインの機能に関するNoseの説明を参照してください。

于 2012-11-30T02:36:19.440 に答える
0

@nailxxの回答に対する1つの補遺:

__test__ = False親クラスを設定してから、メタクラスを使用して(いくつかのすばらしい説明とともにこの質問を参照)、サブクラス化するときにTrueに戻すことができます。

(最後に、メタクラスを使用する言い訳を見つけました!)

__test__二重アンダースコア属性ですが、明示的に設定する必要Trueがあります。設定しないと、Pythonは属性をMROのさらに上で検索し、評価するだけになるためFalseです。

したがって、クラスのインスタンス化時に、親クラスの1つにが含まれているかどうかを確認する必要があります__test__ = False。これが当てはまり、現在のクラス定義がそれ自体を設定していない場合は、属性dictに__test__追加します。'__test__': True

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

class TestWhenSubclassedMeta(type):
    """Metaclass that sets `__test__` back to `True` when subclassed.

    Usage:

        >>> class GenericTestCase(TestCase, metaclass=TestWhenSubclassed):
        ...     __test__ = False
        ...
        ...     def test_something(self):
        ...         self.fail("This test is executed in a subclass, only.")
        ...
        ...
        >>> class SpecificTestCase(GenericTestCase):
        ...     pass

    """

    def __new__(mcs, name, bases, attrs):
        ATTR_NAME = '__test__'
        VALUE_TO_RESET = False
        RESET_VALUE = True

        values = [getattr(base, ATTR_NAME) for base in bases
                  if hasattr(base, ATTR_NAME)]

        # only reset if the first attribute is `VALUE_TO_RESET`
        try:
            first_value = values[0]
        except IndexError:
            pass
        else:
            if first_value == VALUE_TO_RESET and ATTR_NAME not in attrs:
                attrs[ATTR_NAME] = RESET_VALUE

        return super().__new__(mcs, name, bases, attrs)

これを「名前がで始まる場合は自動的Abstractに設定する」などのより暗黙的な動作に拡張することもでき__test__ = Falseますが、わかりやすくするために、私自身は明示的な割り当てを維持します。


動作を示すために簡単な単体テストを貼り付けましょう。機能を導入した後、全員がコードをテストするのに2分かかることを思い出してください。

from unittest import TestCase

from .base import TestWhenSubclassedMeta


class SubclassesTestCase(TestCase):
    def test_subclass_resetted(self):
        class Base(metaclass=TestWhenSubclassedMeta):
            __test__ = False

        class C(Base):
            pass

        self.assertTrue(C.__test__)
        self.assertIn('__test__', C.__dict__)

    def test_subclass_not_resetted(self):
        class Base(metaclass=TestWhenSubclassedMeta):
            __test__ = True

        class C(Base):
            pass

        self.assertTrue(C.__test__)
        self.assertNotIn('__test__', C.__dict__)

    def test_subclass_attr_not_set(self):
        class Base(metaclass=TestWhenSubclassedMeta):
            pass

        class C(Base):
            pass

        with self.assertRaises(AttributeError):
            getattr(C, '__test__')
于 2016-09-04T15:25:17.050 に答える
0

テストケースレベルで多重継承を使用して、基本クラスobjectのみから継承させることもできます。このスレッドを参照してください:

class MyBase(object):
   def finishsetup(self):
       self.z=self.x+self.y

   def test1(self):
       self.assertEqual(self.z, self.x+self.y)

   def test2(self):
       self.assert_(self.x > self.y)

class RealCase1(MyBase, unittest.TestCase):
   def setUp(self):
       self.x=10
       self.y=5
       MyBase.finishsetup(self)

class RealCase2(MyBase, unittest.TestCase):
   def setUp(self):
       self.x=42
       self.y=13
       MyBase.finishsetup(self) 
于 2016-12-08T16:40:14.497 に答える