Tag Archives: playwright

Playwright in CI/CD pipelines

I use Playwright for testing in .NET with Azure DevOps. A CI pipeline performs builds. A CD pipeline deploys product and runs tests.

Playwright expects browser binaries %USERPROFILE%\AppData\Local\ms-playwright

The documentation says to run bin\Debug\netX\playwright.ps1 install to download them. In my case playwright.ps1 did not exist and test were unable to run. I solved it in my CI pipeline like this.

  - task: PowerShell@2
    displayName: Download Playwright Browsers
    continueOnError: True
      targetType: inline
      script: >-
        cd <directory with the playwright .csproj>
        dotnet build
        dotnet tool install --global Microsoft.Playwright.CLI
        playwright install
  build remaining projects, code analysis etc. etc.
  - task: CopyFiles@2
    displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
      SourceFolder: $(system.defaultworkingdirectory)
      Contents: '**\bin\$(BuildConfiguration)\**'
      TargetFolder: $(build.artifactstagingdirectory)
      CleanTargetFolder: true

This creates the script, downloads the browsers and includes the script into the build artifact for other stages and pipelines.

If your CD pipeline uses different machines or users, you need to run playwright.ps1 install in the CD pipeline before starting tests.

Comparing Playwright to Selenium

Playwright is a library for controlling web browsers similar to Cypress, Nightwatch, Selenium etc etc. Its modern, advanced and fast! Especially compared to Selenium and Selenium Grid from providers such as BrowserStack and SauceLabs.

Playwright supports videos, console and network logs out of the box. Even for headless browsers.

You can work with downloads, browser’s network-stack and console.

It has convenient ways of locating elements and easily combines different locator types into 1 locator. Selenium has ByChained, but is more cumbersome.

It automatically waits for elements to be actionable, while Selenium requires the tester to use constructs like: Wait.Until(ElementIsClickable()).Click()

Playwright does way less DOM access than Selenium. Here’s an somewhat extreme example to show the difference. If you do this in Selenium, then for each row, it will query the DOM to return a WebElement for the checkbox in the row.

var rows = FindElements(By.ClassName("table-row"))
foreach(var row in rows)
   var checkbox = row.FindElement(By.ClassName("checkbox"))

Playwright won’t query the DOM for the checkbox. It returns a new locator (equivalent to Selenium’s By class) derived from the row web element to find that specific check-box.

Runs headless in CI/CD pipelines but still delivers video recordings and logfiles.

Although most tutorials use the default Playwright test runner, its works great with TypeScript and cucumber-js.