Можно ли заставить Nose запускать только тесты, которые являются подклассами TestCase или TestSuite (например, unittest.main ()) - PullRequest
5 голосов
/ 24 июня 2010

Моя тестовая среда в настоящее время основана на утилите test-runner, которая сама является производной от python-тестировщика Eclipse pydev. Я переключаюсь на использование Nose, который обладает многими функциями моего собственного тестового прогона, но, кажется, код лучшего качества.

Мой набор тестов включает несколько абстрактных классов тестирования, которые ранее никогда не выполнялись. Стандартный тестер Python (и мой собственный) запускал только экземпляры unittest.TestCase и unittest.TestSuite.

Я заметил, что с тех пор, как я переключился на Nose, он запускает практически все, что начинается с имени «test», что раздражает ... потому что соглашение об именах, которое мы использовали для test-mixins, также похоже на тестовый класс для Nose , Ранее они никогда не выполнялись как тесты, потому что они не были экземплярами TestCase или TestSuite.

Очевидно, я мог бы переименовать методы, чтобы исключить слово «тест» из их имен ... это заняло бы некоторое время, потому что тестовая структура очень большая и имеет большое наследование. С другой стороны, было бы замечательно, если бы был способ заставить Nose видеть только TestCases и TestSuites как работоспособные ... и больше ничего.

Можно ли это сделать?

Ответы [ 5 ]

6 голосов
/ 25 июня 2010

Вы можете попробовать сыграть с опцией -m для nosetests.Из документации:

Тестовый класс - это класс, определенный в тестовом модуле, который соответствует testMatch, или подкласс unittest.TestCase

-m устанавливает, что testMatch таким образом вы можете отключить тестирование всего, что начинается с test .

Другое дело, что вы можете добавить __test__ = False к объявлению класса тестового набора, чтобы пометить его как «не тест».

2 голосов
/ 23 апреля 2015

Если вам нужен действительно абстрактный тестовый класс, вы можете просто наследовать абстрактный класс от объекта, а потом наследовать в тестовых случаях.

Например:

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.

0 голосов
/ 08 декабря 2016

Вы также можете использовать множественное наследование на уровне тестового набора и позволить базовому классу наследовать только от 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) 
0 голосов
/ 04 сентября 2016

Одно дополнение к ответу @nailxx:

Вы можете установить __test__ = False в родительском классе, а затем использовать метакласс (см. Этот вопрос снекоторые блестящие объяснения) установить его обратно в True при создании подклассов.

(Наконец, я нашел оправдание использованию метакласса!)

Хотя __test__ являетсяАтрибут двойного подчеркивания, мы должны явно установить его на True, так как его установка не заставит python просто искать атрибут дальше по MRO и оценивать его как False.

Таким образом, нам нужно проверить в экземпляре класса, имеет ли один из родительских классов __test__ = False.Если это так и текущее определение класса не установило __test__, мы добавим '__test__': True к атрибуту dict.

Полученный код выглядит следующим образом:

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 автоматически», но я бы для себя оставил явное назначение для ясности.


ПозвольтеЯ вставляю простые юнит-тесты, чтобы продемонстрировать поведение - и как напоминание, что всем нужно потратить две минуты, чтобы протестировать свой код после введения функции.

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__')
0 голосов
/ 30 ноября 2012

Вы можете использовать аргумент носа --attr, чтобы указать атрибут, принадлежащий unittest.TestCase. Например, я использую:

nosetests --attr="assertAlmostEqual"

Вы можете стать еще более осторожным, используя и и или , соответствующие:

nosetests -A "assertAlmostEqual or addTest"

См. документацию unittest для получения полного списка методов / атрибутов, а также описание возможностей плагина --attr .

.
...