This content originally appeared on Twilio Blog and was authored by Néstor Campos
Testing your applications is a fundamental part of any project, whether it is to find errors during development, or to verify the expected behavior of your application in each action that a user may or may not execute.
In this post, you are going to use a simple form and test it using Playwright and C# to verify its operation with both correct and incorrect information, simulating the actions of users.
Prerequisites
You will need the following for your development environment:
- a .NET IDE (Visual Studio, VS Code with C# plugin, JetBrains Rider, or any editor of your choice)
- .NET 6 SDK (earlier and newer versions should work too)
- Git CLI
- NUnit
- PowerShell
Test types
You can create different types of tests to verify your software:
- Unit tests test individual methods and functions of the classes, components, or modules your software uses.
- Integration tests verify that the different modules or services used by your application work well together.
- End-to-End (E2E) tests verify that your application works as expected from a user perspective by simulating how a user interacts with your application.
For more details on these types of tests and why you should do them, check out "Unit, Integration, and End-to-End Testing: What’s the Difference?".
There are a lot more types of tests, but these the three above are the most common to test your software. You'll be developing E2E tests using Playwright in this tutorial.
What is Playwright?
Playwright is a browser automation framework for testing web applications end-to-end. Playwright takes advantage of the capabilities of current browsers through an intuitive API. It addresses a lot of the pain points that you had to deal with when using older browser automation frameworks.
One of the biggest pain points of using older automation frameworks, is that you had to manually install browsers and their compatible web drivers, but over time the version of the browser would change and become incompatible with the web driver. Thus, you had to find which newer version of the web driver you had to install. And you had to do this for every browser you wanted to run your tests in. Playwright, on the other hand, automatically install the latest browsers for you and Playwright doesn't use web drivers, so you don't have to worry about keeping those in sync.
Because older automation frameworks used web drivers to instruct the web browsers, they were limited by the capabilities offered by the web drivers. Playwright use the Chrome DevTools protocol to communicate with Chromium, Chrome, and Edge browser. For other browsers like WebKit, Safari, and Firefox, Playwright extended the browser to support a similar protocol. This allows Playwright to use the DevTools protocol to efficiently communicate with all these browsers and take advantage of all their features.
In addition to supporting multiple browsers, Playwright has cross-platform and cross-language support with APIs for .NET (C#), TypeScript, JavaScript, Python, and Java.
If you don't want to manually write your tests, you can generate tests using Codegen which will open a browser and record your actions in that browsers. Each recorded action is translated into the Playwright APIs in the programming language of your choice.
You can also record videos of the tests that will allow you to play them back, which can help with figuring out why a test failed. You can also emulate devices and instantiate browsers with properties such as viewport, location, time zone, geolocation, among others.
Set up the sample web app
To get started, you must first clone this GitHub repository, which contains an ASP.NET Core web app with only 3 pages. A home page with a button leading to the form, the form page with 4 fields and some validations that you are going to test, and a success page if the form is completed successfully. While this sample web app is built using ASP.NET Core, it could've been built using any web technology and you'd still be able to write the same E2E tests with Playwright.
Open a terminal and clone the repository with the following command:
git clone https://github.com/nescampos/tdv_testwebapps.git
Then go into the tdv_testwebapps/ContactForm.Web project folder of the cloned repository and run the ASP.NET Core application:
cd tdv_testwebapps/ContactForm.Web
dotnet run
To run the project in VS Code, press Ctrl + F5
and a prompt will be displayed to select the environment, where you must select .NET Core.
The output of the ASP.NET Core application will print one or more localhost URLs where it is hosted. Open a browser and navigate to one of the localhost URLs.. You will see the home page with the button to open the form. Click on the button, fill out the form, and verify that you get to the success screen.
Home page of the sample web app
Contact us page of the sample web app
Contact us success page of the sample web app
You will be testing this application, so leave it running in the background.
Now that you're familiar with the sample web app, let's find out how to test this web app programmatically.
Create the NUnit project
There are many frameworks to test .NET applications, with xUnit, NUnit, and MSTest being the most popular. This tutorial will use NUnit as its testing framework.
Open another terminal and navigate where you cloned the git repository, then create an NUnit project called ContactForm.Tests, and navigate to the new folder:
dotnet new nunit -n ContactForm.Tests
cd ContactForm.Tests
Install the Playwright library
Now, to use Playwright, you must install it as a library in the project. Run this command to add the Playwright NUnit NuGet package:
dotnet add package Microsoft.Playwright.NUnit
The Playwright library requires some extra setup, which is done via a PowerShell script. This is a little odd for a .NET package, but to get the script you first need to build the project, so go ahead and build the project:
dotnet build
Now the Playwright dependency has been copied into your bin folder, and you can run the PowerShell script. Run the installation script like this:
pwsh bin/Debug/net6.0/playwright.ps1 install
Replace net6.0
with your version of .NET if you're not using .NET 6.
This installation script will install Playwright into your project, including the browsers.
Test the web app
Test the home page
Now, with Playwright installed in the NUnit project, you are going to create your first test, in which you will check if there is a button to open the form on the home page and verify that clicking the button navigates the browser to the form page.
Open the test project in your IDE and delete the generated UnitTest1.cs file. To test the home page, create a new file called WebAppTest.cs in the project and copy the following code into the file:
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
[Parallelizable(ParallelScope.Self)]
public class Tests : PageTest
{
[Test]
public async Task Clicking_ContactButton_Goes_To_ContactForm()
{
await Page.GotoAsync("<URL>");
var formButton = Page.Locator("text=Open Contact Form");
await formButton.ClickAsync();
await Expect(Page).ToHaveURLAsync(new Regex(".*Home/Form"));
}
}
Replace `<URL>` with the web app URL.
In the above code, you have just created a test that retrieves the button to open the form, clicks on it, and checks if the next page is the form page based on the current URL.
By default, Playwright will run your code against a browser in headless mode, meaning that the browser will not be visible. To make it easier to debug and see what's actually happening, you can turn off Headless
mode. However, the tests would run so fast that you still can't perceive what is happening, which is why Playwright provides a SlowMo
option that you can use to slow down the steps within your test.
The most flexible way to configure these options, is to use a .runsettings file. .runsettings files are used by all .NET testing frameworks to configure how the tests run, and Playwright added support to configure Playwright using .runsettings files as well.
Create a new file called .runsettings with the following content:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<Playwright>
<BrowserName>chromium</BrowserName>
<LaunchOptions>
<Headless>false</Headless>
<Channel>msedge</Channel>
<SlowMo>500</SlowMo>
</LaunchOptions>
</Playwright>
</RunSettings>
Here's what the configuration means:
BrowserName
lets you pick between thechromium
,firefox
, orwebkit
browser.Headless
is set totrue
by default, but you can set it totrue
so that you can see the browser UI as the test is run.Channel
configures which version of the browser to run. When you pickchromium
as the browser name, you can pickchrome
ormsedge
to use Google Chrome or Microsoft Edge which are both browser built on top of Chromium. You can also choose to test against the beta version and dev version by suffixing the channel with-beta
or-dev
, for examplemsedge-beta
. You can learn more about the supported browsers and channels at the Playwright docs.SlowMo
lets you slow down automation steps by the specified amount of miliseconds.
Now, run the test using the following command:
dotnet test --settings .runsettings
If everything is ok, you will see the browser will open, click on the specified button and then close.
In the console you will see the result of the successful execution of the test, with an output like the following:
Correct! - With error: 0, Pass: 1, Skip: 0, Total: 1, Time: 5 s - ContactFormTests.dll (net6.0)
You can also run tests from VS Code with .runsettings, and Visual Studio, and there are also settings for this in JetBrains Rider.
Test the form
Now, you are going to create a test that fails. In this test, you will enter all the data of the form at another URL correctly, except for the first name, which in the form will be empty, but hoping that the data is valid and you arrive at the page of thanks.
Since the form is in the same web application, but in another URL, you are going to optimize this using a variable where you will store the base of the URL. And instead of hardcoding this variable, you can make the project more flexible by configuring the URL using the .runsettings file.
First, add the WebAppUrl
parameter in the .runsettings file:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<TestRunParameters>
<Parameter name="WebAppUrl" value="<URL>" />
</TestRunParameters>
<Playwright>
<BrowserName>chromium</BrowserName>
<LaunchOptions>
<Headless>false</Headless>
<Channel>msedge</Channel>
<SlowMo>200</SlowMo>
</LaunchOptions>
</Playwright>
</RunSettings>
Replace <URL>
with the web app URL.
Turning off Headless
and using SlowMo
helps for debugging, but turning Headless
on and SlowMo
off will increase the performance of your tests. For local development, it's up to your preference, but in production and CI environments, you should use keep Headless
on and SlowMo
off.
Next, add a method called Init()
, which, unlike the test methods, will have the OneTimeSetUp
attribute to specify that it should be executed once and before the tests. In this method, you are going to get the value of the URL parameter in the configuration file and save it in the variable webAppUrl
. Then use the webAppUrl
variable in the existing test instead of the hard-coded URL. Your code should look like this:
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
[Parallelizable(ParallelScope.Self)]
public class Tests : PageTest
{
public static string webAppUrl;
[OneTimeSetUp]
public void Init()
{
webAppUrl = TestContext.Parameters["WebAppUrl"]
?? throw new Exception("WebAppUrl is not configured as a parameter.");
}
[Test]
public async Task Clicking_ContactButton_Goes_To_ContactForm()
{
await Page.GotoAsync(webAppUrl);
var formButton = Page.Locator("text=Open Contact Form");
await formButton.ClickAsync();
await Expect(Page).ToHaveURLAsync(new Regex(".*Home/Form"));
}
}
Now, create the new test with the following code:
[Test]
public async Task Filling_And_Submitting_ContactForm_Goes_To_SuccessPage()
{
await Page.GotoAsync($"{webAppUrl}/Home/Form");
await Page.Locator("text=First name").FillAsync("");
await Page.Locator("text=Last name").FillAsync("Campos");
await Page.Locator("text=Email address").FillAsync("nestor@gmail.com");
await Page.Locator("text=Birth date").FillAsync("1989-03-16");
await Page.Locator("text=Send").ClickAsync();
await Expect(Page).ToHaveURLAsync(new Regex(".*Home/Success"));
}
This test navigates directly to the form page, then fills out each form input, submits the form, and verifies the submission was succesful by checking current page is the success page.
The text=
locator in the above test will retrieve the labels of the form input, not the form input itself, but because the labels have been correctly linked to the form input using the for
and id
attribute, Playwright fills in the text into the correct inputs.
Playwright supports a lot of different selectors to locate elements, such as CSS selectors, XPath queries, by ID or test ID, etc. In your tests, you've been using the text-selector which finds elements by matching visible text. Playwright recommends using user-facing attributes to select your elements such as the text, since these don't change as often as the underlying DOM structure.
Rerun the tests, but this time, you're just specifying the execution of the new test by filtering the tests by name:
dotnet test --settings .runsettings --filter Filling_And_Submitting_ContactForm_Goes_To_SuccessPage
You will see the browser open, fill in the data and try to send it, but it fails because the name is required and the test expects to hit a success page.
With error! - With error: 1, Pass: 0, Skip: 0, Total: 1, Time: 8 s - ContactFormTests.dll (net6.0)
Fix the value in the first name with a valid name to pass the test:
await Page.Locator("text=First name").FillAsync("Néstor");
And run the same command again which should show this output:
Correct! - With error: 0, Pass: 1, Skip: 0, Total: 1, Time: 5 s - ContactFormTests.dll (net6.0)
Test form validation
Instead of verifying the "happy path" where the form submits successfully, let's test one of the validation errors by not filling out a valid email address.
Add the following test after your existing tests:
[Test]
public async Task Filling_Invalid_Email_Should_Show_ValidationError()
{
await Page.GotoAsync($"{webAppUrl}/Home/Form");
ILocator emailValidationLocator = Page.Locator("text=The Email address field is not a valid e-mail address.");
await Expect(emailValidationLocator).Not.ToBeVisibleAsync();
await Page.Locator("text=Email address").FillAsync("nestorgmail.com");
await Page.Locator("text=Send").ClickAsync();
await Expect(Page).ToHaveURLAsync(new Regex(".*Home/Form"));
await Expect(emailValidationLocator).ToBeVisibleAsync();
}
This test will verify that there's no invalid email address warning present before submitting the form. Then it will enter an invalid email address, submit the form, and verify that the current page is still the form page via URL and also verify that the email validation error message is visible.
Run the following command to run this test:
dotnet test --settings .runsettings --filter Filling_Invalid_Email_Should_Show_ValidationError
You can apply the same techniques to test all variations of validation.
Next Steps
You just wrote some end-to-end tests to verify form functionality using Playwright. You've learned about a couple of Playwright features and how to use the library, but only scratched the surface. I recommend exploring the Playwright documentation to learn more, for example, you can obtain screenshots of each test, to be able to verify or document your tests with images, or even record videos.
Additional resources
Check out the following resources for more information on the topics and tools presented in this tutorial:
Playwright for .NET – This page contains all the information about the requirements and examples with Playwright for .NET.
Playwright GitHub - Code repository on GitHub from Microsoft containing the Playwright project.
Source Code to this tutorial on GitHub - You can find the source code for this project at this GitHub repository. Use it to compare solutions if you run into any issues.
Néstor Campos is a software engineer, tech founder, and Microsoft Most Value Professional (MVP), working on different types of projects, especially with Web applications.
This content originally appeared on Twilio Blog and was authored by Néstor Campos
Néstor Campos | Sciencx (2022-09-19T16:23:48+00:00) How to test web applications with Playwright and C# .NET. Retrieved from https://www.scien.cx/2022/09/19/how-to-test-web-applications-with-playwright-and-c-net/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.