C#-Playwright

Playwright C# Test Automation Project Structure

Here’s a detailed project structure for a UI and API testing framework using C#, Playwright, and the Page Object Model (POM), incorporating the additional tools and files like Utilities, GitHub workflows, and templates.


Project Structure

PlaywrightTestingFramework/
│
├── .github/
│   ├── CODEOWNERS
│   ├── workflows/
│   │   └── nightly-build.yml
│   └── PULL_REQUEST_TEMPLATE.md
│
├── src/
│   ├── Pages/
│   │   ├── BasePage.cs
│   │   ├── HomePage.cs
│   │   ├── LoginPage.cs
│   │   └── APIPage.cs
│   │
│   ├── Utilities/
│   │   ├── CommonHelpers.cs
│   │   ├── ConfigReader.cs
│   │   └── Logger.cs
│   │
│   ├── Tests/
│   │   ├── UI/
│   │   │   ├── LoginTests.cs
│   │   │   └── HomeTests.cs
│   │   ├── API/
│   │       └── APITests.cs
│   │
│   ├── Drivers/
│   │   └── BrowserFactory.cs
│   │
│   ├── Config/
│   │   └── appsettings.json
│   │
│   └── Program.cs
│
├── .gitignore
├── README.md
├── PlaywrightTestingFramework.sln
└── PlaywrightTestingFramework.csproj

Key Files and Examples

1. .github/CODEOWNERS

# Assign code reviewers/owners
* @team-lead @qa-engineer

2. .github/PULL_REQUEST_TEMPLATE.md

# Pull Request Template

## Description
Describe the changes made in this PR.

## Checklist
- [ ] Code compiles successfully.
- [ ] All tests pass.
- [ ] Code is properly documented.

## Linked Issues
Closes #[issue-number].

3. .github/workflows/nightly-build.yml

name: Nightly Build

on:
  schedule:
    - cron: '0 0 * * *'
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v3

    - name: Setup .NET
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: '7.0'

    - name: Install dependencies
      run: dotnet restore

    - name: Run tests
      run: dotnet test --logger:trx

4. Utilities Files

  • CommonHelpers.cs
public static class CommonHelpers
{
    public static string GenerateRandomString(int length)
    {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        return new string(Enumerable.Repeat(chars, length).Select(s => s[new Random().Next(s.Length)]).ToArray());
    }
}
  • ConfigReader.cs
public static class ConfigReader
{
    public static string GetConfigValue(string key)
    {
        return File.ReadAllText("Config/appsettings.json")[key];
    }
}

5. Page Object Files

  • BasePage.cs
public class BasePage
{
    protected readonly IPage page;

    public BasePage(IPage page)
    {
        this.page = page;
    }
}
  • LoginPage.cs
public class LoginPage : BasePage
{
    private string usernameInput = "#username";
    private string passwordInput = "#password";
    private string loginButton = "#login";

    public LoginPage(IPage page) : base(page) { }

    public async Task Login(string username, string password)
    {
        await page.FillAsync(usernameInput, username);
        await page.FillAsync(passwordInput, password);
        await page.ClickAsync(loginButton);
    }
}

6. Driver Setup

  • BrowserFactory.cs
public class BrowserFactory
{
    public static async Task<IPage> LaunchBrowser(string browserName)
    {
        var playwright = await Playwright.CreateAsync();

        IBrowser browser = browserName.ToLower() switch
        {
            "chrome" => await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = true }),
            "firefox" => await playwright.Firefox.LaunchAsync(new BrowserTypeLaunchOptions { Headless = true }),
            "edge" => await playwright.Chromium.LaunchPersistentContextAsync("user-data-dir"),
            "safari" => await playwright.Webkit.LaunchAsync(new BrowserTypeLaunchOptions { Headless = true }),
            _ => throw new ArgumentException("Unsupported browser type"),
        };

        return await browser.NewPageAsync();
    }
}

7. Tests

  • LoginTests.cs
[TestClass]
public class LoginTests
{
    private IPage page;

    [TestInitialize]
    public async Task Setup()
    {
        page = await BrowserFactory.LaunchBrowser("chrome");
    }

    [TestMethod]
    public async Task LoginWithValidCredentials()
    {
        var loginPage = new LoginPage(page);
        await loginPage.Login("testuser", "password");
        Assert.IsTrue(await page.IsVisibleAsync("#welcomeMessage"));
    }

    [TestCleanup]
    public async Task Teardown()
    {
        await page.CloseAsync();
    }
}
  • APITests.cs
[TestClass]
public class APITests
{
    private HttpClient httpClient;

    [TestInitialize]
    public void Setup()
    {
        httpClient = new HttpClient();
    }

    [TestMethod]
    public async Task GetRequestTest()
    {
        var response = await httpClient.GetAsync("https://api.example.com/data");
        Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
    }
}

8. appsettings.json

{
  "BaseUrl": "https://example.com",
  "Username": "testuser",
  "Password": "password"
}

9. README.md

# Playwright Testing Framework

## Overview
This is a C# testing framework using Playwright for both UI and API testing, designed with the Page Object Model for reusability and maintainability.

## Features
- Cross-browser testing (Chrome, Firefox, Edge, Safari).
- API and UI testing in one framework.
- GitHub Actions for CI/CD.

## Setup
1. Clone the repository.
2. Install dependencies: `dotnet restore`.
3. Run tests: `dotnet test`.

## Folder Structure
- `Pages`: Contains POM files for UI testing.
- `Utilities`: Common helper functions.
- `Tests`: Contains test scripts for UI and API.

This project structure is modular, reusable, and integrates CI/CD, ensuring best practices for test automation!