Skip to Content

From Protractor to Playwright: Speeding Up UI and API Test Automation - Part 3 (Final)

Welcome to the final stage of our series on migrating from Protractor to Playwright! In Part 1 and Part 2, we discussed the strategic decision to transition and the initial steps of moving UI tests. Now, we'll dive into the successful migration of our API tests, showcasing the significant performance gains and the refined testing practices we've adopted.


The API Testing: From Protractor to Playwright

Our journey to modernize our testing suite wasn't limited to UI. A significant portion involved migrating our API tests, which are crucial for ensuring the robustness and reliability of our backend services. This migration presented an opportunity to streamline our API testing workflows, enhance debugging capabilities, and ultimately achieve faster feedback cycles.


Impressive results

We successfully migrated 28 test spec files encompassing a total of 330 tests. The results are compelling: our overall test execution time plummeted from 200.07 minutes with Protractor to a mere 81.8 minutes with Playwright, representing an average performance win of 59.11%! This dramatic improvement translates directly into faster development cycles and quicker identification of issues.

The detailed breakdown reveals consistent and significant time savings across almost all migrated test suites, with some experiencing over a 70% reduction in execution time. This efficiency gain is a testament to Playwright's optimized architecture and its ability to handle concurrent API requests more effectively than our previous setup.


Enhancing Developer Experience: Debugging and Logging

Beyond raw speed, the migration allowed us to implement clever coding exercises that significantly improve the developer experience, particularly in debugging and logging.

Intelligent Status Code Validation

One such enhancement is our statusCodeValidator. This tiny but powerful function dramatically improves logging and debugging for API tests. Instead of a generic error message, it provides immediate context by capturing recent API activity logs when an unexpected status code is encountered.

TypeScript

private statusCodeValidator(actualStatus: number, expectedStatus: number, callingMethod: Function) {
    if (actualStatus !== expectedStatus) {
        const logs = this.logger.getRecentLogs();
        const error = new Error(`Expected status ${expectedStatus} but got ${actualStatus}\n\nRecent API Activity: \n${logs}`);
        Error.captureStackTrace(error, callingMethod)
        throw error;
    }
}

This snippet ensures that when an API call returns an unexpected status, the error message isn't just "wrong status code." Instead, it includes a snapshot of the recent API requests and responses, providing invaluable context for quick problem identification. This directly reduces the time spent on debugging failed tests. 

Streamlined Request Handling for POST Requests

Our postRequest method exemplifies how we've streamlined API request handling in Playwright. This method now includes robust logging and validation, ensuring that every POST request is transparent and easily debuggable.

TypeScript

async postRequest(statusCode: number) {
    let responseJSON: any;
    const url = this.getUrl();
    await test.step(`POST request to: ${url}`, async () => {
        this.logger.logRequest('POST', url, this.getHeaders(), this.apiBody);
        const response = await this.request.post(url, {
            headers: this.getHeaders(),
            data: this.apiBody
        });
        this.cleanupFields();
        const actualStatus = response.status();
        responseJSON = await response.json();
        this.logger.logResponse(actualStatus, responseJSON);
        this.statusCodeValidator(actualStatus, statusCode, this.postRequest);
    });
    return responseJSON;
}

Within this postRequest function, we've integrated our logger to record both the outgoing request (method, URL, headers, body) and the incoming response (status and JSON body). This comprehensive logging, combined with our statusCodeValidator, means that for every POST request, we have a clear, step-by-step record of its execution and validation. This is particularly beneficial for complex API interactions, allowing developers to quickly trace the flow of data and pinpoint the exact point of failure if an issue arises.


Conclusion: Modern QA Automation

Modern QA automation frameworks like Playwright are crucial for driving efficiency, accelerating development cycles, and ultimately delivering higher-quality software faster. Faster feedback loops mean developers can iterate quicker, bugs are caught earlier, and the overall software delivery pipeline becomes more robust and reliable.

For companies like ours, building custom software means that product quality is paramount. A solid foundation in modern QA automation is not just a luxury; it's a necessity for sustained growth and innovation.


Let us help build testing foundation

At VaynerSystems, we understand the challenges of migrating legacy test suites and the immense benefits of a modern automation strategy. We can help your team build a strong foundation and establish scalable QA solutions that combine speed with precision. Our expertise in Playwright and other cutting-edge testing frameworks ensures your software delivery remains agile and robust.

Contact us for support or a tailored automation strategy.

From Protractor to Playwright: Speeding up UI and API test automation – Part 2