Reputation: 1071
I am building a test suite for a web app. I am using fixtures as below:
import pytest
from selenium import webdriver
from common import Common
@pytest.fixture(scope='module')
def driver(module, headless=True):
opts = webdriver.FirefoxOptions()
opts.add_argument('--headless') if headless else None
driver = webdriver.Firefox(options=opts)
driver.get('http://localhost:8080/request')
yield driver
driver.quit()
def test_title(driver):
assert driver.title == 'abc'
if __name__ == '__main__':
test_title() #what I need to execute to see if everything is fine
Suppose I need to see if my test_title
function is doing what it needs to by running this module directly inside a if __name__ == '__main__':
. How can I call test_title()
with driver passed in as an argument?
calling test_title
like below:
if __name__ == '__main__':
test_title(driver(None, False))
python produces an error mentioned below:
(virtual) sflash@debian:~/Documents/php/ufj/ufj-test$ ./test_r*
Traceback (most recent call last):
File "./test_request.py", line 30, in <module>
test_empty_all(driver(None, headless=True))
File "/home/sflash/Documents/php/ufj/ufj-test/virtual/lib/python3.7/site-packages/_pytest/fixtures.py", line 1176, in result
fail(message, pytrace=False)
File "/home/sflash/Documents/php/ufj/ufj-test/virtual/lib/python3.7/site-packages/_pytest/outcomes.py", line 153, in fail
raise Failed(msg=msg, pytrace=pytrace)
Failed: Fixture "driver" called directly. Fixtures are not meant to be called directly,
but are created automatically when test functions request them as parameters.
See https://docs.pytest.org/en/stable/fixture.html for more information about fixtures, and
https://docs.pytest.org/en/stable/deprecations.html#calling-fixtures-directly about how to update your code.
Upvotes: 8
Views: 19802
Reputation: 16815
As has been discussed in the comments, fixtures cannot be called directly - they only work together with pytest
.
To invoke the test directly from your code, you can call pytest.main()
in your __main__
section, which has the same effect as calling pytest
on the command line. Any command line options can be added as arguments to the call (as a list), for example:
if __name__ == '__main__':
pytest.main(['-vv', 'test.py::test_title'])
To use the driver without involving pytest (which was your intention) you have to extract the driver logic and call it separately both from the fixture and from main:
import pytest
from selenium import webdriver
from common import Common
def get_driver(headless=True):
opts = webdriver.FirefoxOptions()
opts.add_argument('--headless') if headless else None
driver = webdriver.Firefox(options=opts)
driver.get('http://localhost:8080/request')
return driver
):
@pytest.fixture(scope='module')
def driver():
yield get_driver()
driver.quit()
def test_title(driver):
assert driver.title == 'abc'
if __name__ == '__main__':
driver = get_driver()
test_title(driver)
driver.quit()
Note that this only works if the test function does not rely on any pytest-specific stuff (for example auto-applied fixtures).
Note also that you cannot use a parameter in your fixture as you did in your example, as you have no way to provide the parameter. Instead you can use parametrized fixtures.
Upvotes: 12