Search code examples
pythonpycharmpytestfixturesparameterization

How to use a variable from setup fixture outside fixture


I want to use the product variable present inside setupone fixture outside it. I want to use it in test_title.py in skipif marker for conditional skipping (run the test case if product name satisfies). conftest.py

def pytest_addoption(parser):
    parser.addoption("--browser_name", action="store", default="chrome")
    parser.addoption("--env", action="store", default="Production")
    parser.addoption("--product_name", nargs = '*', type = str, action ="store", default="chitale")

products_list = getProductList()

@pytest.fixture(scope='class', params = products_list)
def setupone(request):
    browser = request.config.getoption("browser_name")
    env_name = request.config.getoption("env")
    product = request.param

(getProductList() returns ["product1", "product2", "product3"] which is stored in product_list)

BaseOne.py

@pytest.mark.usefixtures("setupone")
class BaseOne:
    pass

test_title.py

from conftest import prod

class TestStoreTitle(BaseOne):

    @pytest.mark.skipif(prod not in ["product1", "product2", "product3"], reason="test case doesn't apply for desired product")
    def test_Store_Title(self):
        pass

I want to use the product from setupone outside the function like:

def pytest_addoption(parser):
    parser.addoption("--browser_name", action="store", default="chrome")
    parser.addoption("--env", action="store", default="Production")
    parser.addoption("--product_name", nargs = '*', type = str, action ="store", default="chitale")

products_list = getProductList()

@pytest.fixture(scope='class', params = products_list)
def setupone(request):
    browser = request.config.getoption("browser_name")
    env_name = request.config.getoption("env")
    product = request.param

prod = product

Solution

  • An alternative is to just access the product from its fixture setupone.

    • Return the value of product from the fixture setupone
    • Define an autouse-fixture that will automatically process the skipping mark for products via get_closest_marker(), which below would be skip_product_not_in_list
    • Pass the list of wanted products to the mark skip_product_not_in_list
    • If the current product from setupone is not in the wanted list, skip it via pytest.skip()
    import pytest
    
    products_list = ["product1", "product2", "product3"]
    
    
    @pytest.fixture(scope='class', params=products_list)
    def setupone(request):
        product = request.param
        return product
    
    
    @pytest.fixture(autouse=True)
    def skip_non_applicable_products(request, setupone):
        if product_marker := request.node.get_closest_marker("skip_product_not_in_list"):
            if setupone not in product_marker.args[0]:
                # Option 1
                # pytest.skip(product_marker.kwargs.get('reason'))
                # Option 2
                pytest.skip(f"{product_marker.kwargs.get('reason') or 'Skipped'} {setupone}")
    
    
    def test_Store_Title_all_products(setupone):
        print("test_Store_Title_all_products:", setupone)
    
    
    @pytest.mark.skip_product_not_in_list(["product1", "product3"], reason="test case doesn't apply for desired product")
    def test_Store_Title_skip_products(setupone):
        print("test_Store_Title_skip_products:", setupone)
    

    Output

    $ pytest -rPS test_src.py
    ============================================== PASSES ===============================================
    ______________________________ test_Store_Title_all_products[product1] ______________________________
    --------------------------------------- Captured stdout call ----------------------------------------
    test_Store_Title_all_products: product1
    _____________________________ test_Store_Title_skip_products[product1] ______________________________
    --------------------------------------- Captured stdout call ----------------------------------------
    test_Store_Title_skip_products: product1
    ______________________________ test_Store_Title_all_products[product2] ______________________________
    --------------------------------------- Captured stdout call ----------------------------------------
    test_Store_Title_all_products: product2
    ______________________________ test_Store_Title_all_products[product3] ______________________________
    --------------------------------------- Captured stdout call ----------------------------------------
    test_Store_Title_all_products: product3
    _____________________________ test_Store_Title_skip_products[product3] ______________________________
    --------------------------------------- Captured stdout call ----------------------------------------
    test_Store_Title_skip_products: product3
    ====================================== short test summary info ======================================
    SKIPPED [1] test_src.py:19: test case doesn't apply for desired product product2
    ============================== 5 passed, 1 skipped, 1 warning in 0.08s ==============================
    
    • For test_Store_Title_all_products, it tested all products. For test_Store_Title_skip_products in where we defined a custom list, we can see that it skipped the "product2" because it wasn't in the list.

    Related question: