Page Object Model Implementation of Python with Selenium – PyTest

HOME

pip install -U pytest

from selenium.webdriver import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec


class BasePage:

    def __init__(self, driver):
        self._driver = driver
        self._wait = WebDriverWait(self._driver, 10)
        self._action = ActionChains(self._driver)

    def find(self, locator):
        return self._driver.find_element(*locator)

from selenium.webdriver.common.by import By

from pages.base_page import BasePage


class LoginPage(BasePage):
    username = (By.NAME, "username")
    password = (By.NAME, "password")
    submit_button = (By.XPATH, "//*[@class='oxd-form']/div[3]/button")
    error_message = (By.XPATH, "//*[@class='orangehrm-login-error']/div[1]/div[1]/p")

    def execute_login(self, username: str, password: str):
        self.find(self.username).send_keys(username)
        self.find(self.password).send_keys(password)
        self.find(self.submit_button).click()

    def actual_error(self):
        return self.find(self.error_message).text

from selenium.webdriver.common.by import By

from pages.base_page import BasePage


class DashboardPage(BasePage):
    heading = (By.XPATH, "//*[@class='oxd-topbar-header-breadcrumb']/h6")
    assign_leave_option = (By.XPATH, "//*[@title='Assign Leave']")
    time_at_work_option = (By.XPATH, "//*[@title='Time at Work']")

    def actual_heading(self):
        return self.find(self.heading).text

    def assign_leave_displayed(self):
        return self.find(self.assign_leave_option).is_displayed()

    def time_at_work_displayed(self):
        return self.find(self.assign_leave_option).is_displayed()

import pytest
from selenium import webdriver


@pytest.fixture(scope="class")
def driver():

    driver = webdriver.Chrome()
    driver.get("https://opensource-demo.orangehrmlive.com/")
    driver.maximize_window()
    driver.implicitly_wait(2)
    yield driver
    driver.close()

import pytest

from pages.dashboard_page import DashboardPage
from pages.login_page import LoginPage


def test_login_negative(driver, get_data):

    login_page = LoginPage(driver)
    login_page.execute_login(get_data["username"], get_data["password"])
    assert login_page.actual_error() == "Invalid credentials", "Error message does not match expected value"


def test_login_positive(driver):
    login_page = LoginPage(driver)
    login_page.execute_login("Admin", "admin123")
    dashboard_page = DashboardPage(driver)
    assert dashboard_page.actual_heading() == "Dashboard", "Heading is different"

@pytest.fixture(params=[{"username":"admin", "password":"admin$$"},
                        {"username":"Admin123", "password":"123"}])
def get_data(request):
    return request.param

from pages.dashboard_page import DashboardPage
from pages.login_page import LoginPage


def test_successful_login(driver):

    login_page = LoginPage(driver)
    login_page.execute_login("Admin", "admin123")
    dashboard_page = DashboardPage(driver)
    assert dashboard_page.actual_heading() == "Dashboard"


def test_time_at_work(driver):
    login_page = LoginPage(driver)
    login_page.execute_login("Admin", "admin123")
    dashboard_page = DashboardPage(driver)
    assert dashboard_page.time_at_work_displayed()

pytest 

 pytest --html=report.html -s

Pytest Logging to print to a File

HOME

import logging


def test_logging_file():

    # Create a named logger
    logger = logging.getLogger(__name__)

    # Create a file handler
    filehandler = logging.FileHandler('logfile.log')

    # Set the formatter for the file handler
    formatter = logging.Formatter("%(asctime)s : %(levelname)s : %(name)s : %(message)s")
    filehandler.setFormatter(formatter)

    # Add the file handler to the logger
    logger.addHandler(filehandler)  

    logger.setLevel(logging.INFO)
    logger.debug("Debug statement is executed")
    logger.info("Information statement is executed")
    logger.warning("Warning mode, but test continues")
    logger.error("Error has happened and failed the test")
    logger.critical("Critical issue")

logging.Formatter("%(asctime)s : %(levelname)s : %(name)s : %(message)s")

pytest test_logging_file.py -s

import inspect
import logging


class BaseClass:

    def get_logger(self):

        loggerName = inspect.stack()[1][3]
        logger = logging.getLogger(loggerName)

        filehandler = logging.FileHandler('logfile.log')

        formatter = logging.Formatter("%(asctime)s : %(levelname)s : %(name)s : %(message)s")
        filehandler.setFormatter(formatter)

        logger.addHandler(filehandler)  

        logger.setLevel(logging.INFO)
        return logger

import pytest
from demo.BaseClass import BaseClass


class TestExample3(BaseClass):

    @pytest.fixture()
    def dataload(self):
        print("User Profile data")
        return ["Vibha", "Singh", "qaautiomation.expert"]

    @pytest.mark.usefixtures("dataload")
    def test_user_profile(self, dataload):
        log = self.get_logger()
        log.info(dataload)
        log.info(f'First Name : {dataload[0]}')
        log.info(f'Surname : {dataload[1]}')
        log.info(f'Website : {dataload[2]}')

pytest -s

Pytest Logging to print to Console

HOME

import logging


def test_logging_console():
    logger = logging.getLogger(__name__)

    # Create a console handler
    console_handler = logging.StreamHandler()

    # Set the formatter for the console handler
    formatter = logging.Formatter("%(asctime)s : %(levelname)s : %(name)s : %(message)s")
    console_handler.setFormatter(formatter)

    # Add the console handler to the logger
    logger.addHandler(console_handler)
    logger.setLevel(logging.INFO)

    logger.debug("Debug statement is executed")
    logger.info("Information statement is executed")
    logger.warning("Warning mode, but test continues")
    logger.error("Error has happened and failed the test")
    logger.critical("Critical issue")

logging.Formatter("%(asctime)s : %(levelname)s : %(name)s : %(message)s")

pytest test_logging_console.py -s

How to generate HTML Report in PyTest Framework

HOME

pip install -U pytest

pip install pytest-html

import pytest


def test_addition():
    a = 6
    b = 5
    c = 11

    assert a + b == 11, "Sum is not 11"
    assert a + b == c, "Sum of a and b is not equal to c"


def test_subtraction():
    x = 15
    y = 4
    z = 10

    assert x - y == z, "Subtract y from x is equal to z"


def test_multiplication():
    a = 6
    b = 5
    c = 30

    assert a * b == c, "Product of 5 and 6 is not 30"


def test_division():
    a = 16
    b = 2
    c = 8

    assert a / b == c, "Division of 2 by 6 is not 3"

pytest --html=report.html

What is conftest.py in PyTest?

HOME

import pytest


@pytest.fixture
def shared_fixture():
    print("This will be executed before any test")

def test_fixture1(shared_fixture):
    print("This is the fixture main method1 for demo1 class")
    print("Good Morning")


def test_fixture2(shared_fixture):
    print("This is the fixture main method2 for demo1 class")
    print("Good AfterNoon")

def test_fixture(shared_fixture):
    print("This is the fixture main method for demo2 class")
    print("Good Evening")

pytest test_demo1.py test_demo2.py -s

import pytest


@pytest.fixture
def shared_fixture():
    print("This will be executed before any test")
    yield
    print("This will be executed after any test")

import pytest


@pytest.mark.usefixtures("shared_fixture")
class TestExample1:

    def test_fixture1(self):
        print("This is the fixture main method1 for demo1 class")
        print("Good Morning")

    def test_fixture2(self):
        print("This is the fixture main method2 for demo1 class")
        print("Good AfterNoon")

import pytest


@pytest.mark.usefixtures("shared_fixture")
class TestExample2:

    def test_fixture(self):
        print("This is the fixture main method for demo2 class")
        print("Good Evening")

pytest -s

import pytest


@pytest.fixture(scope="class")
def shared_fixture():
    print("This will be executed before any test")
    yield
    print("This will be executed after any test")

PyTest Framework

HOME

Configure Selenium with Python

HOME

pip install -U selenium

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(2)
driver.get("https://opensource-demo.orangehrmlive.com/")

driver.find_element(By.NAME, "username").send_keys("Admin")
driver.find_element(By.NAME, "password").send_keys("admin123")
driver.find_element(By.XPATH, "//*[@class='oxd-form']/div[3]/button").click()

homePageTitle = driver.find_element(By.XPATH,"//*[@class='oxd-topbar-header-breadcrumb']/h6").text
print("Heading of DashBoard Page: ", homePageTitle)
driver.quit()

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

driver.maximize_window()

driver.implicitly_wait(2)

driver.get("https://opensource-demo.orangehrmlive.com/")

driver.find_element(By.NAME, "username").send_keys("Admin")
driver.find_element(By.NAME, "password").send_keys("admin123")
driver.find_element(By.XPATH, "//*[@class='oxd-form']/div[3]/button").click()

homePageTitle = driver.find_element(By.XPATH,"//*[@class='oxd-topbar-header-breadcrumb']/h6").text
print("Heading of DashBoard Page: ", homePageTitle)

driver.quit()

pytest LoginTest.py -s

What is PyTest Framework?

HOME

pip install pytest

def test_addition():
    a = 6
    b = 5
    c = 11

    assert a + b == 11, "Sum is not 11"
    assert a + b == c, "Sum of a and b is not equal to c"


def test_subtraction():
    x = 15
    y = 4
    z = 18

    assert x - y == z, "Subtract y from x is equal to z"

pytest

test_sample - valid
sample_test - valid
sample_tests - invalid
testsample - invalid
sampletest - invalid

How to add environment details to Python Allure Report

HOME

os_platform = windows 11
os_release = 10.2
python_version = Python 3.12.1
environment = uat
release_no = 10
author = vibha singh

How to create Python Allure Report for Rest API

HOME

pip install -U requests

pip install -U pytest

pip install allure-pytest

import allure
import requests

ENDPOINT = 'https://reqres.in/api/users'


@allure.description("This tests validates that the response returns status code 201")
@allure.severity(allure.severity_level.BLOCKER)
@allure.label("Owner", "Vibha Singh")
def test_create_user():
    request_body = {
        "name": "Vibha",
        "Job": "CEO"
    }

    response = requests.post(ENDPOINT, request_body)
    response_body = response.json()
    print("Request :", request_body)
    print("Response :", response_body)
    assert response.status_code == 201


@allure.description("This tests validates that the id in the response")
@allure.severity(allure.severity_level.NORMAL)
@allure.label("Owner", "Vibha Singh")
def test_response():
    request_body = {
        "name": "Vibha",
        "Job": "CEO"
    }

    response = requests.post(ENDPOINT, request_body)
    assert response.status_code == 201
    response_body = response.json()
    print("Request :", request_body)
    print("Response :", response_body)

    id = response_body["id"]
    if "id" in response_body:
        print("Value of id :", id)
    else:
        print("id not found")


@allure.description("This tests validates that the header in the response")
@allure.severity(allure.severity_level.NORMAL)
@allure.label("Owner", "Vibha Singh")
def test_header_in_request():
    request_body = {
        "name": "Vibha",
        "Job": "CEO"
    }

    headers = {'Content-Type': 'application/json; charset=utf-8'}
    response = requests.post(ENDPOINT, request_body, headers)
    print("Request :", request_body)
    print("Response :", response.json())
    print("Headers :", response.headers)
    assert response.headers["Content-Type"] == "application/json; charset=utf-8"


@allure.description("This tests validates that the name in the response - FAIL")
@allure.severity(allure.severity_level.NORMAL)
@allure.label("Owner", "Vibha Singh")
def test_verify_name():
    request_body = {
        "name": "Vibha",
        "Job": "CEO"
    }

    header = {"Content-Type":  "application/json; charset=utf-8"}
    response = requests.post(ENDPOINT, request_body, header)
    response_body = response.json()
    print("Response :", response_body)
    print("Request Header :", response.request.headers)
    assert response_body["name"] == "Test"

pytest --alluredir=<path to report directory> test.py

pytest --alluredir=C:\Users\Documents\Vibha\Automation\Python\AllureReport_Python\AllureReport Requests.py

allure serve <path to report directory>
allure serve C:\User\Documents\Vibha\Automation\Python\AllureReport_Python\AllureReport