Может ли Python unittest автоматически повторить неудачный тестовый набор / набор? - PullRequest
5 голосов
/ 22 августа 2011

Краткий вопрос
Можно ли повторить попытку юнит-теста при сбое / ошибке N раз ИЛИ на основе предварительно определенной функции.(Как приглашение пользователя)

Фон
Чтобы не перепечатывать всю страницу системной информации, см. Вопрос SO на передача данных на юнит-тесты и на обнаружение автоматического теста для получения более подробной информации о моей физической настройке.

Что касается рассматриваемого вопроса, я знаю, что могу сделать это, переписав мои тестовые сценарии для цикла, пока он не получит требуемые результаты (см. Псевдокод ниже), а затем утвердить на основе этого.Однако я бы не стал переписывать сотни тестовых случаев.

Я найду кого-то, кто укажет, что если тест на юнит провалится, он должен просто потерпеть неудачу и это будет сделано.Я согласен с этим 100% , если человеческая ошибка может быть устранена.Это физическая система, к которой я подключен, и во многих случаях выводы цифрового мультиметра плохо подключены, и она может выйти из строя из-за слабого соединения.

Обходной путь псевдообмена

class Suite_VoltageRegulator(unittest.TestCase):
    def test_voltage_5v_regulator(self):   
        keep_running = 'y'
        error_detected = False

        print '\n'     
        # Display User Test Configuration
        msg = \
            '1) Connect Front DMM GND(black) to the TP_COM\n' +\
            '2) Connect Front DMM POS(red) to the TP-A\n' +\
            '3) Ensure the DMM terminal button indicates FRONT'

        continue_test = prompt.Prompt_Ok_Cancel('User Action Required!', msg)

        if not continue_test:
            self.assertTrue(False, 'User Canceled Test!')

        while(keep_running == 'y'):
            try:
                # Run the test
                results = measure_voltage_from_system() 

                # Analyze Results
                test_status = pf.value_within_range(results, REGULATOR_5V_LOW, REGULATOR_5V_HIGH)

            catch:
                error_detected = True

            # Retest Failed Cards
            if(test_status == False):
                keep_running = rawinput('Test FAILED: Retry Test? (y/n):')
            elif(error_detected == True):
                keep_running = rawinput('Test ERROR: Retry Test? (y/n):')
            else:
                keep_running = 'n'

        # Inform the user on the test results 
        self.assertTrue(test_status,  'FAIL: 5V Regulator (' +str(results)+ ') Out of Range!')

РЕДАКТИРОВАНИЕ 22.08.11 15:30 CST
Я знаю, что нарушаю определение unittest в этом сценарии использования.Эти вопросы / комментарии также рассматриваются в нескольких других моих SO вопросах.Одна из целей разработки, которую мы выбрали, состояла в том, чтобы использовать существующую структуру, чтобы избежать необходимости «изобретать велосипед».Тот факт, что мы выбрали юнит-тест python, основывался не на его определении, а на его гибкости и надежности для выполнения и отображения серии тестов.

Переходя к этому проекту, я знал, что будут некоторые вещи, которые потребуют обходных путей, потому что этот модуль не предназначен для этого использования.На данный момент я все еще верю, что эти обходные пути были проще / дешевле, чем переписывать мой собственный тест-бегун.

РЕДАКТИРОВАТЬ 22.08.11 17:22 CST
Я не намерен использовать unittest для будущих проектов таким образом, однако я честно настроен на использование существующего фреймастараться не дублировать чужие усилия.Комментарий ниже является примером этого pycopia-QA , как представляется, хорошо подходит для этого проекта.Единственный недостаток моего текущего проекта - это то, что я написал сотни тестовых примеров для юнит-тестов, и если бы я переписал их, это было бы очень трудоемким делом (учитывая, что это также будет не финансируемое мероприятие)

РЕДАКТИРОВАТЬ 24.08.11 11:00 CST
Для будущих проектов может быть очевидным, что для этого типа тестирования может потребоваться перейти на более специализированные рамки.Тем не менее, у меня все еще есть проекты, запущенные с unittest, поэтому все еще нужно решение, использующее только unittest (или нос + 3-й аддон).

Ответы [ 4 ]

4 голосов
/ 23 августа 2011

Модуль юнит-теста Python предназначен для написания юнит-тестов Python. ;-) Это не очень хорошо подходит для других видов тестирования. Пакет nose также является структурой модульного тестирования.

Я написал несколько тестовых сред на Python, которые предназначены для тестирования систем. Системы могут быть распределены и автоматизированы с различными интерфейсами. Два с открытым исходным кодом.

Проект Pycopia представляет собой набор модулей Python, работающих на Linux. Он предоставляется в виде коллекции подпакетов пространства имен, одним из которых является пакет QA, представляющий собой среду тестирования.

Подмножество этого называется powerdroid , и оно предназначено для управления измерительными приборами для проведения физических измерений (таких как напряжение, ток и т. Д.) Через. RS-232, IEEE-488 и т. Д. Он предоставляет альтернативный интерфейс Python для проекта linux-gpib.

Так что вы можете начать с них, а не "изобретать велосипед", если хотите. Возможно, вам не придется выбрасывать существующие тесты, поскольку среда может вызвать любой подпроцесс, с которым вы можете запустить существующие тесты. Это также работает в Linux.

4 голосов
/ 27 августа 2015

4 года спустя после первоначального вопроса - я надеюсь, что кому-нибудь все равно :) Вот мое решение сделать это на вершине unittest.Это некрасиво и зависит от реализации базового класса TestCase, но работает.

class MyTest(unittest.TestCase):
    ###
    ### Insert test methods here
    ###

    # Wrapping each test method so that a retry would take place.  
    def run(self, result=None):
        self.origTestMethodName = self._testMethodName
        self._testMethodName = "_testRetryWrapper"
        super(MyTest, self).run(result)
        self._testMethodName = self.origTestMethodName

    def _testRetryWrapper(self):
        testMethod = getattr(self, self.origTestMethodName)
        retryAttemptsLeft = settings.testRetryCount

        while True:
            try:
                testMethod()
                break
            except:
                if retryAttemptsLeft == 0:
                    raise
                else:
                    retryAttemptsLeft = retryAttemptsLeft - 1
1 голос
/ 11 декабря 2017

Я немного улучшил ответ Шломи Кирали, чтобы он не нарушал структуру unittest, и пропуск тестовых примеров все еще работает:

class MyTest(unittest.TestCase):

#Eanble retries if specified in configuration file by attribute testRetryCount
def run(self, result=None):
    self.origTestMethodName = self._testMethodName
    retryAttemptsLeft = configuration.testRetryCount

    failuresBefore = len(result.failures) #check how many tests that are marked as failed before starting
    errorsBefore = len(result.errors) #check how many tests that are marked as failed before starting

    super(MyTest, self).run(result)
    if failuresBefore < len(result.failures): # If last test failed
        while True:
            if retryAttemptsLeft == 0:
                self.logger.error("Test failed after "+str(configuration.testRetryCount+1)+" attempts")
                break
            else:
                result.failures.pop(-1) #Removing last failure result
                self.logger.error("Test failed - retryAttemptsLeft: "+str(retryAttemptsLeft))
                retryAttemptsLeft = retryAttemptsLeft - 1

                super(MyTest, self).run(result)

    elif errorsBefore < len(result.errors): # If last test failed due to error
        while True:
            if retryAttemptsLeft == 0:
                self.logger.error("Test error after "+str(configuration.testRetryCount+1)+" attempts")
                break
            else:
                result.errors.pop(-1) #Removing last error result
                self.logger.error("Test error - retryAttemptsLeft: "+str(retryAttemptsLeft))
                retryAttemptsLeft = retryAttemptsLeft - 1

                super(MyTest, self).run(result)
1 голос
/ 23 августа 2011

Я думаю, что вы должны написать свою собственную специализированную среду - вы могли бы также смоделировать ее на модульном тесте python, но это явно не тест unit .Вам нужно будет внести некоторые изменения, например, чтобы позволить каждому тесту быть отдельно пропущенным, повторным или повторным проверкой, а затем, в конце концов, иметь возможность пересмотреть и повторно протестировать неудачные тесты со статистикой, показывающей, сколькотесты прошли в первый раз, сколько времени они прошли, какое тестирование заняло больше всего времени, сколько повторных попыток им нужно было сделать и т. д.

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