Home > Software design >  How to write generic selenium tests executed by multiple webdrivers
How to write generic selenium tests executed by multiple webdrivers

Time:06-18

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.

  • Related