How to skip tests based on condition in pytest?

8.7k views Asked by At

Below is the snippet of conftest.py, which accepts command line arguments.

conftest.py

import sys,json,pytest
import logging

def tear_down():
    logging.info(" tear-down after all tests")

def pytest_addoption(parser):

    parser.addoption("--a1", action="store", default="default_a1",
                     help="value of a1")

    parser.addoption("--b1", action="store", default="default_b1",
                     help="value of b1")


 @pytest.fixture(scope="class",autouse=True)
def set_up(request):
    logging.info("set-up before all tests")

    a1 = request.config.getoption("--a1")
    b1 = request.config.getoption("--b1")

    if request.cls.__name__ == 'Test1':
        return([a1,b1])

    request.addfinalizer(tear_down)

Below snippet is of test.py

Whenever the counter value not equal to 1 i.e., c1_1 != 1 (test_2) then it should skip all the following cases. Probably I can try checking this condition in each and every test-case and then pytest.skip or assert False. But this is not great idea.

I tried marker pytest.mark.skipif , but within that marker "can't access variable skip_all" (either "Test1.skip_all") I would like to skip tests based on certain condition. If my below approach is not right, please help me with right approach to skip tests based on condition.

test.py

import os,sys
import pytest
from other import other_class

a1_1 = b1_1 = c1_1 = ""

class Test1:
   skip_all = False

    def test_1(self,set_up):
        try:
            global a1_1,b1_1
            a1_1 = set_up[0]
            b1_1 = set_up[1]
        except Exception as err:
            logging.error(err)
            Test1.skip_all = True
            assert False, err
            
    @pytest.mark.skipif(skip_all == True, reason="Invalid")
    def test_2(self):
        global c1_1
        c1_1 = obj.func1(a1_1,b1_1)
        if c1_1 != 1:      #rest all test-cases shouldn't execute
           logging.error("Invalid")
           Test1.skip_all = True
           
        d1_1 = obj.func2(a1_1, c1_1)
        if d1_1 == 0:
           assert False, "zero"
        
    @pytest.mark.skipif(skip_all == True, reason="Zero")
    def test_3(self):
        d1_1 = obj.func2(b1_1, c1_1)
        if d1_1 == 0:
           assert False, "zero"

    @pytest.mark.skipif(skip_all == True, reason="Zero")
    def test_4(self):
       d1_1 = obj.func2(a1_1, c1_1)
       if d1_1 == 0:
          assert False, "zero"

obj = other_class()

Am I missing anything ? or anything to do with fixtures ? Is this possible ? Can anyone please let me know how to do that ?

In below example, how can we use external variable that's accessible in marker:skipif , instead of 'sys.platform'

import sys
import pytest

@pytest.mark.skipif(sys.platform != 'darwin', reason="Mac tests")
def test_mac():
    assert True

@pytest.mark.skipif(sys.platform != 'linux', reason="Linux tests")
def test_linux():
    assert True 

@pytest.mark.skipif(sys.platform != 'win32', reason="Windows tests")
def test_windows():
    assert True 

@pytest.mark.skip(reason="To show we can skip tests without any condition.")
def test_any():
    assert True
1

There are 1 answers

1
Gang On

first, a function skip_test()

def skip_test():
    return 1

# attention the quote and func call
skipmeif = pytest.mark.skipif("skip_test() == 1")

to skipif a function @skipmeif test_func1, to skipif a class do @skipmeif class TestSth

second, for the skip condition in your case, here is a possible solution but not sure fit your purpose

def skip_test():
    obj = SomeClass()
    c1 = obj.sth()
    return c1