Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 是否可以使Nose只运行TestCase或TestSuite的子类(如unittest.main())的测试_Python_Unit Testing_Nose - Fatal编程技术网

Python 是否可以使Nose只运行TestCase或TestSuite的子类(如unittest.main())的测试

Python 是否可以使Nose只运行TestCase或TestSuite的子类(如unittest.main())的测试,python,unit-testing,nose,Python,Unit Testing,Nose,我的测试框架目前基于一个测试运行程序实用程序,它本身是从EclipsePydevPython测试运行程序派生的。我正在改用Nose,它具有我定制的测试运行程序的许多特性,但似乎是质量更好的代码 我的测试套件包括许多以前从未运行过的抽象测试类。标准python testrunner(以及我的自定义运行程序)只运行unittest.TestCase和unittest.TestSuite的实例 我注意到,自从我切换到Nose之后,它几乎可以运行任何以“test”这个名字开头的东西,这很烦人。。。因为我

我的测试框架目前基于一个测试运行程序实用程序,它本身是从EclipsePydevPython测试运行程序派生的。我正在改用Nose,它具有我定制的测试运行程序的许多特性,但似乎是质量更好的代码

我的测试套件包括许多以前从未运行过的抽象测试类。标准python testrunner(以及我的自定义运行程序)只运行unittest.TestCase和unittest.TestSuite的实例

我注意到,自从我切换到Nose之后,它几乎可以运行任何以“test”这个名字开头的东西,这很烦人。。。因为我们用于测试mixin的命名约定对Nose来说也像一个测试类。以前,它们从未作为测试运行,因为它们不是TestCase或TestSuite的实例

显然,我可以重新命名这些方法,将“test”一词从它们的名称中排除。。。这需要一段时间,因为测试框架非常大,并且有很多继承性。另一方面,如果有一种方法可以让Nose只看到可运行的测试用例和测试套件,那将是一件好事。。。没有别的了


可以这样做吗?

您可以尝试使用
-m
选项进行
鼻测试。从文件:

测试类是在 与testMatch或testMatch匹配的测试模块 是unittest.TestCase的子类

-m
设置
testMatch
,这样您可以禁用从test开始的任何测试

另一件事是,您可以向测试用例类声明中添加
\uuuuu test\uu=False
,将其标记为“非测试”。

您可以使用nose的--attr参数指定unittest.TestCase所拥有的属性。例如,我使用:

nosetests --attr="assertAlmostEqual"
通过使用and或匹配,您可以更加小心:

nosetests -A "assertAlmostEqual or addTest"

有关方法/属性和Nose的完整列表,请参阅。

如果您想要一个真正抽象的测试类,您可以从object继承抽象类,然后在稍后的测试用例中继承

例如:

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
中的测试用例,一个@nalxx答案的附录:

您可以在父类中设置
\uuuuu test\uuu=False
,然后在子类化时使用元类(请参阅,并提供一些精彩的解释)将其设置回True

(最后,我找到了一个使用元类的借口!)

尽管
\uuuu test\uuuu
是一个双下划线属性,但我们必须显式地将其设置为
True
,因为不设置它将导致python只是进一步查找属性并将其计算为
False

因此,我们需要在类实例化时检查父类之一是否具有
\uuuuu test\uuuu=False
。如果是这种情况,并且当前的类定义没有设置
\uuuuuuuuuuuuuuuuuuu
本身,我们将在属性dict中添加
''uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu':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
开头,则自动设置
\uuuuu test\uuuu=False
”,但为了清晰起见,我会保留显式赋值


让我粘贴一些简单的单元测试来演示这种行为——并提醒大家,在引入一个特性之后,每个人都应该花两分钟来测试他们的代码

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__')

您还可以在测试用例级别上使用多重继承,并让基类仅从
对象继承。见:


这是避免问题的好方法,但是抽象测试在我的IDE中是不可读的。
\uuuu test\uuuu=False
技巧在父类的情况下不是很有用,这将迫使子类显式指定
\uuuu test\uuuu=True
,这是一个危险的伎俩。这不是最漂亮的解决方案,但与其他建议相比,它确实有效。非常感谢。
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)