В рамках четвертой части цикла “Тестирование в Python [unittest]” изучим вопрос пропуска тестов. Будет рассмотрен условный и безусловный пропуск тестов, а также пропуск всех тестов внутри класса.
Подготовка
В качестве тестируемого модуля будем использовать расширенный модуль calc.py из части 3.
Модуль calc.py
def add(a, b): return a + b def sub(a, b): return a-b def mul(a, b): return a * b def div(a, b): return a / b def sqrt(a): return a**0.5 def pow(a, b): return a**b
Также возьмем оттуда модуль с тестами.
Модуль calc_tests.py
import unittest import calc class CalcBasicTests(unittest.TestCase): def test_add(self): self.assertEqual(calc.add(1, 2), 3) def test_sub(self): self.assertEqual(calc.sub(4, 2), 2) def test_mul(self): self.assertEqual(calc.mul(2, 5), 10) def test_div(self): self.assertEqual(calc.div(8, 4), 2) class CalcExTests(unittest.TestCase): def test_sqrt(self): self.assertEqual(calc.sqrt(4), 2) def test_pow(self): self.assertEqual(calc.pow(3, 3), 27)
И модуль для запуска тестов test_runner.py.
Модуль test_runner.py
import unittest import calc_tests calcTestSuite = unittest.TestSuite() calcTestSuite.addTest(unittest.makeSuite(calc_tests.CalcBasicTests)) calcTestSuite.addTest(unittest.makeSuite(calc_tests.CalcExTests)) runner = unittest.TextTestRunner(verbosity=2) runner.run(calcTestSuite)
Пропуск отдельных тестов в классе
Безусловный пропуск тестов
Для начала запустим модуль test_runner.py (о запуске тестов можно прочитать в третьей части цикла). Получим следующий результат:
test_add (calc_tests.CalcBasicTests) ... ok test_div (calc_tests.CalcBasicTests) ... ok test_mul (calc_tests.CalcBasicTests) ... ok test_sub (calc_tests.CalcBasicTests) ... ok test_pow (calc_tests.CalcExTests) ... ok test_sqrt (calc_tests.CalcExTests) ... ok ---------------------------------------------------------------------- Ran 6 tests in 0.002s OK
Исключим тест test_add из списка тестов. При попытке решить такую задачу, первое, что может прийти на ум – это удалить либо закомментировать данный тест. Но unittest предоставляет нам инструменты для удобного управление процессом пропуска тестов. Это может быть ещё полезно в том плане, что информацию о пропущенных тестах (их количестве) можно дополнительно получить через специальный API, предоставляемый классом TestResult. Для пропуска теста воспользуемся декоратором, который пишется перед тестом.
@unittest.skip(reason)
Модифицируем класс CalcBasicTests из модуля calc_tests.py:
class CalcBasicTests(unittest.TestCase): @unittest.skip("Temporaly skip test_add") def test_add(self): self.assertEqual(calc.add(1, 2), 3) def test_sub(self): self.assertEqual(calc.sub(4, 2), 2) def test_mul(self): self.assertEqual(calc.mul(2, 5), 10) def test_div(self): self.assertEqual(calc.div(8, 4), 2)
И снова запустим test_runner.py.
test_add (calc_tests.CalcBasicTests) ... skipped 'Temporarily skipped' test_div (calc_tests.CalcBasicTests) ... ok test_mul (calc_tests.CalcBasicTests) ... ok test_sub (calc_tests.CalcBasicTests) ... ok test_pow (calc_tests.CalcExTests) ... ok test_sqrt (calc_tests.CalcExTests) ... ok ---------------------------------------------------------------------- Ran 6 tests in 0.003s OK (skipped=1)
Как видно из примера, был пропущен один тест – test_add.
Условный пропуск тестов
Для условного пропуска тестов применяются следующие декораторы:
@unittest.skipIf(condition, reason)
Тест будет пропущен, если условие (condition) истинно.
@unittest.skipUnless(condition, reason)
Тест будет пропущен если, условие (condition) не истинно.
Условный пропуск тестов можно использовать в ситуациях, когда те или иные тесты зависят от версии программы, например: в новой версии уже не поддерживается часть методов; или тесты могут быть платформозависимые, например: ряд тестов могут выполняться только под операционной системой MS Windows. Условие записывается в параметр condition, текстовое описание – в reason.
Пропуск классов
Для пропуска классов используется декоратор
@unittest.skip(reason)
который записывается перед объявлением класса. В результате все тесты из данного класса не будут выполнены. В рамках нашего примера с математическими действиями, для исключения из процесса тестирования методов sqrt и pow поместим декоратор skip перед объявлением класса CalcExTests.
Модуль calc_tests.py
import unittest import calc class CalcBasicTests(unittest.TestCase): def test_add(self): self.assertEqual(calc.add(1, 2), 3) def test_sub(self): self.assertEqual(calc.sub(4, 2), 2) def test_mul(self): self.assertEqual(calc.mul(2, 5), 10) def test_div(self): self.assertEqual(calc.div(8, 4), 2) @unittest.skip("Skip CalcExTests") class CalcExTests(unittest.TestCase): def test_sqrt(self): self.assertEqual(calc.sqrt(4), 2) def test_pow(self): self.assertEqual(calc.pow(3, 3), 27)
Результат будет следующим:
test_add (calc_tests.CalcBasicTests) ... ok test_div (calc_tests.CalcBasicTests) ... ok test_mul (calc_tests.CalcBasicTests) ... ok test_sub (calc_tests.CalcBasicTests) ... ok test_pow (calc_tests.CalcExTests) ... skipped 'Skip CalcExTests' test_sqrt (calc_tests.CalcExTests) ... skipped 'Skip CalcExTests' ---------------------------------------------------------------------- Ran 6 tests in 0.001s OK (skipped=2)