2022-07-19 00:39:01 +03:00
---
id: writing-tests
2023-03-06 22:52:58 +03:00
title: "Writing tests"
2022-07-19 00:39:01 +03:00
---
2023-10-06 16:08:51 +03:00
## Introduction
2024-05-02 13:06:39 +03:00
Playwright tests are simple, they
2022-07-19 00:39:01 +03:00
2024-05-02 13:06:39 +03:00
- **perform actions**, and
- **assert the state** against expectations.
There is no need to wait for anything prior to performing an action: Playwright
automatically waits for the wide range of [actionability ](./actionability.md )
checks to pass prior to performing each action.
There is also no need to deal with the race conditions when performing the checks -
Playwright assertions are designed in a way that they describe the expectations
that need to be eventually met.
That's it! These design choices allow Playwright users to forget about flaky
timeouts and racy checks in their tests altogether.
**You will learn**
- [How to write the first test ](/writing-tests.md#first-test )
- [How to perform actions ](/writing-tests.md#actions )
- [How to use assertions ](/writing-tests.md#assertions )
- [How tests run in isolation ](/writing-tests.md#test-isolation )
- [How to use test hooks ](/writing-tests.md#using-test-hooks )
## First test
Take a look at the following example to see how to write a test.
2022-07-19 00:39:01 +03:00
< Tabs
2022-08-03 14:39:18 +03:00
groupId="test-runners"
2024-06-11 16:06:03 +03:00
defaultValue="mstest"
2022-07-19 00:39:01 +03:00
values={[
2024-06-11 16:06:03 +03:00
{label: 'MSTest', value: 'mstest'},
2022-07-19 00:39:01 +03:00
{label: 'NUnit', value: 'nunit'},
]
}>
< TabItem value = "nunit" >
2024-01-31 19:49:01 +03:00
```csharp title="UnitTest1.cs"
2022-07-19 00:39:01 +03:00
using System.Text.RegularExpressions;
2022-12-19 18:28:17 +03:00
using System.Threading.Tasks;
using Microsoft.Playwright;
2022-07-19 00:39:01 +03:00
using Microsoft.Playwright.NUnit;
2022-12-19 18:28:17 +03:00
using NUnit.Framework;
2022-07-19 00:39:01 +03:00
namespace PlaywrightTests;
[Parallelizable(ParallelScope.Self)]
2022-09-08 02:44:58 +03:00
[TestFixture]
2024-05-02 13:06:39 +03:00
public class ExampleTest : PageTest
2022-07-19 00:39:01 +03:00
{
2022-09-14 23:44:38 +03:00
[Test]
2024-05-02 13:06:39 +03:00
public async Task HasTitle()
2022-07-19 00:39:01 +03:00
{
await Page.GotoAsync("https://playwright.dev");
// Expect a title "to contain" a substring.
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
2024-05-02 13:06:39 +03:00
}
2022-07-19 00:39:01 +03:00
2024-05-02 13:06:39 +03:00
[Test]
public async Task GetStartedLink()
{
await Page.GotoAsync("https://playwright.dev");
2022-07-19 00:39:01 +03:00
// Click the get started link.
2024-05-02 13:06:39 +03:00
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
2022-07-19 00:39:01 +03:00
2023-08-01 23:04:04 +03:00
// Expects page to have a heading with the name of Installation.
2024-05-02 13:06:39 +03:00
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
}
2022-07-19 00:39:01 +03:00
}
```
< / TabItem >
< TabItem value = "mstest" >
2024-01-31 19:49:01 +03:00
```csharp title="UnitTest1.cs"
2022-07-19 00:39:01 +03:00
using System.Text.RegularExpressions;
2022-12-19 18:28:17 +03:00
using System.Threading.Tasks;
using Microsoft.Playwright;
2022-07-19 00:39:01 +03:00
using Microsoft.Playwright.MSTest;
2022-12-19 18:28:17 +03:00
using Microsoft.VisualStudio.TestTools.UnitTesting;
2022-07-19 00:39:01 +03:00
namespace PlaywrightTests;
2022-08-19 15:19:34 +03:00
[TestClass]
2024-05-02 13:06:39 +03:00
public class ExampleTest : PageTest
2022-07-19 00:39:01 +03:00
{
2022-09-14 23:44:38 +03:00
[TestMethod]
2024-05-02 13:06:39 +03:00
public async Task HasTitle()
2022-07-19 00:39:01 +03:00
{
await Page.GotoAsync("https://playwright.dev");
// Expect a title "to contain" a substring.
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
2024-05-02 13:06:39 +03:00
}
2022-07-19 00:39:01 +03:00
2024-05-02 13:06:39 +03:00
[TestMethod]
public async Task GetStartedLink()
{
await Page.GotoAsync("https://playwright.dev");
2022-07-19 00:39:01 +03:00
// Click the get started link.
2024-05-02 13:06:39 +03:00
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
2022-07-19 00:39:01 +03:00
2024-05-02 13:06:39 +03:00
// Expects page to have a heading with the name of Installation.
await Expect(Page.GetByRole(AriaRole.Heading, new() { Name = "Installation" })).ToBeVisibleAsync();
}
2022-07-19 00:39:01 +03:00
}
```
< / TabItem >
< / Tabs >
2024-05-02 13:06:39 +03:00
## Actions
2022-07-19 00:39:01 +03:00
2024-05-02 13:06:39 +03:00
### Navigation
Most of the tests will start by navigating the page to a URL. After that, the test
will be able to interact with the page elements.
2022-07-19 00:39:01 +03:00
```csharp
2024-05-02 13:06:39 +03:00
await Page.GotoAsync("https://playwright.dev");
2022-07-19 00:39:01 +03:00
```
2024-05-02 13:06:39 +03:00
Playwright will wait for the page to reach the load state prior to moving forward.
Learn more about the [`method: Page.goto`] options.
2022-07-19 00:39:01 +03:00
2024-05-02 13:06:39 +03:00
### Interactions
Performing actions starts with locating the elements. Playwright uses [Locators API ](./locators.md ) for that. Locators represent a way to find element(s) on the page at any moment, learn more about the [different types ](./locators.md ) of locators available. Playwright will wait for the element to be [actionable ](./actionability.md ) prior to performing the action, so there is no need to wait for it to become available.
2022-07-19 00:39:01 +03:00
```csharp
2024-05-02 13:06:39 +03:00
// Create a locator.
2022-11-30 07:56:18 +03:00
var getStarted = Page.GetByRole(AriaRole.Link, new() { Name = "Get started" });
2022-07-19 00:39:01 +03:00
2024-05-02 13:06:39 +03:00
// Click it.
2022-07-19 00:39:01 +03:00
await getStarted.ClickAsync();
```
2024-05-02 13:06:39 +03:00
In most cases, it'll be written in one line:
```csharp
await Page.GetByRole(AriaRole.Link, new() { Name = "Get started" }).ClickAsync();
```
### Basic actions
This is the list of the most popular Playwright actions. Note that there are many more, so make sure to check the [Locator API ](./api/class-locator.md ) section to
learn more about them.
| Action | Description |
| :- | :- |
| [`method: Locator.check`] | Check the input checkbox |
| [`method: Locator.click`] | Click the element |
| [`method: Locator.uncheck`] | Uncheck the input checkbox |
| [`method: Locator.hover`] | Hover mouse over the element |
| [`method: Locator.fill`] | Fill the form field, input text |
| [`method: Locator.focus`] | Focus the element |
| [`method: Locator.press`] | Press single key |
| [`method: Locator.setInputFiles`] | Pick files to upload |
| [`method: Locator.selectOption`] | Select option in the drop down |
## Assertions
Playwright provides an async function called [Expect ](./test-assertions ) to assert and wait until the expected condition is met.
```csharp
await Expect(Page).ToHaveTitleAsync(new Regex("Playwright"));
```
Here is the list of the most popular async assertions. Note that there are [many more ](./test-assertions.md ) to get familiar with:
| Assertion | Description |
| :- | :- |
| [`method: LocatorAssertions.toBeChecked`] | Checkbox is checked |
| [`method: LocatorAssertions.toBeEnabled`] | Control is enabled |
| [`method: LocatorAssertions.toBeVisible`] | Element is visible |
| [`method: LocatorAssertions.toContainText`] | Element contains text |
| [`method: LocatorAssertions.toHaveAttribute`] | Element has attribute |
| [`method: LocatorAssertions.toHaveCount`] | List of elements has given length |
| [`method: LocatorAssertions.toHaveText`] | Element matches text |
| [`method: LocatorAssertions.toHaveValue`] | Input element has value |
| [`method: PageAssertions.toHaveTitle`] | Page has title |
| [`method: PageAssertions.toHaveURL`] | Page has URL |
## Test Isolation
2022-07-19 00:39:01 +03:00
The Playwright NUnit and MSTest test framework base classes will isolate each test from each other by providing a separate `Page` instance. Pages are isolated between tests due to the Browser Context, which is equivalent to a brand new browser profile, where every test gets a fresh environment, even when multiple tests run in a single Browser.
< Tabs
2022-08-03 14:39:18 +03:00
groupId="test-runners"
2024-06-11 16:06:03 +03:00
defaultValue="mstest"
2022-07-19 00:39:01 +03:00
values={[
2024-06-11 16:06:03 +03:00
{label: 'MSTest', value: 'mstest'},
2022-07-19 00:39:01 +03:00
{label: 'NUnit', value: 'nunit'},
]
}>
< TabItem value = "nunit" >
2024-01-31 19:49:01 +03:00
```csharp title="UnitTest1.cs"
2022-07-19 00:39:01 +03:00
using System.Threading.Tasks;
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
namespace PlaywrightTests;
[Parallelizable(ParallelScope.Self)]
2022-09-08 02:44:58 +03:00
[TestFixture]
2024-05-02 13:06:39 +03:00
public class ExampleTest : PageTest
2022-07-19 00:39:01 +03:00
{
2022-09-14 23:44:38 +03:00
[Test]
2022-07-19 00:39:01 +03:00
public async Task BasicTest()
{
await Page.GotoAsync("https://playwright.dev");
}
}
```
< / TabItem >
< TabItem value = "mstest" >
2024-01-31 19:49:01 +03:00
```csharp title="UnitTest1.cs"
2022-12-19 18:28:17 +03:00
using System.Threading.Tasks;
2022-07-19 00:39:01 +03:00
using Microsoft.Playwright.MSTest;
2022-12-19 18:28:17 +03:00
using Microsoft.VisualStudio.TestTools.UnitTesting;
2022-07-19 00:39:01 +03:00
namespace PlaywrightTests;
2022-08-19 15:19:34 +03:00
[TestClass]
2024-05-02 13:06:39 +03:00
public class ExampleTest : PageTest
2022-07-19 00:39:01 +03:00
{
2022-09-14 23:44:38 +03:00
[TestMethod]
2022-07-19 00:39:01 +03:00
public async Task BasicTest()
{
await Page.GotoAsync("https://playwright.dev");
}
}
```
< / TabItem >
< / Tabs >
2024-05-02 13:06:39 +03:00
## Using Test Hooks
2022-07-19 00:39:01 +03:00
You can use `SetUp` /`TearDown` in NUnit or `TestInitialize` /`TestCleanup` in MSTest to prepare and clean up your test environment:
< Tabs
2022-08-03 14:39:18 +03:00
groupId="test-runners"
2024-06-11 16:06:03 +03:00
defaultValue="mstest"
2022-07-19 00:39:01 +03:00
values={[
2024-06-11 16:06:03 +03:00
{label: 'MSTest', value: 'mstest'},
2022-07-19 00:39:01 +03:00
{label: 'NUnit', value: 'nunit'},
]
}>
< TabItem value = "nunit" >
2024-01-31 19:49:01 +03:00
```csharp title="UnitTest1.cs"
2022-07-19 00:39:01 +03:00
using System.Threading.Tasks;
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
namespace PlaywrightTests;
[Parallelizable(ParallelScope.Self)]
2022-09-08 02:44:58 +03:00
[TestFixture]
2024-05-02 13:06:39 +03:00
public class ExampleTest : PageTest
2022-07-19 00:39:01 +03:00
{
2022-09-14 23:44:38 +03:00
[Test]
2022-07-19 00:39:01 +03:00
public async Task MainNavigation()
{
// Assertions use the expect API.
await Expect(Page).ToHaveURLAsync("https://playwright.dev/");
}
[SetUp]
public async Task SetUp()
{
await Page.GotoAsync("https://playwright.dev");
}
}
```
< / TabItem >
< TabItem value = "mstest" >
2024-01-31 19:49:01 +03:00
```csharp title="UnitTest1.cs"
2022-12-19 18:28:17 +03:00
using System.Threading.Tasks;
2022-07-19 00:39:01 +03:00
using Microsoft.Playwright.MSTest;
2022-12-19 18:28:17 +03:00
using Microsoft.VisualStudio.TestTools.UnitTesting;
2022-07-19 00:39:01 +03:00
namespace PlaywrightTests;
2022-08-19 15:19:34 +03:00
[TestClass]
2024-05-02 13:06:39 +03:00
public class ExampleTest : PageTest
2022-07-19 00:39:01 +03:00
{
2022-09-14 23:44:38 +03:00
[TestMethod]
2022-07-19 00:39:01 +03:00
public async Task MainNavigation()
{
// Assertions use the expect API.
await Expect(Page).ToHaveURLAsync("https://playwright.dev/");
}
[TestInitialize]
public async Task TestInitialize()
{
await Page.GotoAsync("https://playwright.dev");
}
}
```
< / TabItem >
< / Tabs >
## What's Next
2022-10-21 19:52:36 +03:00
- [Run single test, multiple tests, headed mode ](./running-tests.md )
2024-05-08 23:55:44 +03:00
- [Generate tests with Codegen ](./codegen-intro.md )
2023-03-06 22:52:58 +03:00
- [See a trace of your tests ](./trace-viewer-intro.md )
2024-05-02 13:06:39 +03:00
- [Run tests on CI ](./ci-intro.md )
2024-06-11 16:06:03 +03:00
- [Learn more about the MSTest and NUnit base classes ](./test-runners.md )