Manual Testing with Playwright MCP – Have you ever felt that a simple manual test should be less manual?
For years, quality assurance relied on pure human effort to explore, click, and record. But what if you could perform structured manual and exploratory testing, generate detailed reports, and even create test cases—all inside your Integrated Development Environment (IDE), using zero code?
I’ll tell you this: there’s a tool that can help us perform manual testing in a much more structured and easy way inside the IDE: Playwright MCP.
Section 1: End the Manual Grind – Welcome to AI-Augmented QA
The core idea is to pair a powerful AI assistant (like GitHub Copilot) with a tool that can control a real browser (Playwright MCP). This simple setup is done in only a few minutes.
The Essential Setup for Manual Testing with Playwright MCP: Detailed Steps
For this setup, you will integrate Playwright MCP as a tool that your AI agent can call directly from VS Code.
1. Prerequisites (The Basics)
VS Code installed in your system.
Node.js (LTS version recommended) installed on your machine.
2. Installing GitHub Copilot (The AI Client)
Open Extensions: In VS Code, navigate to the Extensions view (Ctrl+Shift+X or Cmd+Shift+X).
Search and Install: Search for “GitHub Copilot” and “GitHub Copilot Chat” and install both extensions.
Authentication: Follow the prompts to sign in with your GitHub account and activate your Copilot subscription.
GitHub Copilot is an AI-powered code assistant that acts almost like an AI pair programmer.
After successful installation and Authentication, you see something like below
3. Installing the Playwright MCP Server (The Browser Tool)
Playwright MCP (Model Context Protocol): This is the bridge that provides browser automation capabilities, enabling the AI to interact with the web page.
The most direct way to install the server and configure the agent is via the official GitHub page:
Navigate to the Source: Open your browser and search for the Playwright MCP Server official GitHub page (https://github.com/microsoft/playwright-mcp).
The One-Click Install: On the GitHub page, look for the Install Server VSCode button.
Launch VS Code: Clicking this button will prompt you to open Visual Studio Code.
Final Step: Inside VS Code, select the “Install server” option from the prompt to automatically add the MCP entry to your settings.
To verify successful installation and configuration, follow these steps:
Click on “Configure Tool” icon
After clicking on the “configure tool “ icon, you see the tools of Playwright MCP as shown in the below image.
After clicking on the “Settings” icon, you see the “Configuration (JSON)” file of Playwright MCP, where you start, stop, and restart the server as shown in image below
After the Playwright MCP Server is successfully configured and installed, you will see the output as shown below.
2. Stop and Restart Server
This complete setup allows the Playwright MCP Server to act as the bridge, providing browser automation capabilities and enabling the GitHub Copilot Agent to interact with the web page using natural language.
Section 2: Phase 1: Intelligent Exploration and Reporting
The first, most crucial step is to let the AI agent, powered by the Playwright MCP, perform the exploratory testing and generate the foundational report. This immediately reduces the tester’s documentation effort.
Instead of manually performing steps, you simply give the AI Agent your test objective in natural language.
The Exploration Workflow:
Exploration Execution: The AI uses discrete Playwright MCP tools (like browser_navigate, browser_fill, and browser_click) to perform each action in a real browser session.
Report Generation: Immediately following execution, the AI generates an Exploratory Testing Report. This report is generated on the basis of the exploration, summarizing the detailed steps taken, observations, and any issues found.
Our focus is simple: Using Playwright MCP, we reduce the repetitive tasks of a Manual Tester by automating the recording and execution of manual steps.
Execution Showcase: Exploration to Report
Input (The Prompt File for Exploration)
This prompt directs the AI to execute the manual steps and generate the initial report.
Prompt for Exploratory Testing
Exploratory Testing: (Use Playwright MCP)
Navigate to https://www.demoblaze.com/. Use Playwright MCP Compulsory for Exploring the Module <Module Name> and generate the Exploratory Testing Report in a .md file in the Manual Testing/Documentation Directory.
Output (The Generated Exploration Report) The AI generates a structured report summarizing the execution.
Live Browser Snapshot from Playwright MCP Execution
Once the initial Exploration Report is generated, QA teams move to design specific, reusable assets based on these findings.
1. Test Case Design (on basis of Exploration Report)
The Exploration Report provides the evidence needed to design formal Test Cases. The report’s observations are used to create the Expected Results column in your CSV or Test Management Tool.
The focus is now on designing reusable test cases, which can be stored in a CSV format.
These manually designed test cases form the core of your execution plan.
We need to provide the Exploratory Report for References at the time of design test Cases.
Drag and drop the Exploratory Report File as context as shown in the image below.
Input (Targeted Execution Prompt)
This prompt instructs the AI to perform a single, critical verification action from your Test Case.
Role: Act as a QA Engineer.
Based on Exploratory report Generate the Test cases in below of Format of Test Case Design Template
=======================================
🧪 TEST CASE DESIGN TEMPLATE For CSV File
=======================================
Test Case ID – Unique identifier for the test case (e.g., TC_001)
Test Case Title / Name – Short descriptive name of what is being tested
Preconditions / Setup – Any conditions that must be met before test execution
Test Data – Input values or data required for the test
Test Steps – Detailed step-by-step instructions on how to perform the test
Expected Result – What should happen after executing the steps
Actual Result – What happened (filled after execution)
Status – Pass / Fail / Blocked (result of the execution)
Priority – Importance of the test case (High / Medium / Low)
Severity – Impact level if the test fails (Critical / Major / Minor)
Test Type – (Optional) e.g., Functional, UI, Negative, Regression, etc.
Execution Date – (Optional) When the test was executed
Executed By – (Optional) Name of the tester
Remarks / Comments – Any additional information, observations, or bugs found
Output (The Generated Test cases)
The AI generates structured test cases.
2. Test Plan Creation
The created test cases are organized into a formal Test Plan document, detailing the scope, environment, and execution schedule.
Input (Targeted Execution Prompt)
This prompt instructs the AI to perform a single, critical verification action from your Test Case. 2
Role: Act as a QA Engineer. - Use clear, professional language. - Include examples where relevant. - Keep the structure organized for documentation. - Format can be plain text or Markdown. - Assume the project is a web application with multiple modules. generate Test Cases in Form Of <Module Name >.txt in Manual Testing/Documentation Directory Instructions for AI: - Generate a complete Test Plan for a software project For Our Test Cases - Include the following sections: 1. Test Plan ID 2. Project Name 3. Module/Feature Overview 4. Test Plan Description 5. Test Strategy (Manual, Automation, Tools) 6. Test Objectives 7. Test Deliverables 8. Testing Schedule / Milestones 9. Test Environment 10. Roles & Responsibilities 11. Risk & Mitigation 12. Entry and Exit Criteria 13. Test Case Design Approach 14. Metrics / Reporting 15. Approvals
Output (The Generated Test plan)
The AI generates structured test plan of designed test cases.
3. Test Cases Execution
This is where the Playwright MCP delivers the most power: executing the formal test cases designed in the previous step.
Instead of manually clicking through the steps defined in the Test Plan, the tester uses the AI agent to execute the written test case (e.g., loaded from the CSV) in the browser.
The Playwright MCP ensures the execution of those test cases is fast, documented, and accurate.
Any failures lead to immediate artifact generation (e.g., defect reports).
Input (Targeted Execution Prompt)
This prompt instructs the AI to perform a single, critical verification action from your Test Case.
Use Playwright MCP to Navigate “https://www.demoblaze.com/” and Execute Test Cases attached in context and Generate Test Execution Report.
First, Drag and drop the test case file for references as shown in the image below.
Live Browser Snapshot from Playwright MCP Execution
Output (The Generated Test Execution report)
The AI generates structured test execution report of designed test cases.
4. Defect Reporting and Tracking
If a Test Case execution fails, the tester immediately leverages the AI Agent and Playwright MCP to generate a detailed defect report, which is a key task in manual testing.
Execution Showcase: Formal Test Case Run (with Defect Reporting)
We will now execute a Test Case step, intentionally simulating a failure to demonstrate the automated defect reporting capability.
Input (Targeted Execution Prompt for Failure)
This prompt asks the AI to execute a check and explicitly requests a defect report and a screenshot if the assertion fails.
Refer to the test cases provided in the Context and Use Playwright MCP to execute the test, and if there is any defect, then generate a detailed defect Report. Additionally, I would like a screenshot of the defect for evidence.
Output (The Generated Defect report and Screenshots as Evidence)
The AI generates a structured defect report of designed test cases.
Conclusion: Your Role is Evolving, Not Ending
Manual Testing with Playwright MCP is not about replacing the manual tester; it’s about augmenting their capabilities. It enables a smooth, documented, and low-code way to perform high-quality exploratory testing with automated execution.
Focus on Logic: Spend less time on repetitive clicks and more time on complex scenario design.
Execute Instantly: Use natural language prompts to execute tests in the browser.
Generate Instant Reports: Create structured exploratory test reports from your execution sessions.
Future-Proof Your Skills: Learn to transition seamlessly to an AI-augmented testing workflow.
It’s time to move beyond the traditional—set up your Playwright MCP today and start testing with the power of an AI-pair tester!
Automation always comes with surprises. Recently, I stumbled upon one such challenge while working on a scenario that required automating PDF download using Playwright to verify a PDF download functionality. Sounds straightforward, right? At first, I thought so too. But the web application I was dealing with had other plans.
The Unexpected Complexity
Instead of a simple file download, the application displayed the report PDF inside an iframe. Looking deeper, I noticed a blob source associated with the PDF. Initially, it felt promising—maybe I could just fetch the blob and save it. But soon, I realized the blob didn’t actually contain the full PDF file. It only represented the layout instructions, not the content itself.
Things got more interesting (and complicated) when I found out that the entire PDF was rendered inside a canvas. The content wasn’t static—it was dynamically displayed page by page. This meant I couldn’t directly extract or save the file from the DOM.
At this point, downloading the PDF programmatically felt like chasing shadows.
The Print Button Dilemma
To make matters trickier, the only straightforward option available on the page was the print button. Clicking it triggered the system’s file explorer dialog, asking me to manually pick a save location. While that works fine for an end-user, for automation purposes it was a dealbreaker.
I didn’t want my automation scripts to depend on manual interaction. The whole point of this exercise was to make the process seamless and repeatable.
Digging Deeper: A Breakthrough
After exploring multiple dead ends, I finally turned my focus back to Playwright itself. That’s when I discovered something powerful—Playwright’s built-in capability to generate PDFs directly from a page.
The key was:
Wait for the report to open in a new tab (triggered by the app after selecting “Print View”).
Bring this new page into focus and make sure all content was fully rendered.
Use Playwright’s page.pdf() function to export the page as a properly styled PDF file.
The Solution in Action
Here’s the snippet that solved it:
// Wait for new tab to open and capture it
const [newPage] = await Promise.all([
context.waitForEvent("page"),
event.Click("(//span[text()='OK'])[1]", page), // triggers tab open
]);
global.secondPage = newPage;
await global.secondPage.bringToFront();
await global.secondPage.waitForLoadState("domcontentloaded");
// Use screen media for styling
await global.secondPage.emulateMedia({ media: "screen" });
// Path where you want the file saved
const downloadDir = path.resolve(__dirname, "..", "Downloads", "Reports");
if (!fs.existsSync(downloadDir)) fs.mkdirSync(downloadDir, { recursive: true });
const filePath = path.join(downloadDir, "report.pdf");
// Save as PDF
await global.secondPage.pdf({
path: filePath,
format: "A4",
printBackground: true,
margin: {
top: "1cm",
bottom: "1cm",
left: "1cm",
right: "1cm",
},
});
console.log(`✅ PDF saved to: ${filePath}`);
Key Highlights of the Implementation
Capturing the New Tab The Print/PDF Report option opened the report in a new browser tab. Instead of losing control, we captured it with context.waitForEvent(“page”) and stored it in a global variable global.secondPage. This ensured smooth access to the report tab for further processing.
Switching to Print View The dropdown option was switched to Print View to ensure the PDF was generated in the correct layout before proceeding with export.
Emulating Screen Media To preserve the on-screen styling (instead of print-only styles), we used page.emulateMedia({ media: “screen” }). This allowed the generated PDF to look exactly like what users see in the browser.
Saving the PDF to a Custom Path A custom folder structure was created dynamically using Node.js path and fs modules. The PDFs were named systematically and stored under Downloads/ImageTrend/<date>/, ensuring organized storage.
Full-Page Export with Print Background Using Playwright’s page.pdf() method, we captured all pages of the report (not just the visible one), along with background colors and styles for accurate representation.
Clean Tab Management Once the PDF was saved, the secondary tab (global.secondPage) was closed, bringing the focus back to the original tab for processing the next incident report.
What I Learned
This challenge taught me something new: PDFs in web apps aren’t always what they seem. Sometimes they’re iframes, sometimes blob objects, and in trickier cases, dynamically rendered canvases. Trying to grab the raw file won’t always work.
But with Playwright, there’s a smarter way. By leveraging its ability to generate PDFs from a live-rendered page, I was able to bypass the iframe/blob/canvas complexity entirely and produce consistent, high-quality PDF files.
Conclusion:
What started as a simple “verify PDF download” task quickly turned into a tricky puzzle of iframes, blobs, and canvases. But the solution I found—automating PDF download using Playwright with its built-in PDF generation—was not just a fix, it was an eye-opener.
It reminded me once again that automation isn’t just about tools; it’s about understanding the problem deeply and then letting the tools do what they do best.
This was something new I learned, and I wanted to share it with all of you. Hopefully, it helps the next time you face a similar challenge.
Python for Test Automation: Best Libraries and Frameworks. Indeed, automated testing is at the heart of modern software development, ensuring reliability, rapid delivery, and continuous improvement. Moreover, Python shines in this landscape, offering a mature ecosystem, ease of use, and tools that cater to every type of testing, from back-end APIs to eye-catching web UIs. Let’s dig deeper into the leading Python solutions for test automation, with code snippets and extra insights.
Specifically, Pytest is an open-source framework known for its elegant syntax, allowing developers to write tests using plain Python assert statements, and for its extensible design that accommodates unit, integration, and even complex functional test suites. Its fixture system allows reusable setup and teardown logic, making your tests both DRY (Don’t Repeat Yourself) and powerful. Additionally, a vast ecosystem of plugins supports reporting, parallelization, coverage, mocking, and more.
How it helps:
Plain assert syntax: Write readable tests without specialized assertions.
Powerful fixtures system: Enables reusable setup/teardown logic and dependency injection.
Parameterization: Run the same test with multiple inputs easily.
Plugin ecosystem: Extends capabilities (parallel runs, HTML reporting, mocking, etc.).
Auto test discovery: Finds tests in files and folders automatically.
What makes it useful:
Extremely easy for beginners, yet scalable for large and complex projects.
Fast feedback and parallel test execution.
Integrates well with CI/CD pipelines and popular Python libraries.
Large, active community and abundant documentation.
Meanwhile, Unittest, or PyUnit, is Python’s default, xUnit-inspired testing framework. It leverages class-based test suites and is included with Python by default, so there’s no installation overhead. Specifically, its structure—using setUp() and tearDown() methods—supports organized, reusable testing flows ideal for legacy systems or developers experienced with similar frameworks like JUnit.
How it helps:
Standard library: Ships with Python, zero installation required.
Class-based organization: Supports test grouping and reusability via inheritance.
Flexible test runners: Customizable, can generate XML results for CI.
Rich assertion set: Provides detailed validation of test outputs.
What makes it useful:
Good fit for legacy code or existing xUnit users.
Built-in and stable, making it ideal for long-term projects.
Well-structured testing process with setup/teardown methods.
Easy integration with other Python tools and editors.
import unittest
def add(a, b):
return a + b
class TestCalc(unittest.TestCase):
def setUp(self):
# Code to set up preconditions, if any
pass
def test_add(self):
self.assertEqual(add(2, 3), 5)
def tearDown(self):
# Cleanup code, if any
pass
if __name__ == '__main__':
unittest.main()
3. Selenium – World’s top Browser Automation tool
What it solves:
Selenium automates real browsers (Chrome, Firefox, Safari, and more); moreover, from Python, it simulates everything a user might do—clicks, form inputs, navigation, and more. Indeed, this framework is essential for end-to-end UI automation and cross-browser testing, and it integrates easily with Pytest or Unittest for reporting and assertions. Pair it with cloud services (such as Selenium Grid or BrowserStack) for distributed, real-device testing at scale.
How it helps:
Cross-browser automation: Supports Chrome, Firefox, Safari, Edge, etc.
WebDriver API: Simulates user interactions as in real browsers.
End-to-end testing: Validates application workflows and user experience.
Selectors and waits: Robust element selection and waiting strategies.
What makes it useful:
De facto standard for browser/UI automation.
Integrates with Pytest/Unittest for assertions and reporting.
Supports distributed/cloud/grid testing for broad coverage.
Community support and compatibility with cloud tools (e.g., BrowserStack).
4. Behave – Behavior-Driven Development (BDD) Framework
What it solves:
Behave lets you express test specs in Gherkin (Given-When-Then syntax), bridging the gap between technical and non-technical stakeholders. Ultimately, this encourages better collaboration and living documentation. Moreover, Behave is ideal for product-driven development and client-facing feature verification, as test cases are easy to read and validate against business rules.
How it helps:
Gherkin syntax: Uses Given/When/Then statements for business-readable scenarios.
Separation of concerns: Business rules (features) and code (steps) remain synced.
Feature files: Serve as living documentation and acceptance criteria.
What makes it useful:
Promotes collaboration between dev, QA, and business stakeholders.
Easy for non-coders and clients to understand and refine test cases.
Keeps requirements and test automation in sync—efficient for agile teams.
Feature: Addition
Scenario: Add two numbers
Given I have numbers 2 and 3
When I add them
Then the result should be 5
Step Definition
from behave import given, when, then
@given('I have numbers {a:d} and {b:d}')
def step_given_numbers(context, a, b):
context.a = a
context.b = b
@when('I add them')
def step_when_add(context):
context.result = context.a + context.b
@then('the result should be {expected:d}')
def step_then_result(context, expected):
assert context.result == expected
5. Robot Framework – Keyword-Driven and Extensible
What it solves:
Similarly, Robot Framework uses simple, human-readable, keyword-driven syntax to create test cases. Furthermore, it’s highly extensible, with libraries for web (SeleniumLibrary), API, database, and more, plus robust reporting and log generation. In particular, Robot is perfect for acceptance testing, RPA (Robotic Process Automation), and scenarios where non-developers need to write or understand tests.
How it helps:
Keyword-driven: Tests written in tabular English syntax, easy for non-coders.
*** Settings ***
Library SeleniumLibrary
*** Test Cases ***
Open Google And Check Title
Open Browser https://www.google.com Chrome
Title Should Be Google
Close Browser
6. Requests – HTTP for Humans
What it solves:
Python’s requests library is a developer-friendly HTTP client for RESTful APIs, and when you combine it with Pytest’s structure, you get a powerful and expressive way to test every aspect of an API: endpoints, status codes, headers, and response payloads. This pair is beloved for automated regression suites and contract testing.
How it helps:
Clean HTTP API: Requests library makes REST calls intuitive and readable.
Combine with Pytest: Gets structure, assertions, fixtures, and reporting.
Easy mocking and parameterization: Fast feedback for API contract/regression tests.
What makes it useful:
Rapid API test development and high maintainability.
Efficient CI integration for validating code changes.
Very flexible—supports HTTP, HTTPS, form data, authentication, etc.
Specifically, Locust is a modern load-testing framework that allows you to define user behavior in pure Python. Moreover, it excels at simulating high-traffic scenarios, monitoring system performance, and visualizing results in real time. Consequently, its intuitive web UI and flexibility make it the go-to tool for stress, spike, and endurance testing APIs or backend services.
How it helps:
Python-based user flows: Simulate realistic load scenarios as Python code.
Web interface: Live, interactive test results with metrics and graphs.
Distributed architecture: Scalable to millions of concurrent users.
What makes it useful:
Defines custom user behavior for sophisticated performance testing.
Real-time monitoring and visualization.
Lightweight, scriptable, and easy to integrate in CI pipelines.
from locust import HttpUser, task, between
class WebsiteUser(HttpUser):
wait_time = between(1, 3)
@task
def load_main(self):
self.client.get("/")
@task
def load_about(self):
self.client.get("/about")
@task
def load_contact(self):
self.client.get("/contact")
8. Allure and HTMLTestRunner – Reporting Tools
What it solves:
Visual reports are essential to communicate test results effectively. Notably, Allure generates clean, interactive HTML reports with test status, logs, screengrabs, and execution timelines—welcomed by QA leads and management alike. Similarly, HTMLTestRunner produces classic HTML summaries for unittest runs, showing pass/fail totals, stack traces, and detailed logs. These tools greatly improve visibility and debugging.
9. Playwright for Python – Modern Browser Automation
What it solves:
Playwright is a relatively new but powerful framework for fast, reliable web automation. It supports multi-browser, multi-context testing, handles advanced scenarios like network mocking and file uploads, and offers built-in parallelism for rapid test runs. Its robust architecture and first-class Python API make it a preferred choice for UI regression, cross-browser validation, and visual verification in modern web apps.
How it helps:
Multi-browser/multi-context: Automates Chromium, Firefox, and WebKit with a single API.
Auto-waiting and fast execution: Eliminates common flakiness in web UI tests.
from playwright.sync_api import sync_playwright
def test_example():
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com")
assert page.title() == "Example Domain"
browser.close()
Summary Table of Unique Features and Advantages
Every framework has a unique fit—pair them based on your team’s needs, tech stack, and test goals! Python libraries and frameworks for test automation.
Frameworks
Unique Features
Advantages
Pytest
Fixtures, plugins, assert syntax, auto discovery
Scalable, beginner-friendly, fast, CI/CD ready
Unittest
Std. library, class structure, flexible runner
Stable, built-in, structured
Selenium
Cross-browser UI/WebDriver, selectors, waits
UI/E2E leader, flexible, cloud/grid compatible
Behave
Gherkin/business syntax, feature/step separation
BDD, collaboration, readable, requirement sync
Robot Framework
Keyword-driven, extensible, RPA, reporting
Low code, reusable, logs, test visibility
Request
Simple API calls, strong assertions, fast feedback
Rapid API testing, CI ready, flexible
Locust
Python load flows, real-time web UI, scalable
Powerful perf/load, code-defined scenarios
Allure
Interactive HTML reports, attachments, logs
Stakeholder visibility, better debugging
Playwright
Multi-browser, auto-waiting, advanced scripting
Modern, fast, reliable, JS-app friendly
Conclusion
Python for Test Automation: Each of these frameworks has a unique niche, whether it’s speed, readability, extensibility, collaboration, or robustness. When selecting tools, consider your team’s familiarity, application complexity, and reporting/auditing needs—the Python ecosystem will almost always have a perfect fit for your automation challenge.
Indeed, the Python ecosystem boasts tools for every test automation challenge. Whether you’re creating simple smoke tests or orchestrating enterprise-grade BDD suites, there’s a Python library or framework ready to accelerate your journey. In fact, for every domain—unit, API, UI, performance, or DevOps pipeline, Python keeps testing robust, maintainable, and expressive.
I’m Sr. Digital Marketing Executive with a strong interest in content strategy, SEO, and social media marketing. She is passionate about building brand presence through creative and analytical approaches. In her free time, she enjoys learning new digital trends and exploring innovative marketing tools.
Pytest Vs Unittest: Testing forms the backbone of reliable software development, and in Python, two major frameworks stand out to get the job done: Unittest and Pytest. While both aim to ensure code correctness, maintainability, and robustness, they take very different approaches. Moreover, Python includes Unittest as a built-in framework, offering a familiar class-based testing style without requiring extra dependencies. Pytest, on the other hand, is a modern, feature-rich alternative that emphasizes simplicity, readability, and powerful capabilities like parametrization and fixtures.
In this blog, we’ll break down the key differences, advantages, and practical examples of both frameworks—helping you decide when to stick with the reliability of Unittest and when to embrace the flexibility of Pytest for your projects. Let’s see the Pytest vs Unittest: Which Python Testing Framework to Choose?
Step 1: Understanding the Fundamentals of Pytest Vs Unittest
What is Unittest?
Unittest comes bundled with Python as part of its standard library. Therefore, it ensures immediate availability and compatibility across different environments without requiring extra dependencies. Moreover, the seamless integration across environments makes Unittest convenient to use without the need for additional packages. To begin with, unit testing represents the first level of software testing, where testers examine the smallest parts of a program to ensure each unit functions as designed.
Example:
import unittest
class SimpleTest(unittest.TestCase):
def test_example(self):
self.assertTrue(True)
if __name__ == '__main__':
unittest.main()
For example, this is the basic test code using the Unittest framework, which contains a single test. This test() method will fail if True is ever false.
Output:
OOps concepts supported by unittest framework:
Text Fixture: A test fixture provides a baseline for running the tests. It basically provides the prerequisites needed for executing one or more tests and any clean up or temporary database generation running the process with all these functionality handled by text fixture.
Test Case: A set of cases defines the conditions that determine whether a system under test works correctly. It is a collection of unit tests
Test Suite: In addition, a test suite is a collection of test cases used to verify that a software program exhibits a specified set of behaviors by executing the aggregated tests together.
Test Runner: Similarly, a test runner is a component that sets up the execution of tests and provides the outcomes to the user. Furthermore, the runner may use a graphical interface, a text-based interface, or return a special value to indicate the results of executing tests.
Sample example of Unit test fixture:
import unittest
class SimpleTest(unittest.TestCase):
def setUp(self):
# This is the fixture. Runs before every test.
self.data = [1, 2, 3]
def tearDown(self):
# Clean up here (optional). Runs after every test.
self.data = None
def test_sum(self):
self.assertEqual(sum(self.data), 6)
def test_max(self):
self.assertEqual(max(self.data), 3)
if __name__ == '__main__':
unittest.main()
What is Pytest?
Overall, Pytest is a robust testing framework for Python that makes it easier to write simple and scalable test cases. In fact, Pytest’s simple syntax lets developers get started quickly with minimal boilerplate code. In addition, it supports fixtures, parametrization, and numerous plugins, making it a versatile and powerful tool for writing and organizing test cases.
Example:
import pytest
@pytest.mark.smoke
def test_function_one():
print('inside test function test_function_one')
num = 10
assert num !=12
Output:
Pytest Text Fixture:
Here’s a list of some of the most popular pytest fixtures you’ll often see used:
tmp_path / tmpdir: Provides a temporary directory unique to the test run.
monkeypatch: Allows you to modify or “patch” functions or environment variables for the duration of a test.
capfd / capsys: Captures output to file descriptors/stdout/stderr.
request: Gives access to the test context for parametrization, data, etc.
db (often custom): Sets up and tears down a database connection.
client: Creates a test client for web applications.
autouse fixtures: Moreover, Pytest automatically applies fixtures without requiring you to declare them in a test function.
parametrized fixtures: Moreover, you can deliver different values to tests using the same fixture code, enabling you to run tests against multiple inputs.
Step 3: Writing tests(Automation using Pytest Vs Unittest)
Writing tests using unittest
To begin with, create a project and add a Python package named business_logic. Inside this package, create two Python files: calculator.py and login.py.
Login.py:
USER = "Admin"
PASS = "Admin123"
def authenticate_user(username,password):
if username:
if password:
if USER==USER and PASS==password:
return 'Login Successful'
else:
return 'Invalid Credentials'
else:
return 'Password Cannot Be Empty...'
else:
return 'Username cannot be Empty...'
For example, the above simple code authenticates the user with a valid username and password. If the entered credentials match the predefined ‘Admin’ and ‘Pass’, the user successfully logs in to the application. If it’s not matching the criteria it will give a warning message popup.
Calculator.py:
def addition(n1,n2):
if type(n1) in [int,float,complex] and type(n2) in [int,float,complex]:
if n1<=0 or n2<=0:
return 'Number shud be greater than zero'
return n1+n2
else:
return 'Invalid Input'
In above code a simple calculator method is used for calculator additional functionality where n1 and n2 are could be [int,float,complex] if n1 or n2 are <=0 it will return warning popup message ‘Number shud be greater than zero’ and when n1 or n2>0 it will return addition of n1 and n2 else it will give warning popup message as ‘Invalid Input’.
Test_login_scenario.py:
import unittest
from business_logic.login import authenticate_user
class TestLogin(unittest.TestCase):
def test_valid_username_and_password(self):
if (authenticate_user('user0','pass0'))==True:
return True
print('inside test_valid_username_and_password')
def test_invalid_username_and_password(self):
print('Inside test_invalid_username_and_password')
self.assertEqual(10,20)
For instance, the above unit test verifies the login functionality for both positive and negative scenarios using Python’s built-in library.
Writing tests using pytest
from business_logic.calculator import addition
import pytest
import threading
@pytest.mark.parametrize("n1,n2,expected_result",[
(10,20,30),
(10,"A","Invalid Input"),
(0, "A", "Invalid Input"),
(0,10, "Number shud be greater than zero"),
(0,0,"Number shud be greater than zero"),
(10,-2,"Number shud be greater than zero"),
(2,4,6)
])
def test_calculator(n1,n2,expected_result):
print(n1,n2,expected_result)
result = addition(n1,n2)
assert result == expected_result
Similarly, in the above code, we have used Pytest parameterization to test the calculator’s addition functionality with the Pytest library.
Step 4: Run code through Command line
Unittest important commands:
Python -m unittest —> This is use to search entire test cases Example – python -m unittest tests.module.testclass
Python -m unittest -v test_module —> Here -v is used for more details
Python -m unittest -h —> -h is used for all command line help options
-f —> -f is used to stop the test run on the first error or failure
-k —> It is use to run the test methods and classes that matches the pattern or substring
Pytest important commands:
Pytest test_module() —> This is used to run tests in module
Pytest tests/ —> This is used to run tests in directory
f – failed
E – error
s – skipped
x – xfailed
X – xpassed
p – passed
P – passed with output
Step 5: Advantages of using Pytest and Unittest
Advanced Features of Unittest
Test discovery: Automatically finds and runs tests.
Test suites: Group multiple tests together.
Mocking capabilities: Use unittest.mock for mocking objects.
Advanced Features of Pytest
Parametrization: Easily run a test with multiple sets of parameters.
Plugins: A rich ecosystem of plugins to extend functionality.
Step 6: Key comparison between unittest and pytest
Aspect
Unittest
Pytest
Included with Python
Yes (Standard Libraries)
No (third-party package, install needed)
Syntax
More verbose, class-based
Simple, concise, function-based
Test Discovery
Requires strict naming and class structure
Automatic, flexible
Fixtures
Limited to setUp/tearDown methods
Powerful, modular fixtures with scopes
Parameterization
No built-in support (needs custom handling)
Built-in @pytest.mark.parametrize
Assertions
Assertion methods (e.g., assertEqual)
Plain assert with detailed introspection
Plugins
Few, limited support
Large rich ecosystem
Test Execution Speed
Sequential by default
Supports parallel execution
Mocking
Uses unittest.mock
Compatible with unittest.mock and plugins
Learning Curve
Easier for beginners
Moderate due to more features
Community
Standard library with stable adoption
Large and active community
Conclusion
Both Unittest and Pytest help you write reliable, maintainable tests—but they serve different needs. On the other hand, Unittest is lightweight, built-in, and well-suited for straightforward or legacy projects. In contrast, Pytest is modern, concise, and equipped with powerful features like fixtures, plugins, and parametrization—making it ideal for larger or more complex testing needs.
If you want simplicity with no extra setup, go with Unittest. If you want flexibility, readability, and speed, choose Pytest.
Jyotsna is a Jr SDET which have expertise in manual and automation testing for web and mobile both. She has worked on Python, Selenium, Mysql, BDD, Git, HTML & CSS. She loves to explore new technologies and products which put impact on future technologies.
As virtual reality (VR) continues to make waves in industries like gaming, education, and healthcare, ensuring a seamless and safe user experience through VR testing best practices has become more important than ever. Unlike traditional applications, VR completely immerses users in a 3D environment – which means even small bugs or design flaws can lead to more than just confusion. They can cause dizziness, nausea, or even physical discomfort.
That’s why VR testing is such a critical step in the development process. In this blog, I’ll break down what makes VR testing unique, the common challenges developers face, and some best practices that can help ensure a smooth and comfortable experience for users.
How VR Testing Stands Apart
Testing a regular mobile or web app usually means checking things like buttons, workflows, performance across browsers, etc. But in VR, the scope widens dramatically.
Here, testers must consider:
3D spatial interaction
User immersion in a virtual world
Motion tracking and input gestures
Physical safety and comfort during usage
It’s not just about asking “Does it work?” – but also “Does it feel natural?” and “Is it comfortable for extended use?”
Types of VR Testing
Different testing approaches help cover the full VR experience:
Functional Testing – Do interactions like grabbing, teleporting, or selecting objects work?
Usability Testing – Is the experience intuitive and easy to navigate?
Immersion Testing – Can users stay engaged without feeling disconnected or interrupted?
Performance Testing – Are frame rates stable and latency low?
Comfort/Safety Testing – Are users feeling discomfort, dizziness, or motion sickness?
Challenges That Come with VR Testing
Testing VR comes with its own unique set of hurdles:
Motion Sickness(VR Sickness) – Often caused when visual and physical cues don’t match.
Device Fragmentation – Each headset has its own resolution, controller, and tracking system.
Limited Automation – Unlike traditional UI, many aspects, like user comfort, need manual observation.
Environmental Factors – Lighting, room size, and even how much someone moves around can affect usability.
3D UI Testing – Ensuring buttons or menus are correctly placed and easy to reach in 3D space can be tricky.
Best Practices for Smoother VR Testing
To deliver a reliable and user-friendly VR experience, here are a few best practices to follow while testing VR applications:
Use Teleportation Instead of Smooth Movement Continuous walking can cause nausea; teleportation helps reduce that. Teleportation refers to a locomotion technique that allows a user to instantly move from one point in the virtual environment to another, without having to physically “walk” through the virtual space.
Maintain a High Frame Rate (90+ FPS) The smoother the frame rate, the lower the chances of motion sickness. Hence, we have to test on lower frame rates to check whether the app works correctly.
Snap Turns Over Smooth Turns Fixed-angle turns are less likely to cause dizziness than gradual spins. While testing VR apps, try to test both fixed-angle turns and gradual spins to experience and test such gestures.
Test with Real Users Observe natural user behavior and gather feedback using tools like the Simulator Sickness Questionnaire. Real users typically give us feedback about what gestures worked well and how their experience was.
Test Across Multiple Headsets Make sure the experience feels consistent regardless of the device. Devices like Apple Vision Pro, Oculus, SteamVR, Hand TC Vive Pro 2 can help find the errors and experience problems and fix them before users see them in a live environment.
Add Visual Anchors Integrate fixed visual reference points—such as a virtual nose, cockpit, dashboard, or HUD—that remain steady as the user moves through the VR environment. These visual anchors help users’ brains reconcile virtual movement with their physical balance system, drastically reducing sensory conflict and motion-related discomfort.
Developer’s Perspective: Real-World Insights on VR Testing
Here are a few key takeaways straight from developers working on real VR projects:
Cross-Device Compatibility “We build using cross-platform engines like Unity or Unreal, optimize performance for each device, test on real hardware, and adjust input systems to match each headset’s controllers.”
Tools & Frameworks “We use Unity Profiler, Unreal Insights, XR Plugin Management, Oculus/SteamVR dev tools, and sometimes third-party tools like GPU Profiler or Frame Debugger.”
Design for Comfort “We use teleportation or smooth locomotion with comfort settings, maintain stable frame rates, keep camera movement gentle, and avoid sudden jerks or flashes. We also design at a real-world scale and respect personal space.”
Common Bug Types “Common bugs include controller input issues, tracking glitches, poor frame rates, UI not showing properly in 3D space, and interaction not working correctly on some devices.”
User Data vs Feedback “Mostly user feedback and playtesting, but when available, we also use data like eye tracking or heat maps to improve design and comfort.”
Motion Sickness Testing “We test with different users, observe their reactions, ask for direct feedback, and follow VR comfort guidelines – like keeping high frame rates and avoiding fast camera movement.”
The Hardest Part “The hardest part is testing many headsets with different specs. We tackle it by testing early and often, optimizing for the lowest-end device first, and using a modular, flexible design.”
A Quick Case Study: Teleportation Saves the Day
One VR meditation app originally used joystick-based free movement. But testers quickly complained about nausea. The team switched to teleportation – allowing users to “jump” between spots instead.
The result? Comfort levels rose dramatically, and user satisfaction improved as a result.
Conclusion: Why VR Testing Is a Must
Virtual reality opens doors to amazing experiences. But with that immersion comes greater responsibility – especially around performance, usability, and physical comfort.
A poorly tested VR experience isn’t just frustrating; it can make users feel sick. On the other hand, a well-tested, thoughtful VR app can be immersive, delightful, and safe.
To sum it up, focus on:
Functionality
Frame rate and performance
Comfort and safety
And you’ll be well on your way to delivering a VR experience people will want to return to.
Whether you’re a developer, tester, or product owner, mastering VR testing isn’t just good practice – it’s essential for building impactful, accessible, and safe virtual experiences.
Quality-focused tester with 2–3 years of experience in ETL, manual testing, and basic automation. Proficient in identifying bugs, designing and executing functional, regression, and UI tests, and reporting issues using tools like JIRA and managing documentation through platforms like SharePoint. Familiar with basic API testing using Postman and skilled in SQL. Experienced in working across financial and life sciences domains. Known for clear documentation, collaborative team efforts, and a strong focus on delivering high-quality software.
Can AI Fully Replace Human Testers? In today’s world, Artificial Intelligence (AI) is revolutionizing industries by automating tasks, enhancing decision-making, and improving efficiency.
Automates Repetitive Tasks – Reduces manual effort in test case creation, execution and maintenance.
Enhances Accuracy – Minimizes human errors in test execution and defect detection.
Self-Healing Test Scripts – Adapts test cases to UI and code changes automatically.
Defect Prediction – Analyzes historical data to identify potential failures early.
Optimizes Test Coverage – Uses machine learning to prioritize critical test scenarios.
Accelerates Testing Process – Reduces test cycle time for faster software releases.
So, Can AI Fully Replace Human Testers?
The rise of AI in software testing has sparked a debate on whether it can completely replace human testers. Though there are many benefits of using AI to enhance and expedite testing but still there are some limitations as well due to which AI cannot fully replace human testers and human testers remain crucial for ensuring software quality, creativity, and decision-making.
So let’s highlight on some important reasons why AI can’t fully replace Software Testers
1. Limitations of AI in Understanding Business Logic
AI follows predefined rules but lacks deep understanding of business-specific requirements and exceptions.
Human testers can interpret complex workflows, industry regulations, and real-world scenarios that AI may overlook.
Example:
In a payroll software, AI can verify that salary calculations follow predefined formulas. However, it may fail to detect a business rule that states bonuses should not be taxed for employees in a specific region.
A human tester, understanding the business logic, would catch this error and ensure the software correctly follows company policies and legal requirements.
2. The Need for Exploratory and Ad Hoc Testing
AI follows predefined test cases and patterns but cannot explore software unpredictably like human testers.
Humans think outside the box and use intuition and creativity to find hidden bugs that scripted tests would miss.
Example:
In a travel booking app, AI tests standard workflows like selecting a destination and making a payment.
A human tester, however, might enter an invalid date (e.g., 30 February) or try booking a past flight, uncovering edge cases that AI would overlook.
This unscripted testing could reveal unexpected issues like duplicate transactions or system crashes. These problems AI wouldn’t detect because they fall outside predefined test patterns.
3. AI Relies on Data—But Data Can Be Biased
AI relies on historical data, and if the data is biased or incomplete, test scenarios may miss critical edge cases.
Human testers can recognize gaps in data and create diverse test cases to ensure fair and accurate software testing.
Example:
In an insurance claims system, AI trained on past claims may overlook new fraud detection patterns. A human tester, aware of emerging fraud techniques, can design better test cases for such scenarios.
4. Ethical and Security Considerations
AI can detect common security threats but lacks the intuition to identify hidden vulnerabilities and ethical risks.
Human testers assess privacy concerns, data leaks, and compliance with regulations like GDPR and HIPAA.
Example:
In a healthcare application, AI can test whether patient records are accessible and editable. However, it may not recognize that displaying full patient details to unauthorized users violates HIPAA privacy regulations.
A human tester, aware of compliance laws, would check access controls and ensure sensitive data is only visible to authorized personnel, preventing potential legal and security risks.
5. Test Strategy, Planning, and Decision-Making
AI can generate test cases, but human testers define the overall test strategy, considering business risks and priorities.
Humans assess which areas need deeper testing, while AI treats all tests equally without understanding critical business impacts.
Example:
In a banking application, AI can generate automated test cases for transactions, fund transfers, and account management. However, it cannot determine which features carry the highest risk if they fail.
A human tester uses strategic thinking to prioritize testing for critical functions, such as fraud detection and security measures, ensuring they are tested more thoroughly before release.
6. AI Lacks Creativity and User Perspective
AI follows patterns, not intuition – It cannot predict how real users will interact with software in unpredictable ways.
Human testers understand user experience, emotions, and expectations which AI cannot replicate.
Example:
In a food delivery app, AI can verify that orders are placed and delivered correctly. However, it cannot recognize if the app’s interface is confusing, such as making it hard for users to find the “Cancel Order” button or displaying unclear delivery time estimates.
A human tester, thinking from a user’s perspective, can identify these usability issues and suggest improvements to enhance the overall experience.
7. Difficulty in Understanding User Experience (UX)
AI can verify buttons, layouts, and navigation but cannot assess ease of use, user frustration, or accessibility challenges.
Human testers evaluate if an interface is intuitive, user-friendly, and meets accessibility standards for diverse users.
Example:
In a mobile banking app, AI can verify that all buttons, forms, and links are functional. However, it cannot assess whether the “Transfer Money” button is too small for users with disability or if the color contrast makes text hard to read for visually impaired users.
A human tester evaluates usability, accessibility, and overall user experience to ensure the app is easy and comfortable to use for all customers.
8. Cannot Prioritize Bugs Effectively
AI detects failures but cannot determine which bugs have the highest business impact.
Human testers prioritize critical issues, ensuring major defects are fixed before minor ones.
Example:
AI may report 100 test failures, but a human tester knows that a bug preventing users from making payments is more critical than a minor UI misalignment. Humans prioritize fixes based on business impact.
9. Collaboration and Communication in Testing
Testing involves teamwork, feedback, and communication with developers.
AI cannot replace human collaboration in Agile and DevOps environments.
Example:
In an Agile software development team working on a banking app, testers collaborate with developers to clarify requirements, discuss defects, and suggest improvements.
When a critical bug affecting loan calculations is found, a human tester explains the issue, discusses potential fixes with developers, and ensures the solution aligns with business needs. AI can detect failures but cannot engage in meaningful discussions, negotiate priorities, or contribute to brainstorming sessions like human testers do in Agile and DevOps environments.
10. Limited Adaptability to Change
AI relies on predefined models and struggles to adapt quickly to new features or design changes.
Human testers can instantly analyze and test evolving functionalities without needing retraining.
Example:
In a banking app, if a new biometric login feature is introduced, AI test scripts may fail or require retraining.
A human tester, however, can immediately test fingerprint and facial recognition, ensuring security and usability without waiting for AI updates.
11. Cross-Platform & Real-Device Testing
AI primarily tests in simulated environments, but humans validate software on real devices with varying conditions like network fluctuations and battery levels.
Human testers ensure the application functions correctly across different operating systems, screen sizes, and hardware configurations.
Example:
AI may test a mobile banking app in a controlled environment, but a human tester might check it in low-battery mode, weak network conditions, or different screen sizes to uncover real-world issues.
Conclusion:
While AI is transforming software testing by automating repetitive tasks and accelerating test execution, it cannot replicate human insight, intuition, and creativity. Testers bring critical thinking, domain understanding, ethical judgment, and the ability to evaluate user experience—areas where AI continues to fall short.
The future of software testing isn’t about choosing between AI and humans—it’s about combining their strengths. AI serves as a powerful assistant, handling routine tasks and data-driven predictions, while human testers focus on exploratory testing, strategy, risk analysis, and delivering meaningful user experiences.
As software becomes more complex and user expectations continue to rise, the role of human testers will only grow in importance. Embracing AI not as a replacement, but as a collaborative tool, is the key to building smarter, faster, and more reliable software.
Result-driven Manager – SDET with a strong focus on project management, quality delivery, and team leadership. Adept at leading QA and automation across Web, Mobile, and API platforms within Agile/DevOps frameworks. Skilled in managing cross-functional teams, optimizing project execution, and driving customer satisfaction. Experienced in stakeholder engagement, risk mitigation, and strategic resource planning. Proven success in developing scalable test strategies, integrating automation into CI/CD pipelines, and fostering continuous QA improvements.