What role does request.cls.driver have in pytest fixture with a scope of class?

Viewed 4580

Please see the below fixture and help me understand what exactly request and request.cls.driver=driver is doing? As far I understood it is related to scope of the fixture, what happens if i use a different scope?

@pytest.fixture(scope="class")
def driver_init(request):
    from selenium import webdriver
    web_driver = webdriver.Chrome("C:/chromedriver.exe")
    request.cls.driver = web_driver
    yield
    web_driver.close()
3 Answers

Official API documentation for pytest states, "The request fixture is a special fixture providing information of the requesting test function.". Link - https://docs.pytest.org/en/stable/reference.html#request

Therefore "request" in "diver_init" fixture has the information of the requesting test function (which would be a method to open the browser). From the line "request.cls.driver = web_driver", it is clear that we are assigning driver value for the invoke test function. So, before opening an URL we need a browser which is driver and it is assigned using fixture with scope on class level.

When we execute the script - For that particular instance, driver_init declares the request.cls.driver value as "webdriver.Chrome("C:/chromedriver.exe")". So it sets up the driver as chrome for the test execution using the fixture parameter request.cls.driver.

Without this assignment, request.cls.driver has no values and your script would fail for driver assignment as None.

If the scope of the fixture changed, for example from class to method- driver value would be assigned to None for the next method in order and the sequence would get failed. Instead if it is changed from class to module, there wont be any driver.quit or close methods. So you would run your scripts on existing session.

Basically here, in your method driver_init instead of declaring driver as global you are using request variable as a parameter

 web_driver = webdriver.Chrome("C:/chromedriver.exe")  
 request.cls.driver = web_driver

So, here you are storing web_driver in request variable at a class level which can be accessed while running your test.

When parameter scope = "class" multiple test cases in class will get executed and will only call driver function once.

When parameter scope = "function" driver function is called before the execution of different test cases in class in short for every test case inside class.

I will like to add a clear example to the comment made by @hoefling in the question above.

The code below shows the class fixture

@pytest.fixture(scope='class')
def prepare_db():
    connection_db = db.create_connection()
    request.cli.connection = connection_db
    yield
    connection = db.close()

@pytest.mark.usefixtures("prepare_db")
class TestCase:
     def test_connection(self):
          assert self.connection.execute("..") == "..."

In the above code, request.cli in the prepared_db function fixture, is equivalent to the test class using the fixture. In this case, it will be TestCase.connection = connection_db. The TestCase is a class of test function.

Related