Как запустить тестовые случаи unittest в порядке их объявления

1

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

Я вижу, что есть способ установить порядок сортировки, установив атрибут sortTestMethodsUsing на тестовом загрузчике. По умолчанию используется простой вызов cmp() для лексического сравнения имен. Поэтому я попытался написать функцию cmp -like, которая бы взяла два имени, найти номера строк их деклараций и вернуть их cmp() -equivalent из них:

import unittest

class TestCaseB(unittest.TestCase):
    def test(self):
        print("running test case B")

class TestCaseA(unittest.TestCase):
    def test(self):
        print("running test case A")

import inspect
def get_decl_line_no(cls_name):
    cls = globals()[cls_name]
    return inspect.getsourcelines(cls)[1]

def sgn(x):
    return -1 if x < 0 else 1 if x > 0 else 0

def cmp_class_names_by_decl_order(cls_a, cls_b):
    a = get_decl_line_no(cls_a)
    b = get_decl_line_no(cls_b)
    return sgn(a - b)

unittest.defaultTestLoader.sortTestMethodsUsing = cmp_class_names_by_decl_order
unittest.main()

Когда я запускаю это, я получаю этот вывод:

running test case A
.running test case B
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

что тестовые примеры не выполняются в заказе декларации.

Моя функция сортировки просто не вызвана, поэтому я подозреваю, что main() создает новый тестовый загрузчик, который уничтожает мою функцию сортировки.

  • 0
    Можете ли вы привести минимальный воспроизводимый пример, демонстрирующий вашу проблему? Код, который вы разместили, не содержит никаких тестов, поэтому вам не нужно сортировать какие-либо тесты.
  • 0
    (Если это код , вы запускали, то есть ваш ответ: это ничего не сортировка , потому что нет ничего для сортировки.)
Показать ещё 7 комментариев
Теги:
python-3.x
python-unittest

2 ответа

0
Лучший ответ

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

import unittest

class TestCaseB(unittest.TestCase):
    def runTest(self):
        print("running test case B")

class TestCaseA(unittest.TestCase):
    def runTest(self):
        print("running test case A")


import inspect
def get_decl_line_no(cls):
    return inspect.getsourcelines(cls)[1]

# get all test cases defined in this module
test_case_classes = list(filter(lambda c: c.__name__ in globals(), 
                                unittest.TestCase.__subclasses__()))

# sort them by decl line no
test_case_classes.sort(key=get_decl_line_no)

# make into a suite and run it
suite = unittest.TestSuite(cls() for cls in test_case_classes)
unittest.TextTestRunner().run(suite)

Это дает желаемый результат:

running test case B
.running test case A
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

Важно отметить, что метод тестирования в каждом классе должен быть назван runTest.

0

Как указано в названии, sortTestMethodsUsing используется для сортировки методов тестирования. Он не используется для сортировки классов. (Он не используется для сортировки методов в разных классах, отдельные классы обрабатываются отдельно.)

Если у вас было два метода тестирования в одном классе, sortTestMethodsUsing будет использоваться для определения их порядка. (В этот момент вы получите исключение, потому что ваша функция ожидает имена классов.)

  • 0
    Хотя это дает некоторое представление о том, почему метод, который я пробовал в моем примере кода, не будет делать то, что я хочу, я не уверен, что это квалифицируется как «ответ» на реальный вопрос.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню