Continuing walking through Butch Mayhew's LinkedIn Learning course Playwright Essential Training: Abstractions, Fixtures, and Complex Scenarios, we will be examining his code creating a DataFactory that dynamically generates new registered users for our app under test.
The app we will be testing against is PracticeSoftwareTesting.com. examining how the registration call in the API creates new users. We will also be mimicking this call at a programmatic level, to be used in a Playwright automation framework.
According to Butch Mayhew, in his there are two types of data we use in our tests: static, and dynamic:
Static data that should never change. Already exists before the test.
- Example: Your go-to test user, or your go to product when testing a shopping cart.
Dynamic Data: Data that is created as part of a test.
- Newly registered users. Products created as part of a test.
Between static and dynamic data, Butch believes it should be around 15% / 85% split.
You can dynamically generate data, such as registering new users, by implementing a Datafactory, a helper function that interacts with a system to create this data for you.
Step One: Write A Registration Test
On my local computer, I cloned Butch Mayhew's companion GitHub site for his LinkedIn Learning site, checking out branch 01_05b, the section he was covering in his course.
Microsoft VS Code is the IDE (Integrated Development Environment) we will be using. If you install the Microsoft Playwright VS Code extension, you see on the right hand sidebar for VS Code, an icon that looks like a beaker. Clicking on that, you can see more options such as "Record new", a way to record a new test.
- Visual Studio Code: https://code.visualstudio.com/
- Visual Studio Marketplace: Playwright Test for VS Code.
- Playwright.dev Docs: Getting Started / VS Code
When I clicked on "Record new", following along with the video in the course, it opened up a new test-1.spec.ts file. A new browser window is opened. When I went to https://www.practicesoftwaretesting.com/auth/register and filled out the Registration form, every click, every piece of data filled in was captured in the test.
test('test', async ({ page }) => {
await page.goto('https://www.practicesoftwaretesting.com/auth/register');
await page.getByTestId('first-name').fill('Test');
await page.getByTestId("last-name").fill("Tester");
await page.getByTestId('country').selectOption('US');
await page.getByTestId('postal_code').fill('555555');
await page.getByTestId('street').fill('101 Testing Way');
await page.getByTestId('city').fill('New York');
await page.getByTestId('state').fill('New York');
await page.getByText('First nameLast nameDate of').click();
await page.getByTestId('email').fill('testlinkedinlearning@test.com');
await page.getByTestId('password').fill('Pass$w0rd1');
await page.getByTestId('register-form').getByRole('button').filter({ hasText: /^$/ }).click();
await page.getByTestId('phone').fill('5555555555');
await page.getByTestId('dob').fill('2001-01-01');
await page.getByTestId('house_number').fill('42');
await page.getByTestId('register-submit').click();
});
Step Two: Open the Playwright UI Mode
Before rerunning this test in UI mode, since a condition for registered users is that all emails should be unique, I made the email address "testlinkedinlearning01@test.com".
- Open the Playwright Test UI: npx playwright test --ui
... This command opened up a new Playwright Test browser window showing in the left-hand sidebar all tests in the test suite, including the test-2.spec.ts one that was autogenerated for me.
According to Playwright.dev Docs: Test UI Mode "Once you launch UI Mode you will see a list of all your test files. You can run all your tests by clicking the triangle icon in the sidebar. You can also run a single test file, a block of tests or a single test by hovering over the name and clicking on the triangle next to it".
Step Three: Examine the Register API Call
Want to see what API calls the registration is running?
According to the Playwright Docs / UI Mode / Network, "The Network tab shows you all the network requests that were made during your test. You can sort by different types of requests, status code, method, request, content type, duration and size. Click on a request to see more information about it such as the request headers, response headers, request body and response body".
Select the "Network" tab, just as in Google Chrome Developer tools, and you will see everything, including the POST API call, "register", which posts the data to /users/register endpoint. .
Select the "register" call. If you take a look at the Payload, you can see:
{
"first_name": "Test",
"last_name": "Tester",
"dob": "2001-01-01",
"phone": "5555555555",
"email": "testlinkedinlearning@test.com",
"password": "Pass$w0rd1",
"address": {
"street": "101 Testing Way",
"city": "New York",
"state": "New York",
"country": "US",
"postal_code": "555555"
}
}Step Four: Copy Request As Playwright
If you scroll to the right, you will see the option "Copy request". Choose the dropdown option, "Copy as Playwright", and you get the following code:
await page.request.post('https://api.practicesoftwaretesting.com/users/register', {
data: `{
"first_name": "Test",
"last_name": "Tester",
"dob": "2001-01-01",
"phone": "5555555555",
"email": "testlinkedinlearning01@test.com",
"password": "Pass$w0rd1",
"address": {
"street": "101 Testing Way",
"city": "New York",
"state": "New York",
"country": "US",
"postal_code": "555555"
}
}`,
headers: {
'sec-ch-ua-platform': '"Windows"',
Referer: 'https://www.practicesoftwaretesting.com/',
'Accept-Language': 'en-US',
'sec-ch-ua': '"HeadlessChrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147"',
'sec-ch-ua-mobile': '?0',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.7727.15 Safari/537.36',
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json'
}
}); - Read More at Butch's website, Playwright Solutions: TIP: Playwright Trace Viewer - Copy as Playwright API Request
Step Five: Start Reformatting the DataFactory Code
Butch mentioned that we can take this information to create our Datafactory. Butch created a new file, lib/datafactory/register.ts, pasting the contents there, to start it off.
Since Butch was extracting the data in its own file, he had to do some refactoring:
- Deleted the headers. We didn't need that information for this example.
- Imported the "request" fixture from @playwright/test.
- Initialized the request, with a "const createRequestContext = await request.newContext()
- Switched the "page.request.post" to "createRequestContext.post"
- Removed the string off of the object, removing the quotation marks from each variable to make it less JSON and more JavaScript.
Step Six: Add API_URL to Environment File
Butch then took the API, https://api.practicesoftwaretesting.com/users/register, to "/users/register" and created a new variable, const apiUrl = process.env.API_URL.
- Read More on Playwright.dev: Passing Environment Variables
Butch added the new variable to the .env file in the root directory:
- API_URL=https://api.practicesoftwaretesting.com
Step Seven: Parameterize the Email and Password
Right now, it is still static. In order to make it dynamic, Butch set email and password to a variable, then wrapped it in a function, with:
- export async function registerUser(email: string, password: string)
- Import expect from @playwright/test.
- expect(response.status()).toBe(201)
- Made the entire await block a "const response".
- Returned the response so you know what it is in the test: return response.status().
import { request, expect } from "@playwright/test";
export async function registerUser(email: string, password: string) {
const apiUrl = process.env.API_URL;
const createRequestContext = await request.newContext();
const response = await createRequestContext.post(apiUrl + "/users/register", {
data: {
first_name: "Test",
last_name: "User",
dob: "2001-01-01",
phone: "5555555555",
email: email,
password: password,
address: {
street: "101 Testing Way",
city: "New York",
state: "New York",
country: "US",
postal_code: "55555",
},
},
});
expect(response.status()).toBe(201);
return response.status();
}
lib/datafactory/register.ts Now, every time you need to create a new user, you can import the function, registerUser, passing along an email and a password, and new test user will be generated.
Need to make something dynamic? Butch appended to the email address, Date.now, so it would be unique as long as the test was not run in the same second:
- const email = `test${Date.now()}@test.com
login.spec.ts
import { registerUser } from "@datafactory/register";
test("login with newly registered user", async ({ page }) => {
const email = `test${Date.now()}@test.com`;
const password = "fjdWEdfs82@";
await registerUser(email, password);
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login(email, password);
await expect(page.getByTestId("nav-menu")).toContainText("Test User");
await expect(page.getByTestId("page-title")).toContainText("My account");
});
/tests/login/login.spec.tsNow, you have your very own DataFactory!
No comments:
Post a Comment