automation-testing-selenium-python
Context
Browser testing, a crucial aspect of web development, ensures that your applications perform optimally across different
web browsers. It involves testing web applications for functionality, usability, and responsiveness, ensuring a
consistent and error-free user experience.
Role of Browser Testing in Web Development
Browser testing plays a pivotal role in the Quality Assurance (QA) phase of the Software Development Life Cycle (
SDLC). It helps developers and testers:
- Identify Cross-Browser Compatibility Issues: Ensures that the application works seamlessly across various browser
environments.
- Check Responsiveness and Visual Integrity: Verifies that the application’s layout and visual elements maintain
integrity across different screen sizes and resolutions.
- Enhance User Experience: Guarantees that all users, regardless of their browser choice, receive a fully functional
and accessible experience.
Integration in the SDLC
Browser testing is integrated at multiple stages of the SDLC:
- During Development: Early testing helps catch bugs before they become costly to fix.
- Post-Integration: After components are integrated, browser testing checks for new issues that might arise from
combined functionalities.
- Pre-Release: Before deployment, comprehensive testing ensures that the product is ready for the market and free
from major defects.
- Maintenance: Ongoing testing during the maintenance phase helps in keeping the application up-to-date with
browser updates and new standards.
Objective
The goal of this project is to run a series of tests on a demo website to showcase how Selenium WebDriver can automate
and streamline your browser testing processes.
Pre-requisites
Python Interpreter
- Python 3.10: Required version for compatibility with project scripts.
Dependencies Installed with Poetry
- Selenium 4.20.0 or higher: Automates web browsers, essential for web-based tests.
- webdriver-manager: Manages browser drivers automatically, simplifying test setup.
- pytest: Framework for writing and running tests.
- pytest-html: Plugin for generating HTML reports of test results.
- pytest-xdist: Allows parallel test execution to speed up the testing process.
Up and Running
Setup
Create a virtual environment in the root directory:
python3 -m venv env
source env/bin/activate
Install Poetry for dependency management:
env/bin/pip install -U pip setuptools
env/bin/pip install poetry
Install project dependencies:
poetry install
Running Tests
Running All Tests
Execute all tests with the following command (add -v
for verbose output):
pytest
Running Specific Tests
Run tests marked for specific features (e.g., login tests) by using markers as described in pytest.ini
:
pytest -m <marker>
Generating HTML Reports
Generate an HTML report of the test results with this command:
pytest --html=reports/report.html
Parallel Test Execution
By default, pytest runs tests sequentially. Run tests in parallel to reduce execution time. Adjust the number of
parallel tests according to your CPU cores (e.g., for 3 parallel tests):
pytest -n=3
Testing Features
- conftest.py: This file centralizes the definitions of fixtures, hooks, and plugins for pytest, making test
configuration management more streamlined.
- pytest.fixtures: Reusable blocks of code that can be used across multiple tests to increase modularity and improve
readability. See
conftest.py
for examples.
- fixture params variable: Allows for the parameterization of fixtures by passing different parameters, enabling
diverse test setups. Refer to
conftest.py
for usage.
- pytest.mark: Tags tests with custom labels, helping selectively execute tests based on these labels. For
implementation details, see
tests/
and pytest.ini
.
- pytest.mark.parametrize: Executes a test function multiple times with different sets of arguments, enhancing test
coverage. Examples can be found in
tests/
.
- pytest-addoption function: Introduces custom command-line options to pytest, increasing its flexibility. For
instance, it can be used to specify a browser for testing. See
conftest.py
for details.
Supported Browsers
This project supports the following browsers via Selenium: Firefox, Internet Explorer, Safari, Chrome, and Edge.
Appendix
About Selenium WebDriver
Selenium WebDriver is a browser automation library commonly used for writing end-to-end tests of web applications.
Version 4 is the standard for web automation.
Getting Started with Selenium
- Page Elements and Locators: Learn how to locate elements on a webpage.
- WebElement: Understanding the WebElement class and its usage.
- WebElement Commands: Commands to interact with WebElement.
- Assertions: Techniques for verifying test outcomes.
- Failing Tests: Handling and debugging failed tests.
Notes
PyTest
- Installing PyTest: Steps to install PyTest.
- Simple PyTest Tests: Writing basic tests with PyTest.
- Moving Selenium Test to PyTest: Integrating Selenium tests with PyTest.
- PyTest Marks: Marking and grouping tests.
- Registering Marks: How to register marks in
pytest.ini
.
Advantages of PyTest
- Runs multiple tests in parallel.
- Automatically detects tests.
- Allows skipping tests during execution.
- Free and open source.
- Easy to use.
Group Tests Using PyTest Marks
- Register marks with
pytest.ini
.
- Never trust a test that doesn’t fail.
- PyTest automates unit, integration, functional, and end-to-end tests.
Advanced PyTest Features
- HTML Reports: Generating test reports in HTML format.
- Fixtures: Reusing setup code with fixtures.
- Conftest File: Centralizing fixture definitions.
- Parameterized Tests: Running tests with multiple sets of data.
- Running Tests in Different Browsers: Configuring tests for various browsers.
- Custom Command Line Parameters: Adding custom options for test execution.
- Running Tests in All Browsers: Ensuring cross-browser compatibility.
- Running Tests in Parallel: Speeding up test execution with parallel tests.
Examples
PyTest Fixtures
- PyTest Fixtures Documentation
- Example of parameterizing a test:
@pytest.mark.parametrize("username, password, expected_error_message",
[("incorrectUser", "Password123", "Your username is invalid!"),
("student", "incorrectPassword", "Your password is invalid!")])
Adding Command Line Options
-
Adding Options Documentation
def pytest_addoption(parser):
parser.addoption(
"--browser", action="store", default="chrome", help="browser to execute test (chrome or firefox)"
)
@pytest.fixture()
def driver(request):
browser = request.config.getoption("--browser")
if browser == "chrome":
...
elif browser == "firefox":
...
else:
raise TypeError(f"Expected 'chrome' or 'firefox' but got {browser}")
-
Running tests in parallel with pytest-xdist
:
pytest -m login --html=reports/report.html -n=3
n
= number of tests running in parallel (should not exceed the number of CPU cores).
Selenium Waits and Common Exceptions
- Debugging Tests: Strategies for debugging.
- WebDriver Waits: Using waits to manage element timing.
- Using Implicit Wait: Setting a global wait time.
- Exceptions in Selenium WebDriver: Handling common exceptions.
Common Exceptions
- NoSuchElementException: Element not found.
- ElementNotInteractableException: Element cannot be interacted with.
- InvalidElementStateException: Invalid state of element.
- StateElementReferenceException: Stale element reference.
- TimeoutException: Element did not appear in time.
Notes
- Waiting strategies: Waiting Strategies
- Expected
conditions: Expected Conditions
- Understand Implicit and Explicit
waits: Wait Commands in Selenium
- Implicit Wait: Sets a global wait time for all elements.
- Explicit Wait: Waits for a specific condition to occur before proceeding.
- Fluent Wait: Similar to Explicit Wait, but allows for polling frequency and ignoring specific exceptions.
Page Object Model (POM)
- What is Page Object Model?: A design pattern in UI automation testing that promotes a clear structure for managing
web pages and elements in test scripts.
Advantages of POM
- Separation of Concerns: Keeps test code clean and maintainable by separating operations and verifications.
- Reusability: Allows for the reuse of code across multiple tests.
- Readability: Enhances readability with realistic method names.
- Maintenance: Simplifies maintenance by centralizing changes in the page object classes.
Implementing Page Objects
- Login Page Object: Implementing a login page to handle login functionalities.
- Logged in Successfully Page Object: Handling post-login actions.
- Base Page Object: Creating a base class for common functionalities across pages.
- Inheriting from Base Page: Reusing base page functionality in other page objects.
- Using Page Objects: Writing tests using page objects to interact with the application.
Additional Resources