Showing posts with label Thread Local in Playwright. Show all posts
Showing posts with label Thread Local in Playwright. Show all posts

Thread Local in Playwright

















ThreadLocal in Java with Playwright: Complete Guide for Parallel Test Execution

When working with modern automation frameworks, parallel execution has become a necessity rather than an option. Running tests in parallel helps reduce execution time and improves CI/CD efficiency. However, parallel testing introduces a major challenge — thread safety.

If you are using Playwright with Java, you must understand how to manage browser instances safely across multiple threads. This is where ThreadLocal in Java becomes extremely important.

In this detailed guide, you will learn:

  • What is ThreadLocal in Java?

  • Why ThreadLocal is required in Playwright Java

  • How ThreadLocal prevents flaky tests

  • Step-by-step implementation with Playwright

  • Complete example using TestNG

  • Best practices for parallel execution

This article is fully SEO optimized, beginner friendly, and written in a human-like style so that automation engineers at any level can understand and implement it easily.


What is ThreadLocal in Java?

ThreadLocal is a utility class in Java that provides thread-local variables.

In simple words:

Each thread accessing a ThreadLocal variable gets its own independent copy.

If one thread modifies the value, it does not affect other threads.

This makes ThreadLocal extremely useful in multi-threaded environments where shared variables can lead to:

  • Race conditions

  • Data corruption

  • Inconsistent results

  • Flaky test execution

Instead of sharing one common variable across all threads, ThreadLocal ensures isolation.


Why ThreadLocal is Important in Automation Testing

In automation frameworks, especially when using:

  • Parallel execution

  • CI/CD pipelines

  • Cloud browser execution

  • Multiple browser instances

Thread safety becomes critical.

If multiple test threads share the same object instance (like Browser or Page), one test may:

  • Close the browser unexpectedly

  • Navigate to a different page

  • Modify session data

  • Overwrite cookies or local storage

This leads to unstable and unpredictable automation results.

ThreadLocal solves this problem by giving each test thread its own browser objects.


Why Use ThreadLocal in Playwright Java?

Playwright supports parallel execution across:

  • Multiple browsers

  • Multiple contexts

  • Multiple pages

  • Multiple threads

However, Playwright objects like:

  • Playwright

  • Browser

  • BrowserContext

  • Page

are not thread-safe by default.

If you share a single instance of Browser or Page across multiple threads, your tests will interfere with each other.

To avoid this, we use ThreadLocal storage so that:

  • Each thread maintains its own Playwright instance

  • Each thread has its own Browser

  • Each thread has its own BrowserContext

  • Each thread has its own Page

This prevents:

  • Data leakage

  • Object collision

  • Flaky behavior

  • Cross-test contamination


Real-World Use Case

Imagine running 5 tests in parallel:

  • Test 1 logs into Application A

  • Test 2 logs into Application B

  • Test 3 performs search

  • Test 4 validates cart

  • Test 5 logs out

If all threads share the same Page object:

  • One test might close the browser while another is still running

  • Navigation in one test affects other tests

  • Session cookies overlap

Result? Flaky tests and unstable automation.

With ThreadLocal:

Each thread gets its own isolated browser environment.


How ThreadLocal Works in Playwright Java

The process involves four key steps:

1. Define ThreadLocal Variables

We create ThreadLocal objects for:

  • Playwright

  • Browser

  • BrowserContext

  • Page

Each thread will hold its own instance.


2. Initialize Objects Per Thread

When a test thread starts:

  • Create Playwright instance

  • Launch browser

  • Create context

  • Create page

All stored inside ThreadLocal.


3. Access Objects Safely

Instead of using shared variables, we use getter methods:

PlaywrightFactory.getPage();

This ensures we access the Page belonging only to that thread.


4. Clean Up After Execution

After test completion:

  • Close Page

  • Close Context

  • Close Browser

  • Close Playwright

  • Remove ThreadLocal variables

This prevents memory leaks.


Example: Thread-Safe Playwright Framework in Java

Let’s automate:

https://www.google.com

We will use:

TestNG for parallel execution.


PlaywrightFactory.java

This class manages ThreadLocal objects.

import com.microsoft.playwright.*; public class PlaywrightFactory { private static ThreadLocal<Playwright> tlPlaywright = new ThreadLocal<>(); private static ThreadLocal<Browser> tlBrowser = new ThreadLocal<>(); private static ThreadLocal<BrowserContext> tlContext = new ThreadLocal<>(); private static ThreadLocal<Page> tlPage = new ThreadLocal<>(); public static void initPlaywright() { tlPlaywright.set(Playwright.create()); } public static void initBrowser() { BrowserType.LaunchOptions options = new BrowserType.LaunchOptions().setHeadless(false); tlBrowser.set(getPlaywright().chromium().launch(options)); } public static void initContext() { tlContext.set(getBrowser().newContext()); } public static void initPage() { tlPage.set(getContext().newPage()); } public static Playwright getPlaywright() { return tlPlaywright.get(); } public static Browser getBrowser() { return tlBrowser.get(); } public static BrowserContext getContext() { return tlContext.get(); } public static Page getPage() { return tlPage.get(); } public static void closeAll() { getPage().close(); getContext().close(); getBrowser().close(); getPlaywright().close(); tlPage.remove(); tlContext.remove(); tlBrowser.remove(); tlPlaywright.remove(); } }


Code Explanation

ThreadLocal Declaration

private static ThreadLocal<Page> tlPage = new ThreadLocal<>();

Each thread stores its own Page object.


Initialization

tlPage.set(getContext().newPage());

The page created belongs only to the current thread.


Getter Method

public static Page getPage() { return tlPage.get(); }

This ensures safe access.


Cleanup

tlPage.remove();

Prevents memory leaks after execution.


SampleTest.java

Now let’s write a TestNG test class.

import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.microsoft.playwright.*; public class SampleTest { @BeforeMethod public void setUp() { PlaywrightFactory.initPlaywright(); PlaywrightFactory.initBrowser(); PlaywrightFactory.initContext(); PlaywrightFactory.initPage(); } @Test public void testGoogleSearch() { Page page = PlaywrightFactory.getPage(); page.navigate("https://www.google.com"); System.out.println("Page Title: " + page.title()); } @AfterMethod public void tearDown() { PlaywrightFactory.closeAll(); } }


Execution Flow

@BeforeMethod

  • Initialize Playwright

  • Launch Browser

  • Create Context

  • Create Page

All stored inside ThreadLocal.


@Test

  • Fetch Page using ThreadLocal getter

  • Navigate to Google

  • Print title

Each thread uses its own browser instance.


@AfterMethod

  • Close everything

  • Remove ThreadLocal references


How to Enable Parallel Execution in TestNG

In your testng.xml file:

<suite name="Parallel Suite" parallel="methods" thread-count="3"> <test name="Test"> <classes> <class name="SampleTest"/> </classes> </test> </suite>

This will:

  • Run 3 threads simultaneously

  • Each thread gets isolated Playwright objects

  • No interference between tests


Benefits of Using ThreadLocal in Playwright

1. Thread Safety

No shared browser instances.

2. Faster Execution

Parallel tests reduce runtime significantly.

3. Stable Tests

Reduces flaky test failures.

4. CI/CD Friendly

Works smoothly in Jenkins, GitHub Actions, Azure DevOps.

5. Clean Architecture

Improves framework design.


Common Mistakes to Avoid

  1. Forgetting to call remove() on ThreadLocal.

  2. Sharing Browser instance accidentally.

  3. Not closing resources properly.

  4. Running parallel tests without isolation.


Best Practices

  • Always use ThreadLocal for Playwright objects.

  • Use Page Object Model for better structure.

  • Keep initialization centralized in a Factory class.

  • Enable parallel only after ensuring thread safety.

  • Monitor memory usage in long test suites.


When Should You Use ThreadLocal?

You must use ThreadLocal when:

  • Running parallel tests

  • Using TestNG or JUnit parallel execution

  • Executing in CI pipelines

  • Running cloud browser grids

  • Building scalable automation frameworks

If you are running tests sequentially, ThreadLocal is not mandatory — but for enterprise frameworks, it is strongly recommended.


SEO Keywords Covered

  • ThreadLocal in Java

  • ThreadLocal in Playwright Java

  • Playwright parallel execution

  • Thread safety in automation testing

  • Playwright with TestNG

  • Java multithreading in automation

  • Playwright framework design

  • Prevent flaky tests in Playwright


Suggested Posts:

1. Playwright with TestNG Integration
2. Automate Login Page in Playwright
3. Comma Selectors in Playwright
4. Trace Viewer in Playwright
5. Handle GET API in Playwright