Introduction
When writing Selenium tests with PyTest, it’s important to ensure that resources such as browser sessions are cleaned up properly after every test. If a browser is not closed correctly, it can consume system resources and affect subsequent test executions.
A Yield Fixture provides an elegant way to perform both setup and teardown within a single fixture. Code written before the yield statement executes before the test begins, while code written after yield runs automatically after the test finishes—even if the test fails.
In this tutorial, you’ll learn how Yield Fixtures work in PyTest, how they simplify Selenium automation, and why they are the preferred approach for managing browser setup and cleanup.
What are Yield Fixtures?
A Yield Fixture is a PyTest fixture that uses the yield statement to divide the fixture into two parts:
Setup (before
yield)Teardown (after
yield)
Example:
Test Starts
│
▼
Setup Code
(Launch Browser)
│
▼
yield
│
▼
Execute Test
│
▼
Teardown Code
(Delete Cookies & Close Browser)
The browser is prepared before the test starts and automatically cleaned up after the test finishes.
Why Use Yield Fixtures?
Yield Fixtures help you:
Automate browser setup and cleanup.
Avoid duplicate teardown code.
Improve test reliability.
Ensure resources are always released.
Build cleaner automation frameworks.
How Yield Fixtures Work
A Yield Fixture uses the yield statement to separate setup and teardown.
Example:
@pytest.fixture
def browser():
driver = webdriver.Chrome()
yield driver
driver.quit()
Everything before yield performs the setup.
Everything after yield performs the cleanup.
Example
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
# Topic: 40. Fixtures - Yield Fixtures
# Practice site: https://www.testmuai.com/selenium-playground/input-form-demo
# Run: pytest -s 40_examples/test_03_yield_fixtures.py
#
# Code before yield is setup. Code after yield is teardown and always runs when
# the test finishes, even if it fails.
@pytest.fixture
def cleaned_browser():
driver = webdriver.Chrome()
driver.maximize_window()
yield driver
driver.delete_all_cookies()
driver.quit()
def test_yield_fixtures(cleaned_browser):
cleaned_browser.get("https://www.testmuai.com/selenium-playground/input-form-demo")
name = cleaned_browser.find_element(By.ID, "name")
name.send_keys("Selenium User")
assert name.get_attribute("value") == "Selenium User"
Understanding the Code
Import Required Libraries
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
These modules are required to:
Create PyTest fixtures.
Launch the Chrome browser.
Locate web elements.
Create a Yield Fixture
@pytest.fixture
def cleaned_browser():
The @pytest.fixture decorator tells PyTest that cleaned_browser() is a reusable fixture.
Whenever a test requests the cleaned_browser fixture, PyTest executes it automatically.
Launch the Browser
driver = webdriver.Chrome()
Creates a new Chrome browser session.
This is part of the fixture’s setup phase.
Maximize the Browser Window
driver.maximize_window()
Maximizes the browser window before executing the test.
This helps ensure consistent element visibility across different screen resolutions.
Pause the Fixture Using yield
yield driver
The yield statement passes the browser instance to the test function.
PyTest pauses the fixture here while the test executes.
Once the test completes, PyTest resumes execution with the code following yield.
Delete All Browser Cookies
driver.delete_all_cookies()
Removes all cookies stored during the test execution.
This helps prevent leftover session data from affecting future tests.
Close the Browser
driver.quit()
Closes all browser windows and ends the WebDriver session.
This teardown step executes automatically after every test, even if the test encounters an error.
Open the Practice Website
cleaned_browser.get(
"https://www.testmuai.com/selenium-playground/input-form-demo"
)
Navigates to the Input Form Demo page.
Locate the Name Field
name = cleaned_browser.find_element(
By.ID,
"name"
)
Locates the Name input field using its ID.
Enter the Name
name.send_keys("Selenium User")
Enters the text Selenium User into the input field.
Verify the Entered Value
assert name.get_attribute(
"value"
) == "Selenium User"
The assert statement verifies that the value entered into the textbox matches the expected text.
If the values do not match, PyTest marks the test as failed.
Practical Example
Suppose your Selenium automation suite executes hundreds of form validation tests.
Each test should:
Launch a browser.
Execute the test.
Clear cookies.
Close the browser.
A Yield Fixture performs these tasks automatically, eliminating repetitive cleanup code.
Automation Testing Example
Consider an online shopping application.
Each test needs to:
Open the browser.
Log in to the application.
Execute the shopping workflow.
Remove session cookies.
Close the browser.
Using a Yield Fixture ensures that every test starts with a clean browser session.
Real-World Example
Yield Fixtures are commonly used in:
Selenium automation frameworks
Regression testing
Cross-browser testing
API automation
Data-driven testing
CI/CD pipelines
Enterprise automation projects
Most professional Selenium frameworks use Yield Fixtures to manage browser setup and teardown efficiently.
Advantages of Yield Fixtures
Combine setup and teardown in one fixture.
Automatically clean up resources.
Reduce duplicate code.
Improve test reliability.
Simplify framework maintenance.
Common Mistakes Beginners Make
Using return Instead of yield
Using return ends the fixture immediately.
Use yield whenever cleanup code needs to execute after the test.
Forgetting Cleanup Code
Always place browser cleanup after the yield statement to prevent unused browser sessions from remaining open.
Writing Teardown Before yield
Only setup code should appear before yield.
Cleanup operations belong after yield.
Assuming Teardown Runs Only on Successful Tests
Code after yield executes whether the test passes or fails.
This ensures proper resource cleanup in all situations.
Best Practices
Use
yieldinstead ofreturnfor Selenium fixtures.Keep setup code before
yield.Place cleanup code after
yield.Always close the browser using
driver.quit().Clear cookies when browser isolation is required.
Keep fixtures simple and reusable.
Conclusion
Yield Fixtures are the recommended way to manage setup and teardown in PyTest. By separating browser initialization from cleanup using the yield statement, they produce cleaner, more maintainable, and more reliable Selenium automation tests. They also ensure that browser sessions are properly cleaned up, even when tests fail unexpectedly.
Frequently Asked Questions (FAQs)
What is a Yield Fixture?
A Yield Fixture is a PyTest fixture that uses the yield statement to separate setup and teardown code.
Why use yield instead of return?
The yield statement allows PyTest to execute cleanup code after the test completes.
With return, the fixture ends immediately and teardown code does not execute.
When does the code after yield execute?
The code after yield executes automatically after the test finishes, regardless of whether the test passes or fails.
Can I perform browser cleanup after yield?
Yes.
Operations such as driver.delete_all_cookies() and driver.quit() are commonly placed after the yield statement.
Why are Yield Fixtures recommended for Selenium?
Yield Fixtures simplify browser management, reduce duplicate code, ensure reliable cleanup, and improve the overall maintainability of Selenium automation frameworks.
Key Takeaways
Yield Fixtures separate setup and teardown using the
yieldstatement.Code before
yieldperforms setup.Code after
yieldperforms cleanup.Cleanup code executes even if the test fails.
Yield Fixtures are the recommended approach for Selenium browser management in PyTest.
Proper use of Yield Fixtures helps build reliable and maintainable automation frameworks.
