docs(dotnet): add docs for xUnit (#33742)

This commit is contained in:
Max Schmitt 2024-11-25 10:09:35 +01:00 committed by GitHub
parent e0e4da8ead
commit 9d92b0d3ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 474 additions and 14 deletions

View File

@ -7,7 +7,7 @@ title: "Installation"
Playwright was created specifically to accommodate the needs of end-to-end testing. Playwright supports all modern rendering engines including Chromium, WebKit, and Firefox. Test on Windows, Linux, and macOS, locally or on CI, headless or headed with native mobile emulation.
You can choose to use [MSTest base classes](./test-runners.md) or [NUnit base classes](./test-runners.md) that Playwright provides to write end-to-end tests. These classes support running tests on multiple browser engines, parallelizing tests, adjusting launch/context options and getting a [Page]/[BrowserContext] instance per test out of the box. Alternatively you can use the [library](./library.md) to manually write the testing infrastructure.
You can choose to use MSTest, NUnit, or xUnit [base classes](./test-runners.md) that Playwright provides to write end-to-end tests. These classes support running tests on multiple browser engines, parallelizing tests, adjusting launch/context options and getting a [Page]/[BrowserContext] instance per test out of the box. Alternatively you can use the [library](./library.md) to manually write the testing infrastructure.
1. Start by creating a new project with `dotnet new`. This will create the `PlaywrightTests` directory which includes a `UnitTest1.cs` file:
@ -17,6 +17,7 @@ You can choose to use [MSTest base classes](./test-runners.md) or [NUnit base cl
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -34,6 +35,14 @@ dotnet new mstest -n PlaywrightTests
cd PlaywrightTests
```
</TabItem>
<TabItem value="xunit">
```bash
dotnet new xunit -n PlaywrightTests
cd PlaywrightTests
```
</TabItem>
</Tabs>
@ -45,6 +54,7 @@ cd PlaywrightTests
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -60,6 +70,13 @@ dotnet add package Microsoft.Playwright.NUnit
dotnet add package Microsoft.Playwright.MSTest
```
</TabItem>
<TabItem value="xunit">
```bash
dotnet add package Microsoft.Playwright.Xunit
```
</TabItem>
</Tabs>
@ -87,6 +104,7 @@ Edit the `UnitTest1.cs` file with the code below to create an example end-to-end
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -164,6 +182,41 @@ public class ExampleTest : PageTest
```
</TabItem>
<TabItem value="xunit">
```csharp title="UnitTest1.cs"
using System.Text.RegularExpressions;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task HasTitle()
{
await Page.GotoAsync("https://playwright.dev");
// Expect a title "to contain" a substring.
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
}
[Fact]
public async Task GetStartedLink()
{
await Page.GotoAsync("https://playwright.dev");
// Click the get started link.
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
// Expects page to have a heading with the name of Installation.
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
}
}
```
</TabItem>
</Tabs>
## Running the Example Tests
@ -190,4 +243,4 @@ See our doc on [Running and Debugging Tests](./running-tests.md) to learn more a
- [Generate tests with Codegen](./codegen-intro.md)
- [See a trace of your tests](./trace-viewer-intro.md)
- [Run tests on CI](./ci-intro.md)
- [Learn more about the MSTest and NUnit base classes](./test-runners.md)
- [Learn more about the MSTest, NUnit, and xUnit base classes](./test-runners.md)

View File

@ -30,7 +30,7 @@ You can choose any testing framework such as JUnit or TestNG based on your proje
## .NET
Playwright for .NET comes with [MSTest base classes](https://playwright.dev/dotnet/docs/test-runners) and [NUnit base classes](https://playwright.dev/dotnet/docs/test-runners) for writing end-to-end tests.
Playwright for .NET comes with MSTest, NUnit, and xUnit [base classes](https://playwright.dev/dotnet/docs/test-runners) for writing end-to-end tests.
* [Documentation](https://playwright.dev/dotnet/docs/intro)
* [GitHub repo](https://github.com/microsoft/playwright-dotnet)

View File

@ -5,7 +5,7 @@ title: "Getting started - Library"
## Introduction
Playwright can either be used with the [MSTest](./test-runners.md) or [NUnit](./test-runners.md), or as a Playwright Library (this guide). If you are working on an application that utilizes Playwright capabilities or you are using Playwright with another test runner, read on.
Playwright can either be used with the [MSTest, NUnit, or xUnit base classes](./test-runners.md) or as a Playwright Library (this guide). If you are working on an application that utilizes Playwright capabilities or you are using Playwright with another test runner, read on.
## Usage

View File

@ -113,6 +113,7 @@ dotnet test --filter "Name~GetStartedLink"
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -128,6 +129,19 @@ dotnet test -- NUnit.NumberOfTestWorkers=5
dotnet test -- MSTest.Parallelize.Workers=5
```
</TabItem>
<TabItem value="xunit">
```bash
dotnet test -- xUnit.MaxParallelThreads=5
```
See [here](https://xunit.net/docs/running-tests-in-parallel.html) for more information to run tests in parallel with xUnit.
:::note
We recommend xUnit 2.8+ which uses the [`conservative` parallelism algorithm](https://xunit.net/docs/running-tests-in-parallel.html#algorithms) by default.
:::
</TabItem>
</Tabs>

View File

@ -81,6 +81,7 @@ expect.set_options(timeout=10_000)
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -127,6 +128,24 @@ public class UnitTest1 : PageTest
}
```
</TabItem>
<TabItem value="xunit">
```csharp title="UnitTest1.cs"
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
UnitTest1()
{
SetDefaultExpectTimeout(10_000);
}
// ...
}
```
</TabItem>
</Tabs>

View File

@ -5,7 +5,7 @@ title: "Test Runners"
## Introduction
While Playwright for .NET isn't tied to a particular test runner or testing framework, in our experience the easiest way of getting started is by using the base classes we provide for MSTest and NUnit. These classes support running tests on multiple browser engines, adjusting launch/context options and getting a [Page]/[BrowserContext] instance per test out of the box.
While Playwright for .NET isn't tied to a particular test runner or testing framework, in our experience the easiest way of getting started is by using the base classes we provide for MSTest, NUnit, or xUnit. These classes support running tests on multiple browser engines, adjusting launch/context options and getting a [Page]/[BrowserContext] instance per test out of the box.
Playwright and Browser instances will be reused between tests for better performance. We
recommend running each test case in a new BrowserContext, this way browser state will be
@ -17,6 +17,7 @@ isolated between the tests.
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -28,6 +29,11 @@ Playwright provides base classes to write tests with NUnit via the [`Microsoft.P
Playwright provides base classes to write tests with MSTest via the [`Microsoft.Playwright.MSTest`](https://www.nuget.org/packages/Microsoft.Playwright.MSTest) package.
</TabItem>
<TabItem value="xunit">
Playwright provides base classes to write tests with xUnit via the [`Microsoft.Playwright.Xunit`](https://www.nuget.org/packages/Microsoft.Playwright.Xunit) package.
</TabItem>
</Tabs>
@ -41,6 +47,7 @@ Check out the [installation guide](./intro.md) to get started.
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -64,6 +71,20 @@ Running tests in parallel at the method level (`ExecutionScope.MethodLevel`) is
dotnet test --settings:.runsettings -- MSTest.Parallelize.Workers=4
```
</TabItem>
<TabItem value="xunit">
By default xUnit will run all classes in parallel, while running tests inside each class sequentially.
It will create by default as many processes as there are cores on the system. You can adjust this behavior by using the following CLI parameter or using a `.runsettings` file, see below.
```bash
dotnet test -- xUnit.MaxParallelThreads=5
```
:::note
We recommend xUnit 2.8+ which uses the [`conservative` parallelism algorithm](https://xunit.net/docs/running-tests-in-parallel.html#algorithms) by default.
:::
</TabItem>
</Tabs>
@ -76,6 +97,7 @@ dotnet test --settings:.runsettings -- MSTest.Parallelize.Workers=4
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -154,6 +176,41 @@ public class ExampleTest : PageTest
```
</TabItem>
<TabItem value="xunit">
To customize context options, you can override the `ContextOptions` method of your test class derived from `Microsoft.Playwright.Xunit.PageTest` or `Microsoft.Playwright.Xunit.ContextTest`. See the following example:
```csharp
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
namespace PlaywrightTests;
public class UnitTest1 : PageTest
{
[Fact]
public async Task TestWithCustomContextOptions()
{
// The following Page (and BrowserContext) instance has the custom colorScheme, viewport and baseURL set:
await Page.GotoAsync("/login");
}
public override BrowserNewContextOptions ContextOptions()
{
return new BrowserNewContextOptions()
{
ColorScheme = ColorScheme.Light,
ViewportSize = new()
{
Width = 1920,
Height = 1080
},
BaseURL = "https://github.com",
};
}
}
```
</TabItem>
</Tabs>
@ -194,6 +251,7 @@ When running tests from Visual Studio, you can take advantage of the `.runsettin
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -259,6 +317,36 @@ For example, to specify the number of workers, you can use `MSTest.Parallelize.W
</RunSettings>
```
</TabItem>
<TabItem value="xunit">
For example, to specify the number of workers, you can use `xUnit.MaxParallelThreads`. You can also enable `DEBUG` logs using `RunConfiguration.EnvironmentVariables`.
```xml
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- See https://xunit.net/docs/runsettings -->
<xUnit>
<MaxParallelThreads>1</MaxParallelThreads>
</xUnit>
<!-- General run configuration -->
<RunConfiguration>
<EnvironmentVariables>
<!-- For debugging selectors, it's recommend to set the following environment variable -->
<DEBUG>pw:api</DEBUG>
</EnvironmentVariables>
</RunConfiguration>
<!-- Playwright -->
<Playwright>
<BrowserName>chromium</BrowserName>
<ExpectTimeout>5000</ExpectTimeout>
<LaunchOptions>
<Headless>false</Headless>
<Channel>msedge</Channel>
</LaunchOptions>
</Playwright>
</RunSettings>
```
</TabItem>
</Tabs>
@ -270,6 +358,7 @@ For example, to specify the number of workers, you can use `MSTest.Parallelize.W
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -281,6 +370,11 @@ There are a few base classes available to you in `Microsoft.Playwright.NUnit` na
There are a few base classes available to you in `Microsoft.Playwright.MSTest` namespace:
</TabItem>
<TabItem value="xunit">
There are a few base classes available to you in `Microsoft.Playwright.Xunit` namespace:
</TabItem>
</Tabs>
@ -290,8 +384,3 @@ There are a few base classes available to you in `Microsoft.Playwright.MSTest` n
|ContextTest |Each test will get a fresh copy of a [BrowserContext]. You can create as many pages in this context as you'd like. Using this test is the easiest way to test multi-page scenarios where you need more than one tab.<br></br><br></br>Note: You can override the `ContextOptions` method in each test file to control context options, the ones typically passed into the [`method: Browser.newContext`] method. That way you can specify all kinds of emulation options for your test file individually.|
|BrowserTest |Each test will get a browser and can create as many contexts as it likes. Each test is responsible for cleaning up all the contexts it created.|
|PlaywrightTest|This gives each test a Playwright object so that the test could start and stop as many browsers as it likes.|
## xUnit support
While using xUnit is also supported, we do not support running parallel tests. This is a well known problem/design limitation
outlined by the maintainers across [several](https://github.com/xunit/xunit/issues/2003) [issues](https://github.com/xunit/xunit/issues/2111#issuecomment-650004247).

View File

@ -22,6 +22,7 @@ Traces can be recorded using the [`property: BrowserContext.tracing`] API as fol
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -112,6 +113,69 @@ public class ExampleTest : PageTest
}
```
</TabItem>
<TabItem value="xunit">
```csharp
using System.Reflection;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
using Xunit.Sdk;
namespace PlaywrightTests;
[WithTestName]
public class UnitTest1 : PageTest
{
public override async Task InitializeAsync()
{
await base.InitializeAsync().ConfigureAwait(false);
await Context.Tracing.StartAsync(new()
{
Title = $"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}",
Screenshots = true,
Snapshots = true,
Sources = true
});
}
public override async Task DisposeAsync()
{
await Context.Tracing.StopAsync(new()
{
Path = Path.Combine(
Environment.CurrentDirectory,
"playwright-traces",
$"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}.zip"
)
});
await base.DisposeAsync().ConfigureAwait(false);
}
[Fact]
public async Task GetStartedLink()
{
// ...
await Page.GotoAsync("https://playwright.dev/dotnet/docs/intro");
}
}
public class WithTestNameAttribute : BeforeAfterTestAttribute
{
public static string CurrentTestName = string.Empty;
public static string CurrentClassName = string.Empty;
public override void Before(MethodInfo methodInfo)
{
CurrentTestName = methodInfo.Name;
CurrentClassName = methodInfo.DeclaringType!.Name;
}
public override void After(MethodInfo methodInfo)
{
}
}
```
</TabItem>
</Tabs>
@ -134,4 +198,4 @@ Check out our detailed guide on [Trace Viewer](/trace-viewer.md) to learn more a
## What's next
- [Run tests on CI with GitHub Actions](/ci-intro.md)
- [Learn more about the MSTest and NUnit base classes](./test-runners.md)
- [Learn more about the MSTest, NUnit, and xUnit base classes](./test-runners.md)

View File

@ -254,6 +254,7 @@ Traces can be recorded using the [`property: BrowserContext.tracing`] API as fol
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -348,6 +349,70 @@ public class UnitTest1 : PageTest
}
```
</TabItem>
<TabItem value="xunit">
```csharp
using System.Reflection;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
using Xunit.Sdk;
namespace PlaywrightTests;
[WithTestName]
public class UnitTest1 : PageTest
{
public override async Task InitializeAsync()
{
await base.InitializeAsync().ConfigureAwait(false);
await Context.Tracing.StartAsync(new()
{
Title = $"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}",
Screenshots = true,
Snapshots = true,
Sources = true
});
}
public override async Task DisposeAsync()
{
await Context.Tracing.StopAsync(new()
{
Path = Path.Combine(
Environment.CurrentDirectory,
"playwright-traces",
$"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}.zip"
)
});
await base.DisposeAsync().ConfigureAwait(false);
}
[Fact]
public async Task GetStartedLink()
{
// ...
await Page.GotoAsync("https://playwright.dev/dotnet/docs/intro");
}
}
public class WithTestNameAttribute : BeforeAfterTestAttribute
{
public static string CurrentTestName = string.Empty;
public static string CurrentClassName = string.Empty;
public override void Before(MethodInfo methodInfo)
{
CurrentTestName = methodInfo.Name;
CurrentClassName = methodInfo.DeclaringType!.Name;
}
public override void After(MethodInfo methodInfo)
{
}
}
```
</TabItem>
</Tabs>
@ -365,6 +430,7 @@ Setup your tests to record a trace only when the test fails:
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -459,6 +525,70 @@ public class ExampleTest : PageTest
}
```
</TabItem>
<TabItem value="xunit">
```csharp
using System.Reflection;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
using Xunit.Sdk;
namespace PlaywrightTests;
[WithTestName]
public class UnitTest1 : PageTest
{
public override async Task InitializeAsync()
{
await base.InitializeAsync().ConfigureAwait(false);
await Context.Tracing.StartAsync(new()
{
Title = $"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}",
Screenshots = true,
Snapshots = true,
Sources = true
});
}
public override async Task DisposeAsync()
{
await Context.Tracing.StopAsync(new()
{
Path = !TestOk ? Path.Combine(
Environment.CurrentDirectory,
"playwright-traces",
$"{WithTestNameAttribute.CurrentClassName}.{WithTestNameAttribute.CurrentTestName}.zip"
) : null
});
await base.DisposeAsync().ConfigureAwait(false);
}
[Fact]
public async Task GetStartedLink()
{
// ...
await Page.GotoAsync("https://playwright.dev/dotnet/docs/intro");
}
}
public class WithTestNameAttribute : BeforeAfterTestAttribute
{
public static string CurrentTestName = string.Empty;
public static string CurrentClassName = string.Empty;
public override void Before(MethodInfo methodInfo)
{
CurrentTestName = methodInfo.Name;
CurrentClassName = methodInfo.DeclaringType!.Name;
}
public override void After(MethodInfo methodInfo)
{
}
}
```
</TabItem>
</Tabs>

View File

@ -39,6 +39,7 @@ Take a look at the following example to see how to write a test.
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -117,6 +118,40 @@ public class ExampleTest : PageTest
}
```
</TabItem>
<TabItem value="xunit">
```csharp title="UnitTest1.cs"
using System.Text.RegularExpressions;
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task HasTitle()
{
await Page.GotoAsync("https://playwright.dev");
// Expect a title "to contain" a substring.
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
}
[Fact]
public async Task GetStartedLink()
{
await Page.GotoAsync("https://playwright.dev");
// Click the get started link.
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
// Expects page to have a heading with the name of Installation.
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
}
}
```
</TabItem>
</Tabs>
@ -204,6 +239,7 @@ The Playwright NUnit and MSTest test framework base classes will isolate each te
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
@ -248,23 +284,43 @@ public class ExampleTest : PageTest
}
```
</TabItem>
<TabItem value="xunit">
```csharp title="UnitTest1.cs"
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task BasicTest()
{
await Page.GotoAsync("https://playwright.dev");
}
}
```
</TabItem>
</Tabs>
## Using Test Hooks
You can use `SetUp`/`TearDown` in NUnit or `TestInitialize`/`TestCleanup` in MSTest to prepare and clean up your test environment:
<Tabs
groupId="test-runners"
defaultValue="mstest"
values={[
{label: 'MSTest', value: 'mstest'},
{label: 'NUnit', value: 'nunit'},
{label: 'xUnit', value: 'xunit'},
]
}>
<TabItem value="nunit">
You can use `SetUp`/`TearDown` to prepare and clean up your test environment:
```csharp title="UnitTest1.cs"
using System.Threading.Tasks;
using Microsoft.Playwright.NUnit;
@ -294,6 +350,8 @@ public class ExampleTest : PageTest
</TabItem>
<TabItem value="mstest">
You can use `TestInitialize`/`TestCleanup` to prepare and clean up your test environment:
```csharp title="UnitTest1.cs"
using System.Threading.Tasks;
using Microsoft.Playwright.MSTest;
@ -319,6 +377,39 @@ public class ExampleTest : PageTest
}
```
</TabItem>
<TabItem value="xunit">
You can use `InitializeAsync`/`DisposeAsync` to prepare and clean up your test environment:
```csharp title="UnitTest1.cs"
using Microsoft.Playwright;
using Microsoft.Playwright.Xunit;
namespace PlaywrightTests;
public class UnitTest1: PageTest
{
[Fact]
public async Task MainNavigation()
{
// Assertions use the expect API.
await Expect(Page).ToHaveURLAsync("https://playwright.dev/");
}
override public async Task InitializeAsync()
{
await base.InitializeAsync();
await Page.GotoAsync("https://playwright.dev");
}
public override async Task DisposeAsync()
{
Console.WriteLine("After each test cleanup");
await base.DisposeAsync();
}
}
```
</TabItem>
</Tabs>
@ -328,4 +419,4 @@ public class ExampleTest : PageTest
- [Generate tests with Codegen](./codegen-intro.md)
- [See a trace of your tests](./trace-viewer-intro.md)
- [Run tests on CI](./ci-intro.md)
- [Learn more about the MSTest and NUnit base classes](./test-runners.md)
- [Learn more about the MSTest, NUnit, or xUnit base classes](./test-runners.md)