Инициализация юнит-теста в PyDev? - PullRequest
11 голосов
/ 25 марта 2011

Я тестирую мой код на python в eclipse, используя модульное тестирование PyDev. Я щелкаю правой кнопкой мыши по соответствующему файлу и выбираю Run As -> Python unit-test . По поводу этого плагина у меня есть несколько вопросов:

  1. Есть ли способ иметь метод setUpClass , который выполняется перед любым другим тестом в этом классе? В настоящее время я могу только заставить работать setUp , который вызывается перед любым тестом класса
  2. Есть ли способ иметь глобальную инициализацию, которая вызывается перед выполнением какого-либо теста? Что-то вроде setUpModule , который я также не могу запустить с помощью модульного тестирования PyDev.

Заранее спасибо за любой ответ и комментарий ^^
Черио Волтан

Пример: * ** 1022 тысячу двадцать одна * class TestClass(unittest.TestCase): @classmethod def setUpClass(self): print "Setup" def test1(self): print "Test1" def test2(self): print "Test2" Если я запускаю это с Run As -> Python unit-test setUpClass метод не вызывается.

Ответы [ 4 ]

7 голосов
/ 07 апреля 2011

Это ошибка PyDev, исправленная в 2.0.1.

setUpModule(), tearDownModule(), setUpClass() и tearDownClass() не запускаются в конфигурации запуска «Python unit-test» из-за ошибки в PyDev 2.0.0 и более ранних версиях. В 2.0.1 они работают правильно в конфигурациях «Python unit-test» и «Python Run». Я проверил это сам, чтобы проверить.

5 голосов
/ 30 марта 2011

Хорошо, я сделаю это: я использую Pydev и изучаю использование «тестов на нос» для запуска тестов, так что это как-то уместно. Мое решение - полный взлом, но, похоже, работает, когда говорит "Отладка как UnitTest" из PyDev:

print "before any tests (global) just once..."
class MyTestCase(unittest.TestCase):
   class_setup_called = False
   def __init__(self, test_name):
      unittest.TestCase.__init__(self, test_name)
      if not self.__class__.class_setup_called:
          self.setUpClass()
          self.__class__.class_setup_called = True
   @staticmethod
   def setUpClass():
      print "before first test only..."
   def setUp(self):
      print "before each test..."

К сожалению, это не работает при использовании тестов носа, но работает при запуске из pydev. Я предполагаю, что тесты носа кодируются для создания экземпляров тестовых объектов перед запуском каждого метода тестирования, и в этом случае будет достаточно вашего метода init.

Я не могу сказать достаточно хороших слов о тестах на нос:

  • поддержка исключений и времени тесты.
  • поддержка аннотации "атрибуция".
  • интеграция с профилем, покрытием и отчетом о результатах xunit.
  • рекурсивное обнаружение и атрибутивное выполнение тестовых случаев.

Примеры:

import unittest
@raises(TypeError)          
def test_forexceptions(self): 
    pass

@attr('benchmark')
@timed(5.0)
def test_benchmark(self):
    pass # do something real slow and run nosetests --with-profile -a benchmark

Дополнительный

Дальнейшее расследование, если вы используете тесты на нос, тогда оно покрывает вас, см. "http://somethingaboutorange.com/mrl/projects/nose/1.0.0/writing_tests.html".

Вы можете иметь:

Разборка на уровне пакета: (они существуют в сценариях инициализации на уровне пакета)

def setup_package()
def teardown_package()

Разрыв уровня модуля:

def setup_module()
def teardown_module()

уровень класса:

class MyTestCase(unittest.TestCase):
    @classmethod
    def setup_class(cls): pass
    @classmethod
    def teardown_class(cls): pass

и уровень метода тестирования:

class MyTestCase(unittest.TestCase):
    def setUp(self): pass
    def tearDown(cls): pass

Мне нравится использовать имена "setup_", так как они хорошо очерчивают определенные точки входа в нос. Я хорошо проверил эту работу, когда запускался из носовых тестов через командную строку. Но они не запускаются из Pydev "запустить как модульный тест ...". Потенциальным решением может быть написание плагина pydev, который использует нос для запуска тестов ... возможно, у кого-то есть такой? Вы могли бы объединить мой взлом с носом, вызывающим общие функции модуля для выполнения реальной работы. В идеале наш init () должен был бы знать, что его каким-то образом запустили из Pydev.

2 голосов
/ 04 апреля 2011

Редактировать: Резюме

Проходя через ваш тестовый пример с помощью отладчика, похоже, что это ограничение запуска программы PyDev, не поддерживающего setUpClass(), по крайней мере, не с 1.6.5, который я использую.

Возможно, это будет исправлено в v2.0 PyDev, но в то же время, я думаю, нам придется придерживаться вместо использования __init__(), как предполагает CarlS .

Подробнее

Класс PyDev 1.6.5 PyDevTestSuite использует:

def run(self, result):
    for index, test in enumerate(self._tests):
        if result.shouldStop:
            break
        test(result)

        # Let the memory be released! 
        self._tests[index] = None

    return result

, который очень похож на TestSuite.run () в python 2.6, тогда как TestSuite.run () в unittest Python 2.7.1 делает гораздо больше:

def run(self, result, debug=False):
    topLevel = False
    if getattr(result, '_testRunEntered', False) is False:
        result._testRunEntered = topLevel = True

    for test in self:
        if result.shouldStop:
            break

        if _isnotsuite(test):
            self._tearDownPreviousClass(test, result)
            self._handleModuleFixture(test, result)
            self._handleClassSetUp(test, result)
            result._previousTestClass = test.__class__

            if (getattr(test.__class__, '_classSetupFailed', False) or
                getattr(result, '_moduleSetUpFailed', False)):
                continue

        if not debug:
            test(result)
        else:
            test.debug()

    if topLevel:
        self._tearDownPreviousClass(None, result)
        self._handleModuleTearDown(result)
    return result

Старый ответ

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

Если вы проверите Window> Preferences> PyDev> Interpreter - Python и посмотрите, какой интерпретатор Python используется, вы можете обнаружить, что это pre v2.7, где, если я правильно помню, был представлен setUpClass.

Ссылка на более новую версию python, и я подозреваю, что ваши тесты будут работать как есть.

0 голосов
/ 25 марта 2011

Вместо использования unittest.main(), который автоматически проходит все ваши тестовые классы и отдельные тесты, вы можете загружать тесты из каждого класса отдельно и выполнять их по своему усмотрению, включая перед каждым классом тестирование необходимых инициализаций.Вы можете предшествовать всему этому с некоторой глобальной инициализацией.См. Пример ниже:

import unittest

class MyTestClass1(unittest.TestCase):

    def setUp(self):
         pass

    @classmethod
    def setUpClass(cls):
        pass

    def test1(self):
         pass

    # lots of tests

class MyTestClass2(unittest.TestCase):

    def setUp(self):
         pass

    @classmethod
    def setUpClass(cls):
        pass

    def test1(self):
         pass

    # another whole lot of tests


if __name__=="__main__":
    # add your global initialization code here
    global_initialization()

    # MyTestClass1 initialization:
    MyTestClass1.setUpClass() # python 2.7 only

    suite = unittest.TestLoader().loadTestsFromTestCase(MyTestClass1)
    unittest.TextTestRunner().run(suite)

    # MyTestClass1 initialization:
    MyTestClass2.setUpClass() # python 2.7 only

    suite = unittest.TestLoader().loadTestsFromTestCase(MyTestClass2)
    unittest.TextTestRunner().run(suite)

Документация unittest имеет несколько других примеров аналогичного использования, которые могут оказаться полезными.

Редактировать: Пока мне неизвестно, кажется, что в Python 2.7 есть setUpClass() (должен быть методом класса, а значит, декоратором), который, кажется, делает то, что вам нужно.Однако в Python 2.6 это не так, и вы должны предоставить свои собственные процедуры инициализации.

...