
Input and Select Cheat Sheet
Handy Reference to add text when running Automation
Automating user input and form interactions is a core part of UI testing with Selenium. This cheat sheet provides quick reference examples for entering text and interacting with dropdown menus in a Pytest test suite.
Typing into Input Fields
from selenium.webdriver.common.by import By
# Find input by ID and enter text
username_input = driver.find_element(By.ID, "username")
username_input.clear()
username_input.send_keys("test_user")
# Find input by Name attribute
email_input = driver.find_element(By.NAME, "email")
email_input.send_keys("user@example.com")
# Input into a field using CSS selector
password_input = driver.find_element(By.CSS_SELECTOR, "input[type='password']")
password_input.send_keys("securePassword123")
Working with Select Menus
Selenium provides a helper class called Select
for interacting with dropdowns built using the HTML <select>
tag.
from selenium.webdriver.support.ui import Select
# Select option by visible text
dropdown = Select(driver.find_element(By.ID, "country"))
dropdown.select_by_visible_text("Canada")
# Select option by index
dropdown.select_by_index(2)
# Select option by value
dropdown.select_by_value("us")
Validating Input Values
# Assert input value is what we typed
assert username_input.get_attribute("value") == "test_user"
Bonus: Handling Auto-Suggest Inputs
# Type and wait for suggestion list, then select item
search_box = driver.find_element(By.ID, "search")
search_box.send_keys("Pytest")
# Wait and click suggestion
suggestion = driver.find_element(By.XPATH, "//li[contains(text(), 'Pytest Tutorial')]")
suggestion.click()
These examples serve as a solid foundation for common input tasks in your Selenium test cases. Keep this guide handy when building tests involving forms, login fields, or dropdown menus.
PermalinkPytest + Selenium Selector Type Cheat Sheet
Handy Guide to Have for find_elements
When using Pytest with Selenium, knowing which selector strategy to use can save time and boost test reliability. This cheat sheet summarizes the most common selector types along with syntax examples and practical use cases.
Below is a handy reference image you can download and keep for quick access during test writing.

Common Selector Examples
# ID
driver.find_element(By.ID, "login") # Fast and most reliable
# Name
driver.find_element(By.NAME, "username") # Often used in forms
# Class Name
driver.find_element(By.CLASS_NAME, "btn-primary") # Good for unique CSS classes
# Tag Name
driver.find_element(By.TAG_NAME, "input") # Generic, works when no better option exists
# CSS Selector
driver.find_element(By.CSS_SELECTOR, ".menu > li") # Flexible, powerful, great for nested elements
# XPath
driver.find_element(By.XPATH, "//div[@id='main']") # Very powerful for complex DOMs
# Link Text
driver.find_element(By.LINK_TEXT, "Sign in") # When matching exact visible link text
# Partial Link Text
driver.find_element(By.PARTIAL_LINK_TEXT, "Sign") # For dynamic or lengthy link text
Understanding the strengths of each selector type can help you write more stable and maintainable Selenium tests. Keep this cheat sheet nearby during your next automation sprint.
PermalinkPytest and Selenium: Finding All Anchor Elements
Useful Tips and Trick with Elements
When performing web automation tests, a common task is to interact with or verify links on a webpage. Using Pytest with Selenium makes this process straightforward. This post will walk you through a simple way to find all anchor elements (<a>
tags) on a page.
The Basics of Finding Elements
Selenium provides various methods to locate elements on a webpage. One of the most fundamental is find_elements
, which allows you to retrieve a list of all elements matching a specified locator strategy. To find anchor tags, we use By.TAG_NAME
.
Sample Code for Pytest
Here's a simple Pytest example demonstrating how to find all link elements on a page. We assume you have a Selenium WebDriver instance (driver
) already set up.
from selenium import webdriver
from selenium.webdriver.common.by import By
import pytest
def test_find_all_links(driver):
# Navigate to a sample page (replace with your URL)
driver.get("https://www.example.com")
# Find all link elements
links = driver.find_elements(By.TAG_NAME, "a")
# You can then iterate through the links or perform assertions
print(f"Found {len(links)} anchor elements.")
for link in links:
if link.text: # Print link text if available
print(f"Link Text: {link.text}, URL: {link.get_attribute('href')}")
else: # If no text, just print the URL
print(f"URL: {link.get_attribute('href')}")
# Example assertion: check if at least one link exists
assert len(links) > 0, "No anchor elements found on the page."
Explanation
-
driver.get("https://www.example.com")
: This line navigates your WebDriver instance to the specified URL. Remember to replace "https://www.example.com" with the actual URL of the page you are testing. -
links = driver.find_elements(By.TAG_NAME, "a")
: This is the core of the operation.-
driver.find_elements
: This method returns a list of web elements. If no elements are found, it returns an empty list. -
By.TAG_NAME
: This is the locator strategy, indicating that we want to find elements by their HTML tag name. -
"a"
: This is the value for our locator strategy, specifically targeting the anchor tag.
-
- The subsequent loop iterates through the `links` list. For each `link` element, we print its text (if available) and its `href` attribute, which contains the URL.
-
assert len(links) > 0
: A simple assertion to ensure that at least one anchor element was found. This is a basic example; in real tests, you would have more specific assertions based on your requirements.
Recording Page Load Time with Pytest and Saving to CSV
Automatically Track the Page Load Time for Performance checking
Tracking page load performance is a critical part of maintaining a fast and user-friendly website. In this tutorial, we will use pytest
and Python’s built-in tools to measure how long a page takes to load and save the results to a CSV file. Each row in the CSV will include a timestamp and the corresponding load time.
What You Need
pytest
requests
datetime
andcsv
from the standard library
The Code
This code fetches a web page, measures the response time, and logs the result with a timestamp to a CSV file.
import pytest
import requests
import time
import csv
from datetime import datetime
URL_TO_TEST = "https://www.americanfreight.com/"
CSV_FILE = "page_load_times.csv"
def write_to_csv(timestamp, load_time):
"""Append timestamp and load time to the CSV file."""
with open(CSV_FILE, mode="a", newline="") as file:
writer = csv.writer(file)
writer.writerow([timestamp, load_time])
@pytest.mark.parametrize("url", [URL_TO_TEST])
def test_page_load_time(url):
"""Measure the page load time and write to a CSV file."""
start_time = time.time()
response = requests.get(url)
end_time = time.time()
load_time = round(end_time - start_time, 3)
timestamp = datetime.now().isoformat(timespec="seconds")
assert response.status_code == 200, f"Failed to load page: {response.status_code}"
write_to_csv(timestamp, load_time)
print(f"Page loaded in {load_time} seconds at {timestamp}")
Sample CSV Output
Here is what the CSV file will look like after a few test runs:
2025-05-21T13:00:01,1.276
2025-05-21T13:10:43,1.304
2025-05-21T13:20:22,1.142
Automating in CI
You can easily integrate this into your CI pipeline to monitor page load performance over time. Combine it with cron jobs or GitHub Actions to schedule regular runs and keep tabs on performance degradation.
Tips
- Use
requests.Session()
for persistent connections if testing multiple pages. - Extend the CSV format to include response size or headers if needed.
- Visualize the results using tools like Excel or Python’s
matplotlib
.
Conclusion
Measuring and recording page load times with pytest
is simple yet powerful. With just a few lines of code, you can start building a performance history and catching slowdowns before they impact your users.
Validating Sitemap Namespace with Pytest
Basic Pytest setup
Sitemaps help search engines index your website correctly. But a malformed or incorrectly-namespaced sitemap can cause issues with indexing. This post walks through using pytest
to validate that your sitemap uses the correct XML namespace.
Why Namespace Validation Matters
The XML namespace ensures the sitemap conforms to the sitemaps.org protocol. If the namespace is incorrect or missing, search engines may ignore your sitemap, leading to poor visibility.
The Test Code
Below is the code that checks whether the sitemap at https://www.americanfreight.com/sitemap.xml
is valid and correctly namespaced:
import pytest
import requests
import xml.etree.ElementTree as ET
from urllib.parse import urlparse
# Define the sitemap URL
SITEMAP_URL = "https://www.americanfreight.com/sitemap.xml"
@pytest.fixture
def sitemap_content():
"""Fixture to fetch and return the sitemap XML content."""
response = requests.get(SITEMAP_URL)
assert response.status_code == 200, f"Failed to fetch sitemap: {response.status_code}"
return response.content
@pytest.fixture
def sitemap_root(sitemap_content):
"""Fixture to parse the sitemap XML and return the root element."""
return ET.fromstring(sitemap_content)
def test_sitemap_fetch(sitemap_content):
"""Test that the sitemap can be fetched successfully."""
assert sitemap_content is not None, "Sitemap content is empty"
assert b"<?xml" in sitemap_content, "Sitemap is not valid XML"
def test_sitemap_root_namespace(sitemap_root):
"""Test that the sitemap has the correct XML namespace."""
expected_namespace = "http://www.sitemaps.org/schemas/sitemap/0.9"
assert sitemap_root.tag == f"{{{expected_namespace}}}urlset",
f"Unexpected root tag or namespace: {sitemap_root.tag}"
Running the Test
To run the tests, use the following command in your terminal:
pytest test_sitemap_namespace.py
Test Breakdown
- sitemap_content: Fetches the sitemap and ensures it's accessible (status 200).
- sitemap_root: Parses the XML content for further inspection.
- test_sitemap_fetch: Confirms the sitemap starts with the
<?xml
declaration. - test_sitemap_root_namespace: Verifies the root element includes the correct namespace defined by sitemaps.org.
Conclusion
These simple but powerful tests can catch issues early in your CI pipeline. Whether you're managing SEO for a large e-commerce platform or a personal blog, namespace correctness should be a non-negotiable in your automated checks.
PermalinkHow to Check URL Validity
Quick and Easy
A quick guide to validating URLs after a release using Pytest and Python's requests library.
Introduction
After a software release, ensuring that all URLs are accessible is critical. This blog post demonstrates how to use Pytest and the requests library to check if URLs return a 200 status code, indicating they are valid and accessible. This approach is fast, reliable, and easy to integrate into your testing pipeline.
Prerequisites
- Python 3.6 or higher
- Pytest (
pip install pytest
) - Requests library (
pip install requests
)
Sample Code
Below is a simple Pytest script to check if a URL returns a 200 status code:
import pytest
import requests
def test_url_returns_200():
url = "https://www.cryan.com"
try:
response = requests.get(url, timeout=5)
assert response.status_code == 200
except requests.RequestException as e:
pytest.fail(f"Request failed: {e}")
This test sends a GET request to the specified URL and checks if the response status code is 200. If the request fails (e.g., due to a timeout or network issue), the test fails with an error message.
Running the Test
Save the code in a file (e.g., test_urls.py
) and run it using the following command:
pytest test_urls.py -v
The -v
flag provides verbose output, showing the test results in detail.
Scaling to Multiple URLs
To test multiple URLs, you can use Pytest's parameterization feature. Here's an example:
import pytest
import requests
@pytest.mark.parametrize("url", [
"https://www.cryan.com",
"https://www.example.com",
"https://www.python.org",
])
def test_url_returns_200(url):
try:
response = requests.get(url, timeout=5)
assert response.status_code == 200
except requests.RequestException as e:
pytest.fail(f"Request failed for {url}: {e}")
This script tests multiple URLs in a single test function, making it efficient for checking several endpoints after a release.
Best Practices
- Set a reasonable timeout (e.g., 5 seconds) to avoid hanging tests.
- Use parameterization to test multiple URLs efficiently.
- Integrate tests into your CI/CD pipeline for automated checks post-release.
- Log failures with detailed messages to aid debugging.
Conclusion
Using Pytest and the requests library, you can quickly validate URLs after a release. This approach is simple, scalable, and integrates well with automated testing workflows. By incorporating these tests into your pipeline, you can ensure your application's URLs remain accessible and reliable.
In Pytest, what is the Best Date/Time Format for Filenames
Basic Filename Format to find Files
The best date/time format for filenames is ISO 8601 with modifications to ensure compatibility and readability. I recommend using YYYYMMDD_HHMMSS
(e.g., 20250430_143022
) for the following reasons:
- Sortability: ISO 8601 (year-month-day) ensures files sort chronologically when listed.
- Uniqueness: Including seconds prevents filename collisions during rapid test runs.
- Readability: The format is clear and universally understood.
- Filesystem Safety: Replacing colons (
:
) with underscores (_
) avoids issues on filesystems that don't allow colons in filenames.
Here's an example of generating a timestamped filename in pytest
:
import pytest
from datetime import datetime
def get_timestamped_filename(base_name, extension):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
return f"{base_name}_{timestamp}.{extension}"
# Example usage in a test
def test_example():
filename = get_timestamped_filename("screenshot", "png")
# Save screenshot with filename like "screenshot_20250430_143022.png"
print(f"Saving screenshot as {filename}")
Tip: If you need microseconds for high-frequency tests, use datetime.now().strftime("%Y%m%d_%H%M%S_%f")
to include microseconds (e.g., 20250430_143022_123456
).
Alternative: For human-readable logs, you might include a readable date in the file content but keep the filename simple and sortable. For example, save a log with a header like Test Run: April 30, 2025 14:30:22
inside the file, but name the file log_20250430_143022.txt
.
Check Image Sizes on Production Websites
Using Python and Pytest to Catch Bloated Images Before They Slow Down Your Site
Large images can slow down page performance and negatively impact user experience. During one of my past QA roles, I created a simple Python function to detect when an image might be too large based on its content length header.
Use Case
Our QA team was tasked with verifying the size of images on the production site to ensure they met
optimization standards. While tools like Lighthouse can highlight these issues, I needed something
scriptable - and Pytest
+ requests
was a lightweight and perfect solution.
Sample Code
Here’s a simplified version of the utility function I used in our automated tests:
import requests
def check_image_size(img_url, base_url="https://www.cryan.com"):
# Construct full URL if necessary
if not img_url.startswith(('http://', 'https://')):
img_url = base_url + img_url if img_url.startswith('/') else base_url + '/' + img_url
try:
response = requests.get(img_url, stream=True)
response.raise_for_status()
# Check content length if provided in headers
content_length = response.headers.get('Content-Length')
if content_length and int(content_length) > 1000:
return f"Image at {img_url} might be too large: Header indicates {int(content_length)/1000}KB"
except Exception as e:
return f"Error checking image size: {e}"
return f"Image at {img_url} appears to be an acceptable size."
How to Use It in Pytest
Integrate this into your test suite by looping through known image paths:
def test_image_sizes():
image_paths = [
"/images/logo.png",
"/media/banner.jpg",
"/assets/hero-large.jpg"
]
for img in image_paths:
result = check_image_size(img)
assert "too large" not in result, result
Pro Tip
Content-Length
header, which isn't always accurate for dynamically
generated or CDN-compressed images. For full accuracy, you could download the stream and measure bytes.
Dependencies
This example uses the requests
library:
pip install requests
Permalink
Verifying Your Pytest Setup with a Simple Selenium Test
Quick Test to make sure proper installation
In this post, we'll walk through creating a basic Pytest test that uses Selenium WebDriver to navigate to
www.google.com
and validate that the word "Google" appears in the page title. This test serves
as a lightweight check to ensure your Pytest environment is ready to go.
Prerequisites
Before we dive in, make sure you have the following installed:
- Python: Version 3.7 or higher.
- Pytest: Install it using
pip install pytest
orpython3 -m pip install pytest --user
. - Selenium WebDriver: Install it using
pip install selenium
orpython3 -m pip install selenium --user
. - Web Browser Driver: For this example, we'll use
ChromeDriver. Download it from the ChromeDriver website and ensure it matches your Chrome
browser version. Place the
chromedriver
executable in your system’s PATH or specify its location in the code.
Setting Up the Project
- Create a new directory for your project, e.g.,
pytest_setup_test
. - Inside the directory, create a virtual environment (optional but
recommended):
python -m venv venv source venv/bin/activate # On Windows: venvScriptsactivate
- Install the required packages:
pip install pytest selenium
- Create a file named
test_google.py
to hold our test.
Writing the Pytest Test
Here’s the code for test_google.py
, which uses Selenium to navigate to
www.google.com
and checks the page title:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import pytest
# Fixture to set up and tear down the WebDriver
@pytest.fixture
def browser():
# Specify the path to ChromeDriver if not in PATH
# service = Service('/path/to/chromedriver') # Uncomment and update if needed
service = Service()
driver = webdriver.Chrome(service=service)
yield driver
driver.quit()
# Test to validate the page title of google.com
def test_google_title(browser):
browser.get("https://www.google.com")
title = browser.title
assert "Google" in title, f"Expected 'Google' in title, but got '{title}'"
Explanation
- Fixture (
browser
): Thepytest.fixture
decorator defines a reusable setup/teardown function. Here, it initializes a Chrome WebDriver instance and yields it to the test. After the test runs,driver.quit()
closes the browser. - Test Function (
test_google_title
): This function uses thebrowser
fixture to:- Navigate to
https://www.google.com
usingbrowser.get()
. - Retrieve the page title with
browser.title
. - Assert that the word "Google" is in the title. If not, the test fails with a descriptive message.
- Navigate to
- ChromeDriver Path: If ChromeDriver is not in your system’s
PATH, uncomment the
service
line and specify the path to thechromedriver
executable.
Running the Test
To run the test, navigate to your project directory in the terminal and execute:
pytest test_google.py -v
Expected Output
If everything is set up correctly, you should see output similar to this:
============================= test session starts ==============================
platform linux -- Python 3.9.5, pytest-7.4.3, pluggy-1.0.0
collected 1 item
test_google.py::test_google_title PASSED [100%]
============================== 1 passed in 2.34s ===============================
- PASSED: Indicates the test ran successfully, confirming that Pytest and Selenium are configured correctly, and the word "Google" was found in the page title.
- FAILED: If the test fails, check the error message. Common
issues include:
- ChromeDriver not found (verify the path or PATH configuration).
- Network issues preventing access to
www.google.com
. - Mismatched ChromeDriver and Chrome browser versions.
Troubleshooting Tips
- ChromeDriver Issues: Ensure ChromeDriver matches your
Chrome version (check Chrome’s version in
Settings > About Chrome
). Update or reinstall ChromeDriver if needed. - Pytest Not Found: Verify Pytest is installed in your active
environment (
pip show pytest
). - Selenium Errors: Confirm Selenium is installed
(
pip show selenium
) and that you’re using a compatible version with your browser.
﹤li class="list-group-item">Test Fails Due to Title: Occasionally, Google’s title might
vary (e.g., due to localization). You can modify the assertion to be more flexible if needed.
Why This Test?
This test is a simple yet effective way to validate your Pytest setup because it:
- Confirms Pytest is installed and running tests correctly.
- Verifies Selenium WebDriver is configured and can interact with a browser.
- Checks network connectivity and browser compatibility.
- Provides a clear pass/fail outcome with minimal code.
Next Steps
Once this test passes, your Pytest environment is ready! You can expand your test suite to include more complex scenarios, such as:
- Testing form submissions or button clicks.
- Validating other websites or web applications.
- Integrating with CI/CD pipelines for automated testing.
Feel free to tweak this test to suit your needs. For example, you could test a different website or validate other page elements like text or links. Happy testing!
Spell-Check Your Site Using Pytest
Use Automation to Check Spelling
Here's a clever way to catch embarrassing spelling mistakes on your website using pytest
and spellchecker
. This script can be scheduled to run periodically to ensure nothing slips through the cracks!
Why Check for Spelling?
Spelling errors can reduce trust, affect SEO, and just look unprofessional. With this script, you can automatically scan your site's content and get alerted if anything seems off.
Dependencies
pytest
requests
beautifulsoup4
pyspellchecker
Install them with:
pip install pytest requests beautifulsoup4 pyspellchecker
The Test Code
Here is the full test you can drop into your test suite:
import pytest
import requests
from bs4 import BeautifulSoup
from spellchecker import SpellChecker
from urllib.parse import urljoin
def get_visible_text(url):
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
except requests.RequestException as e:
pytest.fail(f"Failed to fetch {url}: {e}")
soup = BeautifulSoup(response.text, 'html.parser')
for element in soup(['script', 'style', 'header', 'footer', 'nav', 'aside']):
element.decompose()
text = soup.get_text(separator=' ', strip=True)
return text
def check_spelling(text, custom_words=None):
spell = SpellChecker()
if custom_words:
spell.word_frequency.load_words(custom_words)
words = text.split()
misspelled = spell.unknown(words)
return misspelled
def test_spelling_cryan_com():
url = "https://www.cryan.com"
custom_words = ["cryan", "blog", "tech", "xai"]
text = get_visible_text(url)
misspelled_words = check_spelling(text, custom_words=custom_words)
assert not misspelled_words, (
f"Spelling errors found on {url}: {misspelled_words}"
)
if __name__ == "__main__":
pytest.main(["-v", __file__])
Customization Tips
- Add more custom words to avoid false positives like brand names or domain-specific terms.
- Expand to multiple pages by looping through URLs and running the same logic.
- Integrate with CI/CD for automatic detection during deployment.
About
Welcome to Pytest Tips and Tricks, your go-to resource for mastering the art of testing with Pytest! Whether you're a seasoned developer or just dipping your toes into the world of Python testing, this blog is designed to help you unlock the full potential of Pytest - one of the most powerful and flexible testing frameworks out there. Here, I'll share a treasure trove of practical insights, clever techniques, and time-saving shortcuts that I've gathered from years of writing tests and debugging code.
Check out all the blog posts.
Blog Schedule
Wednesday 18 | Pytest |
Thursday 19 | PlayWright |
Friday 20 | Macintosh |
Saturday 21 | Internet Tools |
Sunday 22 | Misc |
Monday 23 | Media |
Tuesday 24 | QA |
Other Posts
- Recording Page Load Time with Pytest and Saving to CSV
- Input and Select Cheat Sheet
- How to Check URL Validity
- In Pytest, what is the Best Date/Time Format for Filenames
- Using pytest.raises to Validate Exceptions Like a Pro
- Level Up Your Pytest WebDriver Game
- Capturing Screenshots in Fixture Teardown
- Naming Screenshots Dynamically in Pytest
- Spell-Check Your Site Using Pytest
- Pytest + Selenium Selector Type Cheat Sheet
- PyTest Install
- Check Image Sizes on Production Websites
- Parametrization in Pytest
- mocker.spy
- Validating Sitemap Namespace with Pytest