Ash
Ash

Reputation: 77

How to use pytest to pass a value in your test using command line args?

I have the following as conftest.py -->

def pytest_addoption(parser):
    parser.addoption("--browser")
    parser.addoption("--osType", help="Type of operating system")
    parser.addoption("--hostURL", action="store", help="prod, stage, or dev")

@pytest.fixture(scope="session")
def browser(request):
    return request.config.getoption("--browser")

@pytest.fixture(scope="session")
def osType(request):
    return request.config.getoption("--osType")

@pytest.fixture(autouse=True)
def hostURL(request):
    return request.config.getoption("--hostURL")

I would like to use the --hostURL flag to pass in value such as prod, stage or dev.

Here's how my test_TheMainTest.py looks -->

import unitest
import pytest

class CheckStatusCodeTest(unittest.TestCase, LoginPage, CustomSeleniumDriver):

    def test_CheckStatusCodeOfPages(self, hostURL):
        self.login(hostURL)

When I run the above test using pytest -q -s --hostURL prod I get the following error -->

   TypeError: test_CheckStatusCodeOfCRPages() missing 1 required positional argument: 'hostURL'

Upvotes: 2

Views: 1145

Answers (1)

hoefling
hoefling

Reputation: 66171

Quoting the docs:

Note

unittest.TestCase methods cannot directly receive fixture arguments as implementing that is likely to inflict on the ability to run general unittest.TestCase test suites.

However, you can still pass regular fixture values to unittest-style tests using autouse fixtures:

class CheckStatusCodeTest(unittest.TestCase):

    @pytest.fixture(autouse=True)
    def _pass_fixture_value(self, hostURL):
        self._hostURL = hostURL

    def test_CheckStatusCodeOfPages(self):
        assert self._hostURL

You can also check out this answer of mine tackling the same issue for more examples.

Another possibility is to implement an autouse fixture that modifies the test class explicitly. This is useful if you have lots of test classes that should have the identical setup:

@pytest.fixture(scope="class")
def set_fixture_value_to_class(request, hostURL):
    request.cls._hostURL = hostURL


@pytest.mark.usefixtures('set_fixture_value_to_class')
class CheckStatusCodeTest(unittest.TestCase):

    def test_CheckStatusCodeOfPages(self):
        assert self._hostURL


@pytest.mark.usefixtures('set_fixture_value_to_class')
class AnotherTest(unittest.TestCase):

    def test_spam(self):
        assert self._hostURL

In this case, no need to copy the same fixture to each test class. Just mark all relevant test classes and you're good to go.

Upvotes: 2

Related Questions