Selenium Web Driver with Python and Pytest Framework

Python & Pytest Framework

Using Selenium with Pytest is a popular combination for testing web applications in Python. Selenium is a web testing library and Pytest is a testing framework.

Pytest Introduction:

Pytest is a testing framework that allows you to write simple unit tests as well as complex functional testing. It is widely used in the Python community for testing applications and libraries. Pytest is known for its simplicity, ease of use, and powerful features.

Pytest Installation:

Install Pycharm IDE to perform automation code for Pytest.

To Install Pytest, you should execute the following command on the Pycharm terminal.

  • pip install -U pytest
Image of Pytest Installation

Once Installation is completed, you can check the Pytest version with the following command on the Pycharm terminal.

  • Pytest –version
Image of Pytest Version

You need to Install the Selenium package to perform test automation using Pytest with Selenium web driver with the following command on the Pycharm terminal.

  • Pytest  install -U selenium
Image of Pytest selenium installation

Naming Conventions for Pytest Tests

  • Python file should create a .py extension.
  •  File Name starts with test_ or ends with _test.

          Example: test_firstProgram.py or firstProgram_test.py

  • The class Name starts with “Test”.

          Example: TestFirstProgram

  • Test Method should start with “test”

           Example: test_FirstProgram [underscore is optional]

Pytest Features:

  • Fixtures
  • Skips tests
  • Ordering tests
  • Dependent tests
  • Grouping tests
  • Parallel testing

1. Fixtures:

Pytest fixtures using the @pytest.fixture() marker, allow you to set up and tear down resources needed for your test.

Fixtures can be shared across multiple tests, improving code reuse.

Code:

import pytest

class TestClass:
 @pytest.fixture()  # we can say decorator, We can give prerequisites using fixtures
 def setup(self):  # Executes once after the every test Method
   print("\nthis is a setup")
   yield  # Executes once after the every test Method
   print(" Closing the browser")

 def test_PaymentInDollar(self,setup):
   print("this is a SignupByEmail")
   assert True == True

 def test_PaymentInRuppess(self,setup):
   print("this is a SignupByFacebook")
   assert True == True

Output:

image of Pytest fixtures output

Command to Execute:

  pytest -v -s pytestFeatures\FixtureModules\test_Payment.py

a) v represents: [verbose output]

It is useful for debugging and understanding the test execution flow and It provides more detailed information about the tests being executed.

b) s represents: [Disable output capture]

It disables the output capture, allowing the standard output [stdout] and standard error [stderr] to be printed in the console during the test execution.

  • PytestFeatures represents: Directory Name
  • FixtureModules represents: SubDirectory Name
  • Test_Payment.py represents: Python File Name

2. Skip Tests

In the pytest, you can skip tests using “@pytest.mark.skip” marker. Skipped tests are not executed, allowing you to exclude certain tests from the test run based on specific conditions or requirements.

Code

class TestClass:
   def test_LoginByEmail(self):
       print("this is a LoginByEmail")
       assert 1 == 1

   @pytest.mark.skip  # using skip marker, you can skip particular tests to run
   def test_LoginByFacebook(self):
       print("this is a LoginByFacebook")
       assert 1 == 1
   def test_LoginByTwitter(self):
       print("this is a LoginByTwitter")
       assert 1 == 1

Output:

Command to execute: pytest -v -s DirectoryName\pythonFileName.py

Image of output of Skips test

3. Ordering Test:

You can use the “@pytest.mark.run” marker to control the order of test execution. This marker allows you to assign a unique number to each test, and Pytest will run the tests in ascending order of these numbers.

 Firstly you will have to install the “pytest-ordering” package from the Pycharm setting.

image of pytest ordering  tests

Code:

import pytest

class TestOrdering:
   @pytest.mark.run(order=3)
   def test_MethodA(self):
       print("this is a test_MethodA")

   @pytest.mark.run(order=1)
   def test_MethodB(self):
       print("this is a test_MethodB")

   @pytest.mark.run(order=2)
   def test_MethodC(self):
       print("this is a test_MethodC")

Output:

Command to execute: Pytest -v -s  DirectoryName\pythonFileName.py

image of output ordering system

4. Dependent Tests:

In Pytest, you can manage test dependencies using the “pytest-dependency” plugin.

This plugin allows you to express dependencies between tests, ensuring that tests are executed in the correct order based on these dependencies.

image of dependent tests

Code:

import pytest

class TestClass:
  @pytest.mark.dependency()
  def test_OpenApp(self):
      assert True

  @pytest.mark.dependency(depends=['TestClass::test_OpenApp'])
  def test_Login(self):
      assert True

  @pytest.mark.dependency(depends=['TestClass::test_Login','TestClass::test_OpenApp'])
  def test_Search(self):
      assert True

In this example, the test_Login method is dependent on the test_OpenApp method and the test_Search method is dependent on the test_Login method and test_OpenApp method.

To show dependency, using “@pytest.mark.dependency” decorator is used to mark a test as having dependencies, and the ‘’depends” parameter specifies the dependencies.

  • If a test fails, its dependent tests will be marked as “blocked” and won’t be executed.

Circular dependencies are not allowed. If there is a circular dependency, Pytest will raise an error

Output:

Command to execute: Pytest -v -s  DirectoryName\pythonFileName.p

Image of dependent tests

5. Grouping Tests

In Pytest, you can define custom markers that represent different groups or categories for your tests and you can run the tests only based on grouping tags. For example, let’s define markers for “smoke” “,sanity” and “regression” tests.

Tests will execute with “@pytest.mark.smoke”, “@pytest.mark.sanity”, and “@pytest.mark.regression” markers Firstly you have to initialize these custom grouping markers in a file [pytest.ini].

image of grouping tests

Code:

import pytest

class TestGrouping:
   @pytest.mark.sanity
   def test_LoginByEmail(self):
       print("this is a test_MethodA")
       assert 1 ==1

   @pytest.mark.smoke
   @pytest.mark.regression
   def test_LoginByFacebook(self):
       print("this is a test_MethodB")
       assert 1 == 1

   @pytest.mark.regression
   def test_SignupByEmail(self):
       print("this is a test_MethodD")
       assert 1 == 1

Output:

Command to execute: Pytest -v -s -m “sanity” DirectoryName\pythonFileName.py

image of Group tests command

When you run Pytest with the -m option, it will group tests in the test report based on the markers.

Let’s suppose, the command to run is Pytest -v -s -m “sanity” pytestFeatures2\test_Grouping.py, It will execute on sanity group test cases and the rest test cases will be deselected.

You can run multiple group tests using the –

  • Pytest -v -s -m “sanity and regression” pytestFeatures2\test_Grouping.py

Here both sanity and regression tests will execute.

6. Parallel Testing

Pytest supports parallel testing using the “pytest-xdist” plugin. This plug-in allows you to parallelize test execution, which can significantly reduce the overall test suite runtime.

  • Install ‘’pytest-xdist
image of Pytest-xdist

Code:

It will execute different methods at the same time on different browsers by using parallel commands.

import pytest
import time

from selenium_firefox import Firefox
class TestParallel:
   def test_LoginChrome(self):
       from selenium.webdriver.common.by import By
       selenium import webdriver
       from selenium.webdriver.chrome.service import Service
       self.serv_obj = Service("D:\\Drivers\\chromedriver-win64\\chromedriver.exe")
       self.driver = webdriver.Chrome(service=self.serv_obj)
       self.driver.get("https://opensource-demo.orangehrmlive.com/")
       self.driver.maximize_window()
       time.sleep(2)
       self.driver.find_element(By.NAME, "username").send_keys("Admin")
       self.driver.find_element(By.NAME, "password").send_keys("admin123")
       self.driver.find_element(By.XPATH, "//button[@type='submit']").click()
       self.act_title = self.driver.title
       self.driver.exp_title = "OrangeHRM"
       self.driver.quit()

   def test_FirefoxLogin(self):
       from selenium.webdriver.common.by import By
       from selenium import webdriver
       Starting with selenium import webdriver
       from webdriver_manager.firefox import GeckoDriverManager
       from selenium.webdriver.firefox.service import Service as FirefoxService
       # Initialize Firefox driver instance
       self.driver = webdriver.Firefox(service=FirefoxService(executable_path=GeckoDriverManager().install()))
       self.driver.maximize_window()
       self.driver.get("https://opensource-demo.orangehrmlive.com/")
       time.sleep(2)
       self.driver.find_element(By.NAME, "username").send_keys("Admin")
       self.driver.find_element(By.NAME, "password").send_keys("admin123")
       self.driver.find_element(By.XPATH,"//button[@type='submit']").click()
       self.act_title = self.driver.title
       self.driver.exp_title = "OrangeHRM"
       self.driver.quit()

Output:

  • Command to execute: pytest -v -s -n=2  pytestFeatures2\test_Parallel.py

  -n: specify the exact number of worker processes.

image of execute command

Conclusion

Combining selenium with pytest empowers you to create a robust and maintainable test suite for your web application. It provides a powerful and flexible solution for ensuring the quality and reliability of your web projects.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top