Модульный тест Python с базовым и подклассом - PullRequest
124 голосов
/ 24 августа 2009

В настоящее время у меня есть несколько модульных тестов, которые используют общий набор тестов. Вот пример:

import unittest

class BaseTest(unittest.TestCase):

    def testCommon(self):
        print 'Calling BaseTest:testCommon'
        value = 5
        self.assertEquals(value, 5)

class SubTest1(BaseTest):

    def testSub1(self):
        print 'Calling SubTest1:testSub1'
        sub = 3
        self.assertEquals(sub, 3)


class SubTest2(BaseTest):

    def testSub2(self):
        print 'Calling SubTest2:testSub2'
        sub = 4
        self.assertEquals(sub, 4)

if __name__ == '__main__':
    unittest.main()

Вывод выше:

Calling BaseTest:testCommon
.Calling BaseTest:testCommon
.Calling SubTest1:testSub1
.Calling BaseTest:testCommon
.Calling SubTest2:testSub2
.
----------------------------------------------------------------------
Ran 5 tests in 0.000s

OK

Есть ли способ переписать вышесказанное так, чтобы самый первый testCommon не вызывался?

EDIT: Вместо запуска 5 тестов, указанных выше, я хочу, чтобы он выполнял только 4 теста, 2 из SubTest1 и еще 2 из SubTest2. Кажется, что Python unittest запускает оригинальный BaseTest сам по себе, и мне нужен механизм, чтобы предотвратить это.

Ответы [ 14 ]

0 голосов
/ 04 июля 2018

Начиная с Python 3.2, вы можете добавить функцию test_loader в модуль, чтобы контролировать, какие тесты (если таковые имеются) обнаруживаются механизмом обнаружения тестов.

Например, следующее будет загружать только тестовые примеры SubTest1 и SubTest2 исходного плаката, игнорируя Base:

def load_tests(loader, standard_tests, pattern):
    suite = TestSuite()
    suite.addTests([SubTest1, SubTest2])
    return suite

Должна быть возможность итерации по standard_tests (TestSuite, содержащему тесты, найденный загрузчик по умолчанию) и вместо этого скопировать все, кроме Base в suite, но вложенная природа TestSuite.__iter__ делает намного сложнее.

0 голосов
/ 09 мая 2018

Так что это своего рода старая тема, но я столкнулся с этой проблемой сегодня и подумал о своем собственном взломе. Он использует декоратор, который делает значения функций None при обращении через базовый класс. Не нужно беспокоиться о настройке и настройке класса, потому что если в базовом классе нет тестов, они не запустятся.

import types
import unittest


class FunctionValueOverride(object):
    def __init__(self, cls, default, override=None):
        self.cls = cls
        self.default = default
        self.override = override

    def __get__(self, obj, klass):
        if klass == self.cls:
            return self.override
        else:
            if obj:
                return types.MethodType(self.default, obj)
            else:
                return self.default


def fixture(cls):
    for t in vars(cls):
        if not callable(getattr(cls, t)) or t[:4] != "test":
            continue
        setattr(cls, t, FunctionValueOverride(cls, getattr(cls, t)))
    return cls


@fixture
class BaseTest(unittest.TestCase):
    def testCommon(self):
        print('Calling BaseTest:testCommon')
        value = 5
        self.assertEqual(value, 5)


class SubTest1(BaseTest):
    def testSub1(self):
        print('Calling SubTest1:testSub1')
        sub = 3
        self.assertEqual(sub, 3)


class SubTest2(BaseTest):

    def testSub2(self):
        print('Calling SubTest2:testSub2')
        sub = 4
        self.assertEqual(sub, 4)

if __name__ == '__main__':
    unittest.main()
0 голосов
/ 18 сентября 2015

Просто переименуйте метод testCommon во что-то другое. Unittest (обычно) пропускает все, что не имеет «test».

Быстрый и простой

  import unittest

  class BaseTest(unittest.TestCase):

   def methodCommon(self):
       print 'Calling BaseTest:testCommon'
       value = 5
       self.assertEquals(value, 5)

  class SubTest1(BaseTest):

      def testSub1(self):
          print 'Calling SubTest1:testSub1'
          sub = 3
          self.assertEquals(sub, 3)


  class SubTest2(BaseTest):

      def testSub2(self):
          print 'Calling SubTest2:testSub2'
          sub = 4
          self.assertEquals(sub, 4)

  if __name__ == '__main__':
      unittest.main()`
0 голосов
/ 24 августа 2009

Измените имя метода BaseTest на setUp:

class BaseTest(unittest.TestCase):
    def setUp(self):
        print 'Calling BaseTest:testCommon'
        value = 5
        self.assertEquals(value, 5)


class SubTest1(BaseTest):
    def testSub1(self):
        print 'Calling SubTest1:testSub1'
        sub = 3
        self.assertEquals(sub, 3)


class SubTest2(BaseTest):
    def testSub2(self):
        print 'Calling SubTest2:testSub2'
        sub = 4
        self.assertEquals(sub, 4)

Выход:

Выполнено 2 теста за 0,000 с

Вызов BaseTest: testCommon Calling
SubTest1: testSub1 Calling
BaseTest: testCommon Calling
Подтест2: testSub2

Из документации :

TestCase.setUp ()
Метод призван подготовить тестовый прибор. Это позвонил непосредственно перед вызовом Метод испытания; любое исключение, вызванное этот метод будет считаться ошибка, а не провал теста. реализация по умолчанию ничего не делает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...