#python #unit-testing #unittest2
#python #модульное тестирование #unittest2
Вопрос:
Я использую unittest2
on Python2.5
для обнаружения тестов с помощью unittest.TestLoader.discover
, вот так:
suite = unittest2.loader.TestLoader().discover(test_path)
unittest2.TextTestRunner(verbosity=2,
resultclass=ColorTestResult).run(suite)
для некоторых test_path
в основе моего проекта.
У меня есть базовый класс, который расширен и перегружен множеством других, но я хотел бы проверить, что эти производные не имеют регрессий. Давайте вызовем этот базовый класс A
и его производные A1
, A2
и т.д.
Я хотел бы создать unittest2.TestCase
базовый класс, который может быть перегружен для каждой из производных A
. Другими словами, я хотел бы иметь иерархию, подобную этой:
class A:
pass
class A1(A):
pass
class UT(unittest2.TestCase):
target = A
class UT2(UT):
target = A1
Теперь фокус в том, что я создаю A
абстрактный класс, и UT
практически все тестовые примеры, которые бы соответствовали UT2
, завершатся неудачей и т.д.
Мне кажется, что самым простым решением является то, чтобы unittest2 discover
каким-то образом «пропускал» UT
unittest2. Я думаю, это было бы возможно, поместив его в файл, отличный от одного соответствующего шаблона ‘test *.py’, хотя, похоже, это не так.
Существуют ли какие-либо решения для вышеупомянутого сценария, которые могли бы быть подходящими?
Я был бы благодарен за любые мысли и предложения.
Ответ №1:
Я предполагаю, что проблема в том, что UT2 наследуется от UT, поэтому модуль, в котором определен UT2, импортирует UT — и, следовательно, делает его доступным в пространстве имен модуля. Таким образом, даже если discovery не просматривает модуль, в котором определен UT, он все равно может найти тестовый набор в модуле UT2.
Это общая проблема с наличием базовых тестовых наборов, которые сами определяют тесты.
Есть несколько возможностей. Одним из них было бы предоставить UT через функцию, поэтому ваш модуль, содержащий UT2, импортирует функцию вместо UT напрямую:
class UT2(get_base_class()):
target = A1
Доступ к атрибутам в UT можно получить с помощью super().
Другим, возможно лучшим, решением было бы также сделать UT более абстрактным. Вы могли бы опустить цель в UT (поскольку, похоже, это не имеет смысла?) и вызвать программу установки SkipTest, если цели нет (или если целью является A).
Третьим решением было бы, чтобы UT не наследовал от TestCase, а использовал его как смешанный:
class UT2(TestCase, UT):
target = A1