Status Code, Line, Body, and Header Verification in Python Requests

HOME

pip install -U requests
pip install -U pytest

import requests


def test_get_statuscode():

    # Define the API endpoint
    url = "https://reqres.in/api/users/2"

    # Make a GET request to the API endpoint
    response = requests.get(url)

    # Retrieve status code
    status_code = response.status_code

    # Display the results
    print("Status Code:", status_code)
    assert status_code == 200

pytest ResponseStatusCode_test.py -s

import requests


def test_get_statuscode():

    # Define the API endpoint
    url = "https://reqres.in/api/users/200000"

    # Make a GET request to the API endpoint
    response = requests.get(url)

    # Retrieve status code
    status_code = response.status_code

    # Display the results
    if status_code == 200:
        print("Request is successful")
    elif status_code == 401:
        print("Unauthorized Request")
    elif status_code == 404:
        print("Resource not found")
    elif status_code == 500:
        print("Server Error")
    elif status_code == 503:
        print("Service Unavailable")
    else:
        print("Status Code:", status_code)

import requests


def test_get_statuscode():

    # Define the API endpoint
    url = "https://reqres.in/api/users/200000"

    # Make a GET request to the API endpoint
    response = requests.get(url)

    # Retrieve status code
    status_code = response.status_code

    # Display the results
    try:
        response.raise_for_status()
        print("Request is successful")
    except requests.exceptions.HTTPError as http_err:
        print(f"HTTP error occurred : {http_err}")
    except Exception as err:
        print(f"Other error occurred: {err}")

import requests


def test_get_statusline():

    # Define the API endpoint
    url = "https://reqres.in/api/users/2"

    # Make a GET request to the API endpoint
    response = requests.get(url)

    # Retrieve status line (in this example, requests library does not provide status line directly, so we can construct it)
    status_line = f"{response.status_code} {response.reason}"

    # Display the results
    print("Status Line:", status_line)
    assert status_line == "200 OK"

import requests


def test_get_responsebody():

    # Define the API endpoint
    url = "https://reqres.in/api/users/2"

    # Make a GET request to the API endpoint
    response = requests.get(url)

    # Retrieve response content
    content = response.content

    # Display the results
    print("Response Content:", content)

import requests


def test_get_headers():

    # Define the API endpoint
    url = "https://reqres.in/api/users/2"

    # Make a GET request to the API endpoint
    response = requests.get(url)

    # Retrieve content type
    content_type = response.headers['Content-Type']

    # Display the results
    print("Content Type:", content_type)
    assert content_type == "application/json; charset=utf-8"


How to handle HTTP Query Parameters in Python

HOME

https://reqres.in/api/users?page=2

import requests

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


def test_verify_header():
    params = {
        'pages': 2
    }

    response = requests.get(ENDPOINT, params)
    print(response.json())

    print("Response Header", response.headers)

    #Assert status code
    assert response.status_code == 200

    # Assert Response Body
    response_body = response.json()
    assert response_body["per_page"] == 6

    assert response_body["data"][0]["id"] == 1

pytest QueryParam_test.py

How to run PyTest Framework in GitHub Actions

Last Updated On

HOME

This tutorial explains the steps to create a GitHub Action for the PyTest Framework. It also guides you on how to execute the tests in that workflow.

Table of Contents

Why GitHub?

GitHub is a collaborative platform. It supports version control and code collaboration. Automated testing and issue tracking are also supported. These are crucial elements in the software testing process. It promotes transparency, collaboration, and efficiency in the development and testing workflows.

CI/CD pipelines have contributed to the success of the DevOps cycle in all software development projects. This is a holistic process that bridges development and operations. Continuous integration helps development teams deploy code efficiently, and continuous delivery automates code deployment.

Implementation Steps

Step 1 – Create GitHub Actions and Workflows

I have a repository available in GitHub – “PyTest_Framework” as shown in the below image. Go to the “Actions” tab.  Click on the “Actions” tab.

Step 2 – Select the type of Actions

You will see that GitHub recommends Actions depending on the project. In our case, it is recommending actions suitable for a Java project. I have selected the “Python application” option as my project is built in Maven.

Step 3 – Generation of Sample pipeline

If you choose an existing option, it will automatically generate a .yaml for the project as shown below.

We will replace the current workflow with the following yml file as shown below:

name: PyTest Framework - Python
on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - name: Set up Python 3.12.1
        uses: actions/setup-python@v4
        with:
          python-version: 3.12.1

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest
          pip install pytest-selenium
   
      - name: Test with PyTest
        run: pytest --html=tests/Reports/Report.html  

      - name: Test Report Generation
        uses: actions/upload-artifact@v4
        if: success() || failure()
        with:
          name: Pytest Report           # Name of the folder
          path: tests/Reports           # Path to test results

python -m pip install --upgrade pip

pip install pytest
pip install pytest-selenium

  - name: Test with PyTest
    run: pytest --html=tests/Reports/Report.html  

Step 4 – Commit the changes

After the changes, hit the “Start Commit” button.

This will give the option to add a description for the commit. It will also enable the user to commit either to the main branch or commit to any other branch that exists in the project. My personal prefernece is to create a new branch like shown below and then commit the changes in that new branch.

Step 5 – Verify that the workflow is running

Next, head over to the “Actions” tab, and you will see your YAML workflow file present under the tab. The yellow sign represents that the job is in the queue.

In Progress – When the job starts building and running, you will see the status change from “Queued” to “In progress”.

Passed – If the build is successful, you will see a green tick mark. 

Click on the workflow and the below screen is displayed. It shows the status of the run of the workflow, the total time taken to run the workflow, and the name of the .yml file.

Below shows all the steps of the workflow.

The complete code can be found here on GitHub – vibssingh/PyTest_Framework.

Congratulations! We just created our CI workflow for running our Python Robot Framework.

Integration of Allure Report with PyTest

Last Updated on

HOME

In this tutorial, we will discuss the Integration of Allure Report with the PyTest.

Table of Contents:

  1. What is an Allure Report?
  2. Prerequisite
  3. Implementation Steps
    1. Install allure-pytest plugin
    2. Create a new project folder and open it in PyCharm
    3. Add the allure-pytest package to the PyCharms
    4. Create the test code
    5. Execute the tests
    6. Generation of allure-results folder
    7. Generate the Allure Report
    8. Allure Report Dashboard
      1. Categories in Allure Report
      2. Suites in Allure Report
      3. Graphs in Allure Report
      4. Timeline in Allure Report
      5. Behaviours of Allure Report
      6. Packages in Allure Report

What is an Allure Report?

Allure Framework is a flexible lightweight multi-language test report tool that not only shows a very concise representation of what has been tested in a neat web report form but allows everyone participating in the development process to extract maximum useful information from everyday execution of tests.

From the dev/qa perspective, Allure reports shorten common defect lifecycle: test failures can be divided into bugs and broken tests, also logs, steps, fixtures, attachments, timings, history, and integrations with TMS and bug-tracking systems can be configured, so the responsible developers and testers will have all information at hand.

Prerequisite:

    Implementation Steps:

    Step 1 – Install allure-pytest plugin

    Go to the command prompt and run the below-mentioned command to download the plugin:

    pip install allure-pytest
    

    The below image shows that the plugin is installed successfully.

    Step 3 – Add the allure-pytest package to the PyCharms

    Go to File->Settings ->Project:PageObjectModel_Pytest->Python Interpreter.

    Click on the “+” sign and enter allure-pytest in the search bar. It will show a list of packages. Select the “allure-pytest” package and click on the “Install Package”.

    Once the package is installed, we will see the message that the package is installed successfully, and it can be seen under the package list as shown below:

    Step 4 – Create the test code

    The complete PyTest framework can be found here – Page Object Model Implementation of Python with Selenium – PyTest.

    Step 5 – Execute the tests

    We need the below command to run the PyTest Framework script using the Allure listener.

    pytest --alluredir allure-results
    

    The output of the above program is

    Step 6 – Generation of allure-results folder

    We have the test case passed. It will generate an allure-results folder in the tests directory. This folder contains all the files needed to generate the Allure Report.

    Step 7 – Generate the Allure Report

    To create Allure Report, use the below command

    allure serve allure-results
    

    This will generate the beautiful Allure Test Report as shown below.

    Step 8 – Allure Report Dashboard

    The overview page hosts several default widgets representing the basic characteristics of your project and test environment.

    1. Statistics – overall report statistics.
    2. Launches – if this report represents several test launches, statistics per launch will be shown here.
    3. Behaviours – information on results aggregated according to stories and features.
    4. Executors – information on test executors that were used to run the tests.
    5. History Trend – if tests accumulated some historical data, it’s trend will be calculated and shown on the graph.
    6. Environment – information on the test environment.

    Categories in Allure Report

    The categories tab gives you a way to create custom defect classifications to apply for test results. There are two categories of defects – Product Defects (failed tests) and Test Defects (broken tests).

    Suites in Allure Report

    On the Suites tab a standard structural representation of executed tests, grouped by suites and classes can be found.

    Graphs in Allure Report

    Graphs allow you to see different statistics collected from the test data: statuses breakdown or severity and duration diagrams.

    Timeline in Allure Report

    The timeline tab visualizes retrospective of tests execution, allure adaptors collect precise timings of tests, and here on this tab, they are arranged accordingly to their sequential or parallel timing structure.

    Behaviours of Allure Report

    This tab groups test results according to Epic, Feature, and Story tags.

    Packages in Allure Report

    The packages tab represents a tree-like layout of test results, grouped by different packages.

    That’s it! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

    Cross Browser Testing in PyTest

    HOME

    import pytest
    from selenium import webdriver
    
    
    def pytest_addoption(parser):
        """Custom Pytest command line options"""
        parser.addoption(
            "--browser_name", action="store", default="chrome"
        )
    
    
    @pytest.fixture(scope="class")
    def driver(request):
    
        browser_name = request.config.getoption("browser_name")
    
        if browser_name == "chrome":
            options = webdriver.ChromeOptions()
            driver = webdriver.Chrome(options)
            print("Chrome Browser is opened")
        elif browser_name == "firefox":
            options = webdriver.FirefoxOptions()
            driver = webdriver.Firefox(options)
            print("Firefox Browser is opened")
        elif browser_name == "edge":
            options = webdriver.EdgeOptions()
            driver = webdriver.Edge(options)
            print("Edge Browser is opened")
        else:
            print("No browser is selected")
        driver.get("https://opensource-demo.orangehrmlive.com/")
        driver.maximize_window()
        driver.implicitly_wait(5)
        yield driver
        driver.close()
    
    
    from selenium.webdriver.common.by import By
    
    
    class Test_Login:
    
        def test_login(self,driver):
            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()
            print("Successful login to the application")
            homePageTitle = driver.find_element(By.XPATH, "//*[@class='oxd-topbar-header-breadcrumb']/h6").text
            print("Heading of DashBoard Page: ", homePageTitle)
            assert homePageTitle == "Dashboard", "Heading is different"
    
    
    pytest test_login.py -s
    

     pytest test_login.py --browser_name firefox -s
    

    How to skip tests in PyTest – skip, skipIf, xfail

    HOME

    import pytest
    
    
    @pytest.mark.skip(reason="In Progress")
    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"
    
    
    @pytest.mark.skipif(15-4>10, reason="Conditional")
    def test_subtraction():
        x = 15
        y = 4
        z = 10
    
        assert x - y == z, "Subtract y from x is equal to z"
    
    
    @pytest.mark.xfail
    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 test_skip_demo.py
    

    import pytest
    
    
    @pytest.mark.skip("Development in progress")
    class test_skip_class:
    
        def test_addition(self):
            a = 10.44
            b = 5.56
            c = 16.00
    
            assert a + b == 16.00, "Sum is not 16"
    
        def test_subtraction(self):
            x = 15
            y = 4
            z = 10
    
            assert x - y == z, "Subtract y from x is equal to z"
    
    

    Filtering by tags in PyTest-BDD

    HOME

    @Login
    Feature: Login Page
    
        @ValidCredentials
        Scenario: Successful Application Login
            Given User is on login page
            When User enter username "Admin" and password "admin123"
            Then User should be able to login successfully and new page open "Dashboard"
    

    @ScenarioOutline
    Feature: Scenario Outline Example
    
        @InvalidCredentials
        Scenario Outline: Invalid credentials generate error message
            Given User is on OrangeHome page
            When User enters username as "<username>" and password as "<password>"
            Then User should be able to see error message as "Invalid credentials"
    
          Examples:
           | username | password    |
           | admin    | admin12345  |
           | Admin123 | admin       |
           | 123      | admin       |
    
    
        @MissingUsername
        Scenario: Missing Username generates error
            Given User is on OrangeHome page
            When User enters username as " " and password as "admin123"
            Then User should be able to see error message as "Required" below the username field
    
    
    pytest
    

    [pytest]
    markers =
        Login: mark all tests as login
        ValidCredentials: mark a test as a valid credentials (deselect with '-m "not ValidCredentials"')
    	ScenarioOutline: mark all tests as ScenarioOutline
    	InvalidCredentials: mark test as invalid credentials (deselect with '-m "not InvalidCredentials"')
    	MissingUsername: mark test as missing username (deselect with '-m "not MissingUsername"')
    

     pytest -k "MissingUsername"
    

    pytest -k  "Login"
    

    pytest -m "ScenarioOutline and MissingUsername"
    

    pytest -m "ValidCredentials or MissingUsername"
    

     pytest -m "not InvalidCredentials"
    

    Scenario Outline in PyTest – BDD

    HOME

    pip install pytest
    pip install pytest-bdd
    pip install pytest-selenium (If using Selenium)
    

    Feature: Scenario Outline Example
    
        @InvalidCredentials
        Scenario Outline: Unsuccessful Application Login
            Given User is on OrangeHome page
            When User enters username as "<username>" and password as "<password>"
            Then User should be able to see error message as "Invalid credentials"
    
          Examples:
           | username | password    |
           | admin    | admin12345  |
           | Admin123 | admin       |
           | 123      | admin       |
    
    

    import pytest
    
    from pytest_bdd import scenarios, given, when, then, parsers
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    
    # Constants
    TIMEOUT = 5
    URL = 'https://opensource-demo.orangehrmlive.com/'
    
    
    # Scenarios
    scenarios('../features/ScenarioOutline.feature')
    
    
    # Fixtures
    @pytest.fixture
    def driver():
        driver = webdriver.Firefox()
        driver.implicitly_wait(TIMEOUT)
        driver.maximize_window()
        yield driver
        driver.quit()
    
    
    # Given Steps
    @given('User is on OrangeHome page')
    def open_browser(driver):
        driver.get(URL)
    
    
    # When Steps
    @when(parsers.parse('User enters username as "{username}" and password as "{password}"'))
    def search_phrase(driver, username, password):
        driver.find_element(By.NAME, "username").send_keys(username)
        driver.find_element(By.NAME, "password").send_keys(password)
        driver.find_element(By.XPATH, "//*[@class='oxd-form']/div[3]/button").click()
    
    
    # Then Steps
    @then(parsers.parse('User should be able to see error message as "{expected_error_message}"'))
    def search_results(driver, expected_error_message):
        actual_error_message = driver.find_element(By.XPATH, "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/div/div[1]/div[1]/p").text
        assert actual_error_message == expected_error_message
    

    scenarios('../features/ScenarioOutline.feature')
    

    pytest stepdefinitions/test_scenario_outline_definitions.py -s
    

     pytest stepdefinitions/test_scenario_outline_definitions.py --html=Report.html 
    

    PyTest – BDD (Behavioural Driven Development) with Selenium

    HOME

    pip install pytest
    
    pip install pytest-bdd
    

    pip install pytest-selenium
    

    Feature: Login Page
    
        Scenario: Successful Application Login
            Given User is on login page
            When User enter username "Admin" and password "admin123"
            Then User should be able to login successfully and new page open "Dashboard"
    

    import pytest
    
    from pytest_bdd import scenarios, given, when, then, parsers
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    # Constants
    TIMEOUT = 4
    URL = 'https://opensource-demo.orangehrmlive.com/'
    
    
    # Scenarios
    scenarios('../features/Login.feature')
    
    
    # Fixtures
    @pytest.fixture
    def driver():
        driver = webdriver.Firefox()
        driver.implicitly_wait(TIMEOUT)
        driver.maximize_window()
        yield driver
        driver.quit()
    
    
    # Given Steps
    @given('User is on login page')
    def open_browser(driver):
        driver.get(URL)
    
    
    # When Steps
    @when(parsers.parse('User enter username "{username}" and password "{password}"'))
    def search_phrase(driver, username, password):
        driver.find_element(By.NAME, "username").send_keys(username)
        driver.find_element(By.NAME, "password").send_keys(password)
        driver.find_element(By.XPATH, "//*[@class='oxd-form']/div[3]/button").click()
    
    
    # Then Steps
    @then(parsers.parse('User should be able to login successfully and new page open "{heading}"'))
    def search_results(driver, heading):
        homepage_title = driver.find_element(By.XPATH, "//*[@class='oxd-topbar-header-breadcrumb']/h6").text
        assert homepage_title == heading
    
    
    scenarios('../features/Login.feature')
    

    pytest tests
    

    pytest tests --html=Report.html -s
    

    How to run Python Selenium tests with Jenkins

    HOME

    In the previous tutorial, we have seen the How to generate HTML Reports in Jenkins. In this tutorial, we show you how to integrate PyTest tests with Jenkins

    Prerequisite:

    Jenkin’s installed and started on the computer. The current Jenkins version is – 2.361.2

    Implementation Steps

    To generate HTML Report in Jenkins, we need to download HTML Publisher Plugin. Please refer to this tutorial to install the plugin – How to install Plugins in Jenkins.

    Step 1: Create a new FreeStyle project

    1. Give the Name of the projectPyTestFramework_Demo
    2. Click on the Freestyle project. 
    3. Click on the OK button.

    In the General section, enter the project description in the Description box – This is demo integration of Python with Selenium tests to run in Jenkins.

    Step 2: Select a custom workspace

    Mention the full path of the project in the Use custom workspace.

    Select Source Code Management as None if the project is locally present on the machine.

    Step 3: Build Management

    Go to the Build section of the new job. Select “Execute Windows batch command”.

    cd tests
    pytest  --html=$WORKSPACE/Reports/report.html -s
    

    Step 4: Select “Publish HTML reports” from “Post Build Actions”

    Scroll down to “Post Build Actions” and click on the “Add Post Build Actions” drop-down list. Select “Publish HTML reports“. 

    If you want to see where the report will be saved in Jenkins, go to the Dashboard -> PyTestFramework_Demo -> Workspace -> Reports ->report.html.

    Enter the HTML directory to archive – Reports, Index page[s] – report.html, and Report title – HTML Report.

    Click on the Apply and Save buttons.

    We have created a new FreeStyle project “PyTestFramework_Demo” with the configuration to run the Python tests in windows batch.

    Step 5: Execute the tests

    Let’s execute it now by clicking on the “Build Now” button. 

    Right-click on Build Number (here in my case it is #1).

    Click on Console Output to see the result.

    Step 6: View the HTML Report

    Once the execution is completed, click on go “Back to Project“, and we could see a link to view the “HTML Report“.

    We can see here that the HTML Report link is displayed in the Console.

    Below is the HTML Report generated in Jenkins.

    There are chances that the report won’t look very pretty. The reason is that CSS is stripped out because of the Content Security Policy in Jenkins.

    The default rule set in Jenkins is:

    sandbox; default-src 'none'; img-src 'self'; style-src 'self';
    

    To know more about this, please refer to this tutorial – https://www.jenkins.io/doc/book/security/configuring-content-security-policy/.

    We can customize Content Security Policy in Jenkins. But keep in mind that it should be done after checking with the Security team in your organization. This is a workaround solution. I can’t emphasize enough that this is not a standard practice.

    Go to Manage Jenkins -> Manage Nodes and Clouds.

    Click on the Script Console option.

    Type in the following command and Press Run. If you see the output as ‘Result:’ then the protection is disabled. Re-Run your build and you can see that the new HTML files archived will have the CSS enabled.

    System.setProperty("hudson.model.DirectoryBrowserSupport.CSP","")
    

    Re-run the HTMLReport_Demo project. Now you can see a properly rendered HTML Report.

    Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!

    Additional Tutorials

    How to Install Python on Windows 11
    How to install and setup Robot Framework for Python
    How to rerun failed tests in Robot Framework
    How to implement tagging in Robot Framework
     How to set variable values from Runtime command in Robot Framework
    How to load data from CSV files in the Robot Framework?