Part 2: Automation Tests with Playwright .Net
Welcome to the second part of this series, and I hope you were able to follow the first. If you have any questions or suggestions, kindly leave a comment so that we may all learn from this experience. In the last article, we were able to navigate to a page and assert its title. The objective of this article is to explain and modify the code. Let's dive in and complete the login process.
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Playwright;
using Microsoft.Playwright.NUnit;
using NUnit.Framework;
namespace PlaywrightTests;
public class OrangeHrm : PageTest
{
[Test]
public async Task LoginTest()
{
await Page.GotoAsync("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
await Expect(Page).ToHaveTitleAsync(new Regex("OrangeHRM"));
await Page.Locator("input[name='username']").FillAsync("Admin");
await Page.Locator("input[name='password']").FillAsync("admin123");
await Page.Locator("button[type='submit']").ClickAsync();
await Expect(Page).ToHaveURLAsync(new Regex(".*dashboard"));
}
}
Step 1: Import all necessary directives for use in the application. These provide users with access to a variety of functions, including classes, methods, and asynchronous programming, among others.
Step 2: namespace ScopeName
is mostly used to organise code to avoid name conflicts and to put related classes and functionality together.
Step 3: public class OrangeHrm : PageTest
is used to define a public class named OrangeHrm, which inherits all of PageTest's functionality. There are four base MSTest classes: PageTest
, ContextTest
, BrowserTest
and PlaywrightTests
, check out more information here.
Step 4: [Test]
indicates what should be executed; that is, the code within the test method will be treated as a testcase.
Step 5: public async Task LoginTest()
is an asynchronous function that defines the LoginTest. This is where all of the testcase's steps are written.
Now that we've completed the login page, let's do some cleaning up. The first step will be to construct a page class file that will include the locators and call it from the UnitTest.cs file.
For the time being, there is no need to establish a folder and then add a file to it; this will be done in future iterations. So let's create a file called LoginPage.cs in the root directory.
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Playwright;
namespace PlaywrightTests.Pages
{
public class LoginPage
{
private readonly IPage _page;
public LoginPage(IPage page)
{
_page = page;
}
public async Task NavigateToLoginPage()
{
await _page.GotoAsync("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
}
public async Task PerformLogin(string username, string password)
{
await _page.Locator("input[name='username']").FillAsync(username);
await _page.Locator("input[name='password']").FillAsync(password);
await _page.Locator("button[type='submit']").ClickAsync();
}
public async Task VerifyPageTitle()
{
await Assertions.Expect(_page).ToHaveTitleAsync(new Regex("OrangeHRM"));
}
public async Task VerifyDashboardUrl()
{
await Assertions.Expect(_page).ToHaveURLAsync(new Regex(".*dashboard"));
}
}
}
IPage
is a page interface offered by Playwright, and we declare _page
to be of this type in order to gain access to all features such as click. Then we have a constructor class called LoginPage
that takes IPage
and page
as the arguments and finally assigns page
to _page
. Furthermore, separate methods are defined to accomplish specific actions. It is vital to notice that if the page file contains an assertion,Assertions.Expect
should be used instead of Expect
.
And the update in the UnitTest.cs should be like this;
using NUnit.Framework;
using Microsoft.Playwright;
using Microsoft.Playwright.NUnit;
using PlaywrightTests.Pages;
namespace PlaywrightTests
{
[TestFixture]
public class OrangeHrm : PageTest
{
[Test]
public async Task LoginTest()
{
var loginPage = new LoginPage(Page);
await loginPage.NavigateToLoginPage();
await loginPage.VerifyPageTitle();
await loginPage.PerformLogin("Admin", "admin123");
await loginPage.VerifyDashboardUrl();
await Page.PauseAsync();
}
}
}
The first thing we need to do is to call the page file in the UnitTest.cs file using PlaywrightTests.Pages;
and it should be noted that this is the same namespace given in the page file. This namespace in the page file can be named anything; however, the name in the page file must match the name in the run file.
[TestFixture]
is an attribute in NUnit used to mark a class that contains tests for run and setup methods.
public class OrangeHrm : PageTest
- We are creating a public class called OrangeHrm that inherits all of the PageTests
properties. The reason for this is because we want to have the setup and teardown logic available from PageTest rather than going down the rabbit hole of customising the logic. An example will be that PageTest
allows you to write a test that automatically open a browser.
public async Task LoginTest()
creates a class named LoginTest that contains the login test steps, and this is an asynchronous method.
var loginPage = new LoginPage(Page)
is creating a new instance of LoginPage
that would be accessed by loginPage
. With this, any public method in the LoginPage file can be accessed in this new file.
For example we have a NavigateToLoginPage()
method in the LoginPage class, this function can now be accessed using the dot notation by await loginPage.NavigateToLoginPage()
.
We've reached the conclusion of this step; more cleanups will be performed using a data-driven method, and I know it will be intriguing!
Bye for now.
Subscribe to my newsletter
Read articles from Onyedikachi Hope Amaechi-Okorie directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Onyedikachi Hope Amaechi-Okorie
Onyedikachi Hope Amaechi-Okorie
Senior Quality Engineer with experience in creating and monitoring manual and automated test suites for web and mobile applications.