Exit course
Chapter 1 of 10 Intermediate 5 min read Updated

Selenium Python Tutorial with pytest

A Selenium Python tutorial built on pytest: setup with Selenium Manager, locators, explicit waits, fixtures, screenshots on failure, page objects, parallel runs with pytest-xdist and a cloud grid.

What you will learn

  1. Selenium Python Tutorial with pytest
  2. Set up Selenium with Python and pytest
  3. Selenium locators in Python: the By API
  4. Selenium waits in Python: WebDriverWait and time.sleep
  5. pytest fixtures for Selenium: conftest.py and scope
  6. Assertions, screenshots on failure and test reports
  7. Page objects in Python
  8. Run Selenium tests in parallel with pytest-xdist
  9. Run Selenium Python tests on the TestingBot grid
  10. Selenium Python Quiz
On this page
  1. Selenium drives the browser, pytest runs the tests
  2. Why pytest and not unittest?
  3. What you'll build
  4. Prerequisites

Last reviewed November 2026 against Selenium 4.52.0, pytest 9.2.0, pytest-xdist 3.8.0, pytest-html 4.2.0 and Python 3.13.

This course builds a small but complete browser test suite in Python. Every example in it was run, first against local Chrome and Firefox and then, in the last chapter, on the TestingBot grid. By the end you will have one project that you can run on your laptop, in CI and on a cloud grid without changing a single test.

Selenium drives the browser, pytest runs the tests#

The suite is built from two libraries that do very different jobs, and most early confusion comes from mixing them up.

Selenium WebDriver is a browser automation library. It starts a browser, navigates, finds elements, clicks, types and reads text back. It has no idea what a test is: it does not know what "passed" means and it will leave a browser running forever if you forget to call quit().

pytest is a test runner. It finds functions whose names start with test_, runs setup and teardown code around them through fixtures, feeds them data, rewrites plain assert statements so failures explain themselves, and reports what passed and failed. It knows nothing about browsers.

Concern Who handles it
Start and stop a browser Selenium (webdriver.Chrome(), driver.quit()), called from a pytest fixture
Find elements, wait for them, interact Selenium (By, WebDriverWait, expected_conditions)
Discover and select tests pytest (test_ functions, -k, markers)
Check results pytest (plain assert)
Run one test with several inputs pytest (@pytest.mark.parametrize)
Run tests in parallel pytest-xdist schedules the workers; each test still needs its own browser
Screenshots and reports on failure pytest hooks and plugins, using Selenium to take the screenshot

Here is the whole idea in a dozen lines:

import pytest
from selenium import webdriver


@pytest.fixture
def driver():
    driver = webdriver.Chrome()   # Selenium: start a browser
    yield driver                  # pytest: hand it to the test
    driver.quit()                 # pytest runs this after the test, pass or fail


def test_title(driver):           # pytest: this is a test
    driver.get("https://www.selenium.dev/selenium/web/web-form.html")
    assert driver.title == "Web form"

Nothing here downloads a ChromeDriver binary. Since Selenium 4.6, Selenium Manager ships inside the selenium package and finds or downloads the right driver the first time you start a browser. Tutorials that begin with "download chromedriver and add it to your PATH" are out of date.

Why pytest and not unittest?#

Python ships with unittest, and Selenium works with it. pytest has become the usual choice for browser suites because:

  • Fixtures replace setUp/tearDown classes. A browser fixture is written once in conftest.py and any test that names driver as an argument gets one.
  • Plain assert gives readable failure diffs without assertEqual and friends.
  • Parametrisation turns one test into many with a decorator.
  • Plugins add parallel runs (pytest-xdist), HTML reports (pytest-html) and much more, and pytest also runs existing unittest tests unchanged.

If your team already uses unittest, TestingBot has a PyUnit example. This course uses pytest throughout.

What you'll build#

Chapter You add
1. Set up Python, Selenium and pytest a virtual environment, Selenium Manager, a first passing test
2. Locators the By strategies and a rule for picking stable ones
3. Waits WebDriverWait and expected conditions instead of time.sleep
4. Fixtures a driver fixture in conftest.py, command-line options, parametrisation
5. Assertions, screenshots and reports a screenshot for every failure, HTML and JUnit XML reports
6. Page objects a small page object, and where to go for more
7. Parallel runs pytest-xdist and the rules that keep parallel tests independent
8. The TestingBot grid remote browsers, tb:options, pass/fail status, GitHub Actions
9. Quiz ten questions on the decisions the course made

The final project looks like this:

selenium-python-course/
  conftest.py          driver fixture, command-line options, screenshot hook
  pytest.ini           test paths and markers
  requirements.txt     pinned versions
  pages/
    web_form.py        page object
  tests/
    test_web_form.py
    test_dynamic.py

The tests use the practice pages the Selenium project publishes for exactly this purpose: a web form and a page that adds elements after a delay. They are public, stable and safe to hit from a test.

Prerequisites#

  • Python 3.10 or newer. Selenium 4.52 and pytest 9 both require it. The examples were run on Python 3.13.
  • Basic Python: functions, imports, a class or two.
  • Chrome installed locally (Firefox too, if you want to follow the cross-browser parts).
  • No prior Selenium experience.

If you write Java rather than Python, the sibling course Selenium with Java and TestNG builds the same suite with Maven and TestNG. And for a common misconception up front: there is no official certification from the Selenium project. What employers look for is a suite you can explain, which is what this course builds.