Writing tests

Introduction

CSTesting for .NET (C:\CSTesting-DotNet) uses async methods on ICSTestingBrowser and ICSTestingLocator (see README.md). Tests are ordinary NUnit tests: use Assert.That with values from await Browser..... There is no assertThat on the browser.

The snippet below matches the style of tests/CSTesting.Tests/SampleRecordedTest.cs.

using System.Threading.Tasks;
using CSTesting;
using CSTesting.NUnit;
using NUnit.Framework;
using static CSTesting.CSTesting;

[TestFixture]
public class ExampleTests : CSTestingNUnitBrowserFixtureBase
{
    [SetUp]
    public async Task SetUp()
    {
        if (Browser == null)
            Browser = await CreateBrowserAsync(new CSTestingOptions { Headless = true });
    }

    [Test]
    public async Task Example_Loads()
    {
        await Browser!.GotoAsync("https://example.com");
        var title = await Browser.EvaluateAsync<string>("document.title");
        Assert.That(title, Does.Contain("Example"));

        var href = await Browser.Locator("a").First().GetAttributeAsync("href");
        Assert.That(href, Is.Not.Empty);

        await Browser.ClickAsync("a");
        await Browser.WaitForLoadAsync();
        Assert.That(await Browser.Locator("h1").IsVisibleAsync(), Is.True);
    }
}

Assertions

Use NUnit constraints with data from the browser API.

Page:

var url = await Browser!.GetUrlAsync();
Assert.That(url, Does.Contain("example.com"));

var title = await Browser.EvaluateAsync<string>("document.title");
Assert.That(title, Does.Contain("Example Domain"));

Element:

Assert.That(await Browser!.Locator("h1").GetTextContentAsync(),
    Does.Contain("Welcome"));

Assert.That(await Browser.IsVisibleAsync("button"), Is.True);
Assert.That(await Browser.IsDisabledAsync("#submit"), Is.False);

var val = await Browser.Locator("#search").GetAttributeAsync("value");
Assert.That(val, Is.EqualTo("query"));

See Assertions for more patterns.

Locators

Create locators with Browser.Locator(selector). Actions are async: await loc.ClickAsync(), await loc.TypeAsync("text"). For multiple matches use .First(), .Last(), or .Nth(n) on ICSTestingLocator.

Selector formats: Playwright-style — CSS, XPath (//...), id=, name=, etc. (see Locators).

var link = Browser!.Locator("//a[contains(.,'More information')]").First();
var href = await link.GetAttributeAsync("href");
Assert.That(href, Does.Contain("iana"));
await link.ClickAsync();

await Browser.TypeAsync("name=email", "user@example.com");

Test isolation

Create a new browser per test in [SetUp] (or per fixture) so cookies and storage do not leak. With CSTestingNUnitBrowserFixtureBase, the base [TearDown] closes the browser after each test. Alternatively, use await using with CreateBrowserAsync inside a single test (ICSTestingBrowser implements IAsyncDisposable).

[Test]
public async Task Login_Redirects()
{
    await using var browser = await CreateBrowserAsync(new CSTestingOptions { Headless = true });
    await browser.GotoAsync("https://example.com/login");
    await browser.TypeAsync("name=user", "alice");
    await browser.TypeAsync("name=pass", "secret");
    await browser.ClickAsync("button[type=submit]");
    await browser.WaitForURLAsync("**/welcome", 10_000);
}