Saturday, August 8, 2026

Playwright + TypeScript, from Zero to AI-Powered E2E Testing

Playwright with Typescript Udemy Course Overview


I just launched a new Udemy course, "Playwright with TypeScript – Automation Testing, E2E, API & AI/MCP," and I wanted to write a bit about why I built it, what's inside, and where you can grab the code that goes along with every lecture.

🚀 Enroll in the course on Udemy  |  💻 Get the companion code on GitHub

Why Playwright, and why now?

Playwright has quietly become one of the most reliable tools for end-to-end testing — fast, resilient to flakiness, and genuinely pleasant to write tests in once you get past the first few locators. But most tutorials stop at "click a button, assert some text." Real test suites need to survive real applications: dialogs, iframes, drag-and-drop, shopping carts, custom fixtures, and CI pipelines that don't fall over every time the UI shifts a pixel.

This course is built around that gap. It starts from the fundamentals and works all the way up to using AI — specifically the Playwright MCP server and Claude Code — to generate and even self-heal failing tests inside GitHub Actions.

What you'll learn

  • Writing reliable E2E tests with Playwright + TypeScript, from locators to assertions
  • Handling real-world UI patterns: checkboxes, radios, drag-and-drop, dialogs, iframes
  • Building maintainable test suites with custom fixtures and the Page Object pattern
  • Testing a full shopping cart flow end-to-end
  • Debugging with traces, the HTML reporter, and soft assertions
  • Generating and healing tests with AI, using the Playwright MCP server and Claude Code
  • Wiring up a self-healing CI workflow so failing tests fix themselves via GitHub Actions

The companion repo

Every lecture has real, working code behind it, all in one place:

github.com/naeemakram/playwright-typescript-e2e-ai

tests/
  cart/            # Full shopping cart E2E test suite
  *.spec.ts        # Section-by-section lecture exercises
specs/             # AI-generated test plans (used with the Playwright MCP planner)
.github/workflows/ # CI, including an AI-powered self-healing test workflow
playwright.config.ts  # Base URL, projects, tracing, and reporter setup
.mcp.json          # Playwright MCP server config used for AI test generation

Commits roughly track the course section-by-section, so you can check out the history and watch each feature get built incrementally rather than just staring at a finished pile of code. Clone it, follow along, and — most importantly — break things and fix them. That's still the fastest way to actually learn a testing tool.

Getting started with the code

npm install
npx playwright install
npx playwright test

And once a run finishes, open the HTML report to see exactly what happened:

npx playwright show-report

Who this is for

If you've never written an automated test before, you'll be fine — the course starts at the very beginning. If you already know Playwright but haven't touched fixtures, Page Objects, or CI, there's a lot here for you too. And if you're curious how AI tooling like MCP and Claude Code fits into a real test workflow rather than just being a novelty, the later sections are built specifically for that.

Let's go

Enroll in the course on Udemy and pair it with the GitHub repo as you go. If you find it useful, a rating or review genuinely helps other learners find it — thank you in advance! ⭐⭐⭐⭐⭐

Friday, August 7, 2026

AI Model Collapse

Machine Learning & AI

Understanding AI Model Collapse: What Happens When AI Feeds on AI?

What happens when synthetic data floods the internet, and future models train primarily on AI-generated content? Welcome to the challenge of Model Collapse.

Udemy Course: Playwright TypeScript Automation Testing


AI Model Collapse


Think of model collapse like making a photocopy of a photocopy. Each successive generation introduces minor errors, hallucinations, and bias amplifications that compound over time—until the system completely loses touch with reality.

1. The Mechanism: How Collapse Occurs

Researchers studying recursive training loops have identified two distinct stages of degradation when AI systems are trained on outputs from older AI models:

Stage 1: Early Collapse (Tail Loss)

The model begins losing its grasp on rare facts, edge cases, and nuanced details—the tails of the statistical distribution curve. While general fluency remains intact, niche expertise vanishes.

Stage 2: Late Collapse (Systemic Breakdown)

The model entirely disconnects from real-world data structures. Outputs become hyper-generic, highly repetitive, and fundamentally ungrounded from factual reality.

2. The Core Risks

Allowing model collapse to go unchecked poses significant challenges for digital ecosystems and enterprise deployments:

  • Knowledge Collapse: The AI maintains fluent, grammatically flawless syntax while becoming completely unreliable regarding facts underneath.
  • Homogenization & Loss of Diversity: Outputs lose stylistic variance and unique cultural perspectives, flattening into predictable, generic prose.
  • Bias Amplification: Systemic biases present in initial training datasets are magnified exponentially as models repeatedly digest their own assumptions.

3. Prevention & Architectural Fixes

While commercial frontier models are not in full collapse today, preventing this "hall of mirrors" outcome requires proactive system architecture:

Strategy Mechanism & Purpose
Human-in-the-Loop (HITL) Injecting high-quality, verified human-generated data to periodically recalibrate model weights and maintain baseline reality.
Retrieval-Augmented Generation (RAG) Anchoring LLM outputs against external, authoritative databases rather than relying purely on fixed internal parameter storage.
Data Provenance & Verification Implementing cryptographic tracking for original web data and deploying multi-agent verification pipelines to cross-check factual consistency.

The Long-Term Engineering Reality

Preventing model collapse isn't just an abstract data science concern—it is a fundamental software quality and data governance challenge. Keeping artificial intelligence grounded requires rigorous data pipeline management and continuous validation.

How is your engineering team auditing and verifying training data or live inputs in your AI workflows?

Saturday, August 1, 2026

The Death of Script Maintenance: Why AI-Era Engineers Write "Toilet Paper Code"

The Rise of Toilet Pager Code in AI Era

 

Udemy Course: Playwright TypeScript Automation Testing

Executive Summary: For decades, software engineering operated under a fundamental rule: Every line of code is an asset that must be maintained, architected, and checked into source control. Today, generative AI has crushed the marginal cost of code creation to zero. As a result, code is transforming from a durable asset into a single-use utility—what I call "Toilet Paper Code." Here is why this shift is happening, how to leverage it safely, and where the boundary lies between disposable utility and toxic tech debt.

The Old Paradigm: Code as a Durable Asset

Historically, writing code carried high cognitive and temporal overhead.

Even for trivial tasks—formatting a messy 50,000-row CSV file, parsing legacy test execution logs, or transforming a complex JSON payload—an engineer had to make a calculated decision: Is it worth spending 45 minutes writing and debugging a Python script to save 20 minutes of manual labor?

More often than not, the math didn't add up. When we did write those scripts, we treated them like durable assets. We created dedicated git repositories, set up virtual environments, added argparse options, handled every theoretical edge case, and wrapped them in documentation.

We were conditioned to believe that all code must be built to last.

[Traditional Mindset]
Intent ──> High Overhead ──> Architect ──> Test ──> Commit to Git ──> Long-term Maintenance

The AI Shift: The Zero-Cost Marginal Line

Generative AI inverts this dynamic completely.

When an LLM can craft a context-aware 30-line Python script or Bash pipeline in under 3 seconds, the friction between intent and execution disappears.

[AI-Era Mindset]
Intent ──> Prompt LLM ──> Execute Code in REPL/CLI ──> Consume Result ──> Discard

When code creation cost approaches zero, code itself ceases to be the product or the deliverable. It becomes a transient runtime query language—an ephemeral bridge to get from raw input to desired output.

This gives rise to Toilet Paper Code(term coined by Naeem Malik in 2026): code that is context-sensitive, hyper-specific, run once (or a few times), and immediately thrown away.

The 4 Golden Rules of Toilet Paper Code

Not all disposable code is created equal. To practice this pattern effectively without creating chaos, top-tier engineers stick to four core principles:

1. Hyper-Contextual

Toilet Paper Code solves only the specific data, schema, or system state in front of you at this exact moment. It doesn't care about backward compatibility, modularity, or parameterization.

2. Ephemeral Execution

It lives in temporary buffers—an interactive Python REPL, a throwaway terminal tab, or a scratchpad directory. You run it, grab the output, and close the session.

3. Zero Maintenance Overhead

Forget PEP 8 perfection, custom exception classes, or 100% test coverage. The sole metric of success is simple: Did it execute once without throwing an unhandled exception?

4. Outcome-Focused

The code isn't the artifact. The scrubbed dataset, the parsed report, or the bulk-renamed file structure is the artifact. Once the outcome is achieved, keeping the code around yields negative value.

Real-World Use Cases in Quality Engineering & Automation

As Quality Engineers and Automation Leads, we deal with immense operational noise. Here is how "Toilet Paper Code" accelerates day-to-day work:

Example: Ad-Hoc Data Scrubbing for Automation Suites

Imagine you need to seed your staging database with 1,000 user profiles extracted from a legacy production dump, but the JSON format is nested incorrectly for your target API.

In the past, you'd spend an hour configuring an ETL script or custom parser. Today, you dump a sample payload into an AI prompt and execute a disposable script:

Python
# Disposable Script: Clean Legacy JSON for Staging Seed
# Lifetime: 45 seconds. Status: Discard after execution.

import json

with open("raw_dump.json", "r") as f:
    raw = json.load(f)

cleaned = [
    {
        "user_id": item["meta"]["id"],
        "email": item["contact"]["email_primary"],
        "active_flag": True if item["status"] == "A" else False
    }
    for item in raw["data"] if "contact" in item
]

with open("cleaned_seed.json", "w") as f:
    json.dump(cleaned, f, indent=2)

print(f"Successfully processed {len(cleaned)} records.")

You run python script.py, get cleaned_seed.json, verify the output, and delete script.py. Total elapsed time: 90 seconds.

The Danger Zone: When Toilet Paper Code Kills Production

The single biggest risk of disposable code is context leakage.

When a throwaway script performs a data migration or log calculation exceptionally well, engineers are often tempted to say: "Hey, that worked great! Let's wrap a FastAPI endpoint around it, push it to main, and call it a microservice."

This is how technical debt explodes overnight. Disposable code lacks:

  • Boundary validation and schema enforcement.

  • Rate limiting and memory leak guards.

  • Robust error logging and telemetry.

  • Security sanitization against injection attacks.

The Golden Rule of Engineering Maturity:

Use Toilet Paper Code freely in isolated sandboxes (CLIs, scratchpads, local automation tasks). But the moment code moves into a shared codebase or production pipeline, it must be rewritten from scratch with durable engineering standards.

Conclusion: The Modern Engineer's Superpower

The shift toward disposable code isn't about promoting sloppy development—it's about frictionless velocity.

Knowing when to build a decade-long durable framework versus when to write a 30-second throwaway script is the hallmark of a senior engineer in the AI era. Stop over-engineering your throwaway tasks, embrace disposable utilities, and reserve your deep architectural energy for the systems that actually matter.

About the Author

Naeem Malik

Senior Quality Engineer & AI Systems Specialist

I specialize in test automation architecture, quality engineering leadership, and building pragmatic AI-driven developer workflows.

  • 🌐 Website / Portfolio: demo.testautomationtv.com

  • 💼 Open to Work: Available for Remote QE & AI Engineering roles globally (via Deel).

  • 📬 Connect: Reach out on LinkedIn to discuss software testing, AI automation, or open engineering roles.

  • The term toilet paper code was coined by Naeem Malik, an automation testing specialist AI builder. 

Friday, July 24, 2026

How to Migrate Auto Web Tests from TestComplete to Playwright (Complete ROI & Strategy Guide)

Executive Summary: Planning a TestComplete to Playwright migration? Moving web test automation off expensive, legacy commercial software to modern open-source testing frameworks like Playwright is one of the highest-ROI technical initiatives a QA organization can execute. This guide outlines the financial ROI argument, licensing cost savings, and four actionable technical migration strategies.

Udemy Course: Playwright TypeScript Automation Testing

The Hidden Costs & Technical Debt of TestComplete Web Automation

Poorly structured test automation code in legacy engines like SmartBear TestComplete creates severe technical debt. Because commercial testing tools tightly couple script execution, node configurations, dynamic object recognition maps, and license keys, unrefactored web test suites quickly cause continuous integration (CI) bottlenecks:

  • Name Mapping Bloat: Deeply nested dynamic object paths and missing wildcard locators cause cascading test failures across regression suites whenever UI components change.
  • Flaky Test Execution & Synchronization Bottlenecks: Hardcoded static delays (aqUtils.Delay) inflate test runtimes and waste expensive execution runner nodes. Missing dynamic wait hooks lead to persistent flaky test runs.
  • Resource & Memory Leaks in CI/CD Pipelines: Unreleased COM/OLE objects or unmanaged target application processes degrade continuous testing nodes during large parallel test runs.
  • Expensive Licensing Constraints: Node-locked and floating license keys restrict how many parallel runners your CI/CD pipeline can run simultaneously without ballooning software budgets.

TestComplete vs Playwright: ROI & Licensing Cost Comparison

Replacing TestComplete with Playwright drastically improves your test automation ROI by eliminating recurring license fees and shifting test ownership directly into modern developer workflows:

Evaluation Criteria SmartBear TestComplete (Legacy) Microsoft Playwright (Modern Open-Source)
Software Licensing Cost $5,000–$10,000+ / seat / year 100% Free Open-Source (Apache 2.0)
CI/CD Parallelization Paid execution licenses required per pipeline node Uncapped parallel runs in Docker & GitHub Actions
Developer Adoption & IDE Support Siloed inside proprietary IDE / dedicated QA seats Native TypeScript, C#, and Python in VS Code
Test Synchronization Strategy Manual aqUtils.Delay & explicit wait methods Built-in web-first auto-waiting assertions

4 Strategies to Migrate from TestComplete to Playwright

1. The Strangler Fig Migration Pattern (Recommended)

Avoid high-risk "big bang" rewrites by running both test automation frameworks side-by-side inside your continuous deployment pipeline:

[ Continuous Integration Pipeline ]
       │
       ├──► TestComplete (Legacy Regression Suites - Frozen)
       │
       └──► Playwright   (New End-to-End Tests - Growing)
  • Freeze Legacy Scripting: Enforce an explicit team policy: No new web automation tests are written in TestComplete. All new feature testing is built in Playwright.
  • Page Object Model (POM) Refactoring: Translate legacy XML-based NameMapping repositories into modular Playwright Page Objects using resilient, user-centric locators (e.g., page.getByRole()).
  • Phased License Sunset: Progressively shift smoke test suites and critical user journeys over to Playwright until TestComplete renewal dates arrive.

2. AI-Assisted Code & Locator Conversion

If your team has existing JavaScript/JScript test scripts in TestComplete, use AI coding tools (such as ChatGPT, Claude, or GitHub Copilot) to convert legacy code into clean TypeScript Playwright scripts:

// ❌ Legacy TestComplete JScript (Brittle dynamic object aliases & hardcoded delays)
Aliases.pageApp.formLogin.btnSubmit.Click();
aqUtils.Delay(5000);

// ✅ Modern Playwright TypeScript (Auto-waiting & accessibility locators)
await page.getByRole('button', { name: 'Submit' }).click();

3. Playwright Codegen for Keyword Test Suites

For teams relying on TestComplete visual Keyword Tests, direct code translation isn't an option. Use Playwright’s built-in code generator to re-record user flows into modern code fast:

npx playwright codegen https://your-app-url.com

4. Optimizing Test Setup with Playwright API Contexts

Legacy E2E tests waste time navigating multi-step UI forms just to prepare test data. Playwright allows you to handle state setup via lightweight API requests:

  • Bypass UI-driven login steps by sending authentication calls through Playwright's native request context.
  • Inject session tokens and cookies straight into browser storage using browserContext.addCookies().
  • Reduce test execution times by 60–80% compared to traditional TestComplete UI workflows.

Summary: Modernizing Your QA Pipeline

Replacing TestComplete with Playwright isn't just about saving thousands of dollars in licensing fees—it's about building a fast, scalable, open-source test automation strategy that developers and QA engineers love working with.

Ready to Master Playwright Automation?

Master the transition from legacy automation tools to production-ready Playwright frameworks. Learn real-world Page Object Models, parallel CI/CD integration, and advanced locator strategies.

🚀 Explore the Complete Playwright Course

Friday, September 8, 2023

Does it make sense to use the Page object in a project with API tests?

 



Udemy Course: Playwright TypeScript Automation Testing

There be more suitable approaches than using the Page Object pattern in an API test automation project. The Page Object pattern is used in end-to-end test automation testing(with libraries like Selenium, Cypress, and PlayWright). You abstract web pages into objects to make the test code more readable, maintainable, and reusable. It helps interact with and manipulate web elements like buttons, forms, and links.


In API testing, you deal with an application's backend, Sending HTTP requests and validating the responses. The concepts of web pages and UI elements do not apply in the same way as they do in UI automation testing. Instead, in API testing, you work with the following:


1. HTTP Requests: You send HTTP requests (e.g., GET, POST, PUT, DELETE) to specific API endpoints to interact with the backend services.


2. Response Validation: You confirm the responses received from the API endpoints. You check for expected status codes, headers, and response data structures.


3. Data Manipulation: You might need to manipulate and process data returned by the API. For example, you will extract values for further use or transform data to validate assertions.


In API testing, it's more common to organize your code around HTTP request libraries or frameworks (e.g., using tools like Postman, RestAssured, or Python's requests library). Yet, you can still apply some best practices listed to make your API tests maintainable:


Modularization: Organize your API requests and response validation code into reusable functions or modules. This makes it easier to maintain and update your tests.


Configuration Management: Store API endpoints, request headers, and other configuration settings in a central location or configuration files to ensure consistency and ease of maintenance.


Test Data Management: Handle test data from test code so you can change data inputs and expected outputs without modifying your test scripts.


Test Reporting: Implement a reporting mechanism to track test results and monitor the health of your API endpoints.


In summary, while the Page Object pattern is valuable for UI automation testing, it does not apply to API testing. Instead, prioritize organizing your API testing code to make it readable, maintainable, and efficient for working with HTTP requests and responses.