Как задать условия для пропуска тестов в `unittest` и `pytest`?

unittest: Использовать декораторы:
  • @unittest.skip(reason): безусловный пропуск.
  • @unittest.skipIf(condition, reason): пропуск при выполнении условия.
  • @unittest.skipUnless(condition, reason): пропуск, если условие не выполнено.
Или метод self.skipTest(reason) внутри теста.

pytest: Использовать декораторы:
  • @pytest.mark.skip(reason): безусловный пропуск.
  • @pytest.mark.skipif(condition, reason): пропуск при выполнении условия.
Или функцию pytest.skip(reason) внутри теста.

В Python, как в unittest, так и в pytest, предусмотрены механизмы для пропуска тестов на основе определенных условий. Это полезно, когда тест не актуален в текущей среде, конфигурации или просто временно не должен выполняться.

В unittest:

unittest предоставляет несколько способов пропуска тестов:

  • unittest.skip(reason): Безусловный пропуск теста. reason – строка с описанием причины пропуска.
    import unittest
    
    class MyTest(unittest.TestCase):
        @unittest.skip("Причина пропуска: Временная недоступность ресурса")
        def test_skipped(self):
            self.fail("Этот тест должен быть пропущен")
    
  • unittest.skipIf(condition, reason): Пропуск теста, если condition истинно.
    import unittest
    import sys
    
    class MyTest(unittest.TestCase):
        @unittest.skipIf(sys.platform.startswith("win"), "Не запускать на Windows")
        def test_only_linux(self):
            print("Этот тест должен работать только на Linux")
            self.assertTrue(True)  # Пример утверждения
    
  • unittest.skipUnless(condition, reason): Пропуск теста, если condition ложно.
    import unittest
    import os
    
    class MyTest(unittest.TestCase):
        @unittest.skipUnless("MY_ENV_VAR" in os.environ, "Требуется переменная окружения MY_ENV_VAR")
        def test_needs_env_var(self):
            print("Этот тест требует переменную окружения MY_ENV_VAR")
            self.assertTrue(True)
    
  • unittest.expectedFailure(): Помечает тест, как ожидаемо проваленный. Тест все еще выполняется, но провал не считается ошибкой.
    import unittest
    
    class MyTest(unittest.TestCase):
        @unittest.expectedFailure
        def test_expected_failure(self):
            self.assertEqual(1, 2, "Этот тест должен провалиться")
    

Эти декораторы можно применять как к отдельным тестовым методам, так и ко всему классу тестов.

В pytest:

pytest предоставляет более гибкие способы для пропуска тестов:

  • pytest.mark.skip(reason): Безусловный пропуск теста.
    import pytest
    
    @pytest.mark.skip(reason="Временная недоступность API")
    def test_api_unavailable():
        assert True  # Пример утверждения
    
  • pytest.mark.skipif(condition, reason): Пропуск теста, если condition истинно.
    import pytest
    import sys
    
    @pytest.mark.skipif(sys.version_info < (3, 7), reason="Требуется Python 3.7 или выше")
    def test_python_version():
        assert True
    
  • pytest.skip(reason): Внутри тестовой функции можно вызвать pytest.skip(reason) для пропуска теста во время выполнения.
    import pytest
    
    def test_conditional_skip():
        if not check_something(): #какая то функция, возвращающая bool
            pytest.skip("Условие не выполнено, пропускаем тест")
        assert True
    
  • pytest.xfail(reason): Помечает тест как ожидаемо проваленный. Аналогично unittest.expectedFailure().
    import pytest
    
    @pytest.mark.xfail(reason="Известная ошибка")
    def test_known_failure():
        assert 1 == 2
    
  • Конфигурирование пропуска с помощью pytest.ini или pyproject.toml: Можно настроить пропуск тестов на основе маркеров или путей к файлам.

    Пример в pytest.ini:

    [pytest]
    markers =
        slow: mark test as slow to run
        database: mark test as requiring database
    

    Далее, можно использовать -m "not database" при запуске pytest, чтобы пропустить все тесты, помеченные как database.

Различия и рекомендации:

  • pytest предоставляет более декларативный и гибкий синтаксис (маркеры).
  • unittest в основном использует декораторы.
  • Используйте skipIf/skipUnless или skipif для условного пропуска тестов в зависимости от окружения, версии Python, наличия внешних зависимостей и т.д.
  • Всегда указывайте понятную причину пропуска (reason), чтобы было ясно, почему тест не выполняется.
  • xfail используйте для тестов, которые, как известно, не работают, но должны быть исправлены в будущем.
0