i'm new to both python and selenium testing and i've encountered a problem that probably has a standard solution but i'm unable to find it.
Let's say that the project that i'm working on is supporting Google Chrome and Firefox. Writing separate tests for every supported browser seems redundant, so i've been trying to write generic test methods that will be executed separately using different webdrivers.
My current approach goes as follows
from selenium import webdriver
def construct_chrome_webdriver () :
driver = webdriver.Chrome()
driver.implicitly_wait(10)
return driver
def construct_firefox_webdriver () :
driver = webdriver.Firefox()
driver.implicitly_wait(10)
return driver
def actual_test_method_implementation (construct_webdriver) :
webdriver = construct_webdriver()
webdriver.get('http://localhost:3333')
# do some testing
def test_method_that_is_executed_by_pytest () :
actual_test_method_implementation(construct_chrome_webdriver)
actual_test_method_implementation(construct_firefox_webdriver)
And the tests are executed using command pytest filename.py
This approach requires a lot of boilerplate - two methods for each test. Is there a better way of achieving this?
CodePudding user response:
to simplify your calls, you could directly call your driver like this: (using getattr)
from selenium import webdriver
driver = getattr(webdriver, "Firefox")(options=youroptions, executable_path="path\\geckodriver.exe" )
or
driver = getattr(webdriver, "Chrome")(options=options, executable_path="path\\chromedriver.exe" )
getattr(webdriver, "Chrome")(options=options, executable_path="path\\chromedriver.exe" )
is equivalent to
webdriver.Chrome(options=options, executable_path="path\\chromedriver.exe" )
for nav in ["Chrome", "Firefox"]:
driver = getattr(webdriver, nav)
driver.implicitly_wait(10)
driver.get('http://localhost:3333')
CodePudding user response:
Allright, i've found a better solution but im still not sure if that's the best available option so i wont mark that answer as an accepted answer for a few days.
conftest.py
import pytest
def pytest_addoption (parser):
parser.addoption("--webdriver", action="store", default="chrome", help="chrome | firefox")
@pytest.fixture
def webdriver_name (request) :
return request.config.getoption('--webdriver')
test_utils.py
from selenium import webdriver
def construct_webdriver (webdriver_name) :
if webdriver_name == 'firefox' :
driver = webdriver.Firefox()
else :
driver = webdriver.Chrome() # chrome is also the default choice
# further webdriver initialization
driver.implicitly_wait(10)
driver.get('http://localhost:3333')
return driver
test_file.py
from test_utils import construct_webdriver
def test_method_that_is_executed_by_pytest (webdriver_name) :
print('webdriver_name = ' webdriver_name)
webdriver = construct_webdriver(webdriver_name)
# do some testing
Test invocation
pytest filename.py --webdriver=chrome
pytest filename.py --webdriver=firefox
Explanation
Documentation on conftest.py and fixtures
TLDR;
In conftest.py
i've defined a test parameter called webdriver
which is set while invoking the tests from command line.
Fixture called webdriver_name
will be injected to every test method that is managed by pytest.
construct_webdriver
function will choose a webdriver implementation based on whatever the value of webdriver_name
is.
PROS
Doesn't require a lot of boilerplate code - each test needs exactly one method
CONS
This still isn't a standarized way of doing things and i feel like i'm reinventing the wheel.