Fixtures are a powerful feature of PyTest. Fixtures help us to setup some pre-conditions like setup a database connection / get test data from files etc that should run before any tests are executed. Earlier we have seen Fixtures and Scope of fixtures, In this article, will focus more on using fixtures with conftest.py
We can put fixtures into individual test files, if we want the fixture to be only used by a single test file. But to share fixtures among multiple test files, we need to use
conftest.py file so that tests from multiple test classes/modules in the directory can access the fixture function.
When fixture function is called, it will run the code in the function from the beginning until it hits yield statement which serves as the "setUp" code and the code after the yield statement serves as the "tearDown" code. The code after the yield is guaranteed to run regardless of what happens during the tests.
In order to share fixtures across multiple tests, py.test suggests to define fixtures in one single conftest.py file.
It is usually a good idea to keep your conftest.py file in the top level test or project root directory.
Before proceeding, You'll need to be sure you have downloaded selenium bindings for python.
Open command prompt and install selenium by typing
"pip install selenium" and press enter. You can find more details here - Get started using Selenium with Python
Example: - Let's see how this works
We will create conftest.py file and add below code to a conftest.py file at the root of your tests' directory : -
import pytest from selenium import webdriver @pytest.fixture(scope="class") def setup(request): print("initiating chrome driver") driver = webdriver.Chrome("chrome driver path") #if not added in PATH driver.get("http://seleniumeasy.com/test") driver.maximize_window() request.cls.driver = driver yield driver driver.close()
Let us create two classes "test_exampleOne.py" and "test_exampleTwo.py" and decorate with @pytest.mark.usefixtures("setup")
class - test_exampleOne.py
import pytest from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC @pytest.mark.usefixtures("setup") class TestExampleOne: def test_title(self): assert "Selenium Easy" in self.driver.title def test_content_text(self): print("Verify content on the page") centerText = self.driver.find_element_by_css_selector('.tab-content .text-center').text assert "WELCOME TO SELENIUM EASY DEMO" == centerText def test_bootstrap_bar(self): print("Lets try with another example") mainMenu = self.driver.find_element_by_xpath("//li/a[contains(text(), 'Progress Bars')]") mainMenu.click() subMenu = self.driver.find_element_by_xpath("//li/a[contains(text(), 'Bootstrap Progress bar')]") subMenu.click() btnDownload = self.driver.find_element_by_id("cricle-btn") btnDownload.click() WebDriverWait(self.driver, 50).until(EC.text_to_be_present_in_element_value((By.ID, 'cricleinput'), "105")) elemValue = self.driver.find_element_by_id("cricleinput") elemVAttributealue = elemValue.get_attribute('value') assert elemVAttributealue == "105"
class - test_exampleTwo.py
import pytest @pytest.mark.usefixtures("setup") class TestExampleTwo: def test_simpleInputForm(self): print("Another example") mainMenu = self.driver.find_element_by_xpath("//li/a[contains(text(), 'Input Forms')]") mainMenu.click() subMenu = self.driver.find_element_by_xpath("//li/a[contains(text(), 'Simple Form Demo')]") subMenu.click() #Finding "Single input form" input text field by id. And sending keys(entering data) in it. eleUserMessage = self.driver.find_element_by_id("user-message") eleUserMessage.clear() eleUserMessage.send_keys("Test Python") #Finding "Show Your Message" button element by css selector using both id and class name. And clicking it. eleShowMsgBtn=self.driver.find_element_by_css_selector('#get-input > .btn') eleShowMsgBtn.click() #Checking whether the input text and output text are same using assertion. eleYourMsg=self.driver.find_element_by_id("display") assert "Test Python" in eleYourMsg.text
The above two classes "test_exampleOne.py" and "test_exampleTwo" are decorated with @pytest.mark.usefixtures("setup").
Applying "@pytest.mark.usefixtures" to the class is same as applying a fixture to every test methods in the class. Since the fixture "setup" has a scope defined as "class", webdriver will be initialized only once per each class.
If you observe, In fixture, we have set the driver attribute via "request.cls.driver = driver", So that test classes can access the webdriver instance with self.driver.
Run your program using
pytest -s and if everything goes well, the output looks like below :-
Below is the output image :-
We hope that this article helps you to understand pytest fixtures and conftest.py. It's very easy to get started with using it, and it can handle most of what you need in automation testing. Give it a try !!!