Features

Playwright & .NET

Playwright for .NET provides a powerful API for browser automation that can be used for end-to-end testing with C# and other .NET languages.
See the example below on how to use .NET with Playwright to run tests on the TestingBot browser grid.

More information about Playwright for .NET can be found on the Playwright .NET documentation.

Installation

To get started with Playwright for .NET, you'll need to install the relevant NuGet packages for your preferred test framework:

To install the Playwright NuGet packages for MSTest, run the following commands in your terminal:

Copy code
dotnet new mstest
dotnet add package Microsoft.Playwright
dotnet add package Microsoft.Playwright.MSTest
dotnet build
pwsh bin/Debug/net8.0/playwright.ps1 install

On macOS/Linux, use:

Copy code
playwright install

To install the Playwright NuGet packages for NUnit, run the following commands in your terminal:

Copy code
dotnet new nunit
dotnet add package Microsoft.Playwright
dotnet add package Microsoft.Playwright.NUnit
dotnet build
pwsh bin/Debug/net8.0/playwright.ps1 install

On macOS/Linux, use:

Copy code
playwright install

To install the Playwright NuGet packages for xUnit, run the following commands in your terminal:

Copy code
dotnet new xunit
dotnet add package Microsoft.Playwright
dotnet build
pwsh bin/Debug/net8.0/playwright.ps1 install

On macOS/Linux, use:

Copy code
playwright install

Note that there is no specific Microsoft.Playwright.xUnit package, but you can still use Playwright with xUnit.

Code Generation

Playwright provides a powerful code generation tool that helps you quickly create test scripts by recording your interactions with the browser. To use it, run the following command:

Copy code
pwsh bin/Debug/net8.0/playwright.ps1 codegen https://testingbot.com

On macOS/Linux, use:

Copy code
playwright codegen https://testingbot.com

This will open a browser window where you can interact with the webpage, and Playwright will generate C# code based on your actions. You can then copy this code and use it as a starting point for your tests.

Running Tests

To run your tests, use the standard dotnet test command:

Copy code
dotnet test

You can also run specific test classes or methods:

Copy code
dotnet test --filter "FullyQualifiedName=PlaywrightTests.PlaywrightTestingBotTest"

Example using NUnit:

Copy code
using System;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Playwright;
using Microsoft.Playwright.NUnit;
using NUnit.Framework;

namespace PlaywrightTests
{
    [Parallelizable(ParallelScope.Self)]
    public class PlaywrightTestingBotTest : PageTest
    {
        private IBrowser _browser;
        private IBrowserContext _context;
        private IPage _page;

        [SetUp]
        public async Task SetupTestAsync()
        {
            // Create the capabilities object with authentication information
            var capabilities = new JsonObject
            {
                ["browserName"] = "chrome",
                ["browserVersion"] = "latest",
                ["platform"] = "WIN10",
                ["tb:options"] = new JsonObject
                {
                    ["key"] = "YOUR_KEY",
                    ["secret"] = "YOUR_SECRET"
                }
            };

            // Create the playwright instance
            var playwright = await Playwright.CreateAsync();

            // Connect to TestingBot
            var wsEndpoint = $"wss://cloud.testingbot.com/playwright?capabilities={HttpUtility.UrlEncode(capabilities.ToJsonString())}";
            _browser = await playwright.Chromium.ConnectAsync(new BrowserTypeConnectOptions
            {
                WsEndpoint = wsEndpoint
            });

            // Create a context and page
            _context = await _browser.NewContextAsync();
            _page = await _context.NewPageAsync();
        }

        [TearDown]
        public async Task TearDownTestAsync()
        {
            if (_page != null)
            {
                // Take a screenshot at the end of the test
                await _page.ScreenshotAsync(new PageScreenshotOptions
                {
                    Path = $"screenshot-{Guid.NewGuid()}.png"
                });

                await _context?.CloseAsync();
                await _browser?.CloseAsync();
            }
        }

        [Test]
        public async Task ShouldCheckPageTitle()
        {
            await _page.GotoAsync("https://testingbot.com/");
            var title = await _page.TitleAsync();
            Assert.AreEqual("Cross Browser Testing and Mobile App Testing | TestingBot", title);
        }
    }
}

Example using MSTest:

Copy code
using System;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Playwright;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace PlaywrightTests
{
    [TestClass]
    public class PlaywrightTestingBotTest
    {
        private static IPlaywright _playwright;
        private IBrowser _browser;
        private IBrowserContext _context;
        private IPage _page;

        [TestInitialize]
        public async Task TestInitialize()
        {
            // Create the capabilities object with authentication information
            var capabilities = new JsonObject
            {
                ["browserName"] = "chrome",
                ["browserVersion"] = "latest",
                ["platform"] = "WIN10",
                ["tb:options"] = new JsonObject
                {
                    ["key"] = "YOUR_KEY",
                    ["secret"] = "YOUR_SECRET"
                }
            };

            // Create the playwright instance
            _playwright = await Playwright.CreateAsync();

            // Connect to TestingBot
            var wsEndpoint = $"wss://cloud.testingbot.com/playwright?capabilities={HttpUtility.UrlEncode(capabilities.ToJsonString())}";
            _browser = await _playwright.Chromium.ConnectAsync(new BrowserTypeConnectOptions
            {
                WsEndpoint = wsEndpoint
            });

            // Create a context and page
            _context = await _browser.NewContextAsync();
            _page = await _context.NewPageAsync();
        }

        [TestCleanup]
        public async Task TestCleanup()
        {
            if (_page != null)
            {
                // Take a screenshot at the end of the test
                await _page.ScreenshotAsync(new PageScreenshotOptions
                {
                    Path = $"screenshot-{Guid.NewGuid()}.png"
                });

                await _context?.CloseAsync();
                await _browser?.CloseAsync();
                _playwright.Dispose();
            }
        }

        [TestMethod]
        public async Task ShouldCheckPageTitle()
        {
            await _page.GotoAsync("https://testingbot.com/");
            var title = await _page.TitleAsync();
            Assert.AreEqual("Cross Browser Testing and Mobile App Testing | TestingBot", title);
        }
    }
}

Example using xUnit:

Copy code
using System;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Playwright;
using Xunit;

namespace PlaywrightTests
{
    public class PlaywrightTestingBotTest : IAsyncLifetime
    {
        private IPlaywright _playwright;
        private IBrowser _browser;
        private IBrowserContext _context;
        private IPage _page;

        public async Task InitializeAsync()
        {
            // Create the capabilities object with authentication information
            var capabilities = new JsonObject
            {
                ["browserName"] = "chrome",
                ["browserVersion"] = "latest",
                ["platform"] = "WIN10",
                ["tb:options"] = new JsonObject
                {
                    ["key"] = "YOUR_KEY",
                    ["secret"] = "YOUR_SECRET"
                }
            };

            // Create the playwright instance
            _playwright = await Playwright.CreateAsync();

            // Connect to TestingBot
            var wsEndpoint = $"wss://cloud.testingbot.com/playwright?capabilities={HttpUtility.UrlEncode(capabilities.ToJsonString())}";
            _browser = await _playwright.Chromium.ConnectAsync(new BrowserTypeConnectOptions
            {
                WsEndpoint = wsEndpoint
            });

            // Create a context and page
            _context = await _browser.NewContextAsync();
            _page = await _context.NewPageAsync();
        }

        public async Task DisposeAsync()
        {
            if (_page != null)
            {
                // Take a screenshot at the end of the test
                await _page.ScreenshotAsync(new PageScreenshotOptions
                {
                    Path = $"screenshot-{Guid.NewGuid()}.png"
                });

                await _context?.CloseAsync();
                await _browser?.CloseAsync();
                _playwright.Dispose();
            }
        }

        [Fact]
        public async Task ShouldCheckPageTitle()
        {
            await _page.GotoAsync("https://testingbot.com/");
            var title = await _page.TitleAsync();
            Assert.Equal("Cross Browser Testing and Mobile App Testing | TestingBot", title);
        }
    }
}

This example will use Playwright to connect to a Chrome browser in the TestingBot cloud.
It will open the TestingBot website, retrieve the title of the page and verify with NUnit assertions if the title is correct.

You can also use test frameworks like MSTest or xUnit with Playwright, following a similar approach. Just adapt the test attributes according to your preferred test framework.

After each test, we'll take a screenshot and close the browser context to clean up resources.

Parallel Testing with .NET

One of the great advantages of the TestingBot service is that you can run multiple tests simultaneously.
This drastically shortens the total duration of your test suite, as multiple tests will run concurrently.

Here's how you can set up parallel test execution using NUnit:

Copy code
using System;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Playwright;
using NUnit.Framework;

namespace PlaywrightTests
{
    [TestFixture]
    [Parallelizable(ParallelScope.All)] // Enable parallel execution
    public class ParallelPlaywrightTests
    {
        // Helper method to set up the browser
        private async Task<ibrowser> SetupBrowserAsync(string browserName)
        {
            // Create capabilities
            var capabilities = new JsonObject
            {
                ["browserName"] = browserName,
                ["browserVersion"] = "latest",
                ["tb:options"] = new JsonObject
                {
                    ["key"] = "YOUR_KEY",
                    ["secret"] = "YOUR_SECRET"
                }
            };

            // Create the playwright instance
            var playwright = await Playwright.CreateAsync();
            
            // Determine which browser type to use
            IBrowserType browserType;
            switch (browserName.ToLower())
            {
                case "chrome":
                    browserType = playwright.Chromium;
                    break;
                case "firefox":
                    browserType = playwright.Firefox;
                    break;
                case "webkit":
                case "safari":
                    browserType = playwright.Webkit;
                    break;
                default:
                    throw new ArgumentException($"Unsupported browser: {browserName}");
            }
            
            // Connect to TestingBot
            var wsEndpoint = $"wss://cloud.testingbot.com/playwright?capabilities={HttpUtility.UrlEncode(capabilities.ToJsonString())}";
            return await browserType.ConnectAsync(new BrowserTypeConnectOptions
            {
                WsEndpoint = wsEndpoint
            });
        }

        [Test]
        public async Task TestHomepageInChrome()
        {
            // Each test manages its own browser instance
            using var playwright = await Playwright.CreateAsync();
            var browser = await SetupBrowserAsync("chrome");
            
            try
            {
                var context = await browser.NewContextAsync();
                var page = await context.NewPageAsync();
                
                try
                {
                    await page.GotoAsync("https://testingbot.com/");
                    var title = await page.TitleAsync();
                    Assert.AreEqual("Cross Browser Testing and Mobile App Testing | TestingBot", title);
                    await page.ScreenshotAsync(new PageScreenshotOptions
                    {
                        Path = "chrome-homepage.png"
                    });
                }
                finally
                {
                    await context.CloseAsync();
                }
            }
            finally
            {
                await browser.CloseAsync();
            }
        }

        [Test]
        public async Task TestPricingPageInFirefox()
        {
            // Each test manages its own browser instance
            using var playwright = await Playwright.CreateAsync();
            var browser = await SetupBrowserAsync("firefox");
            
            try
            {
                var context = await browser.NewContextAsync();
                var page = await context.NewPageAsync();
                
                try
                {
                    await page.GotoAsync("https://testingbot.com/pricing");
                    var title = await page.TitleAsync();
                    Assert.AreEqual("Cross Browser Testing - Prices and plans available for test online.", title);
                    await page.ScreenshotAsync(new PageScreenshotOptions
                    {
                        Path = "firefox-pricing.png"
                    });
                }
                finally
                {
                    await context.CloseAsync();
                }
            }
            finally
            {
                await browser.CloseAsync();
            }
        }
    }
}</ibrowser>

To enable parallel execution with NUnit, add the following to your NUnit.runsettings file:

Copy code
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <NUnit>
    <NumberOfTestWorkers>4</NumberOfTestWorkers>
  </NUnit>
</RunSettings>

For MSTest, you can configure parallel execution in your .runsettings file:

Copy code
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <MSTest>
    <Parallelize>
      <Workers>4</Workers>
      <Scope>ClassLevel</Scope>
    </Parallelize>
  </MSTest>
</RunSettings>

The examples above demonstrate how to run multiple tests concurrently against different browsers on the TestingBot infrastructure. Each test manages its own browser instance, allowing multiple tests to run in parallel.

Depending on how many tests you run in parallel, you can drastically shorten your total test duration and get faster feedback from your tests.