Багатобюджетний тест E2E з Playwright для.NET (Українська (Ukrainian))

Багатобюджетний тест E2E з Playwright для.NET

Thursday, 27 November 2025

//

17 minute read

Playwright є офіційним рішенням Microsoft для сучасної автоматизації навігатора, він пропонує підтримку багатоброма (Rhrome, Firefox, Safari) з одним програмним інтерфейсом, вбудованим зневаджуванням трасування і емуляцією мобільних телефонів. Цей довідник охоплює все від налаштування до складних тестових візерунків, порівнюючи його з PuppeterSrap, щоб допомогти вам обрати правильний інструмент. Якщо вам потрібні лише Rhrome і потрібні простіші налаштування, подумайте про те, як налаштувати програму. PuppeterSap Замість цього, - але, якщо вам потрібен повний тест на перехресті, Playwright - це шлях вперед.

Вступ

Якщо ви прочитали мою статтю про PuppeterSapВи знаєте, що я фанат сучасних інструментів тестування E2E, які не змушують вас роздирати волосся. Playwright заходить.

Playwright - це відповідь Microsoft на проблему автоматизації навігатора, і вони вивчили все, що було раніше. Це схоже на те, що більш амбітний брат PuppeterSap: він робить все, що робить Puppeter, але додає підтримку Firefox і Safari, краще чекає на себе, а також є джерелом інструментів для усування вад, які роблять пошук абсолютного дзюрчання.

У цій статті я покажу вам, як використовувати Playwright для тестування за допомогою Chrome, Firefox і Safari з прикладами коду і практичними шаблонами, якими ви можете скористатися сьогодні.

Навіщо грати прямо над PuppeterSap?

Не зрозумійте мене неправильно. PuppeterSap Це чудово, якщо вам потрібен тільки Хром. Але тут, коли Playwright має сенс:

Проблема з декількома переглядачами

Ваші користувачі не всі використовують Хром. Вони використовують:

  • Chrome/Edge: ~65% користувачів (заснований на хроміумі)
  • Safari: ~20% користувачів (особливо мобільний)
  • Firefox: ~5% користувачів (але часто різне відображення)

Вада, яка з' являється лише у Safari, може втратити 20% ваших потенційних користувачів. За допомогою Playwright ви можете перевірити всі три з однаковим API.

Кращий досвід розробника

graph TB
    subgraph "PuppeteerSharp"
        PS[Chrome Only]
        PS --> PS1[Fast setup]
        PS --> PS2[Simple API]
        PS --> PS3[Chrome DevTools]
    end

    subgraph "Playwright"
        PW[Multi-Browser]
        PW --> PW1[Chrome, Firefox, Safari]
        PW --> PW2[Auto-waiting built-in]
        PW --> PW3[Trace viewer]
        PW --> PW4[Codegen tool]
        PW --> PW5[Better error messages]
    end

    style PW stroke:#00aa00,stroke-width:3px
    style PW1 stroke:#0066cc,stroke-width:2px
    style PW3 stroke:#0066cc,stroke-width:2px
    style PW4 stroke:#0066cc,stroke-width:2px

Переваги ключів

  1. Підтримка багаторядкових комп' ютерів - Тестовий хром, Firefox, Safari з однаковим кодом
  2. Покращена автоматична очікування - Більш надійний за межами коробки, менше невдалих тестів
  3. Перегляд траєкторії - Записати всі сліди виконання тесту для зневаджування
  4. Codegen - Створити тестовий код шляхом взаємодії з вашим сайтом
  5. Перехоплення мережі - Більш потужний, ніж PuppeterSap
  6. Сучасні можливості веб- сайта - Краща підтримка для Тіней DOM, iframes тощо.

Налаштування Playwright для.NET

Встановити Microsoft. Playwright Пакунок NuGet:

dotnet add package Microsoft.Playwright
dotnet add package Microsoft.Playwright.NUnit  # Or use xUnit

Після цього встановіть переглядачі (це звантаження Хром, Firefox, і WebKit):

pwsh bin/Debug/net9.0/playwright.ps1 install

Або на Linux/Mac:

playwright install

Примітка: Перший браузер встановлює звантаження близько 400 Мб. Незмінні оновлення набагато менші.

Ось моя конфігурація тестового проекту:

<PackageReference Include="Microsoft.Playwright" Version="1.48.0" />
<PackageReference Include="Microsoft.Playwright.NUnit" Version="1.48.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

Я використовую xUnit, але Playwright однаково добре працює з NUnit або MSTest... Насправді, Playwright присвятив Інтеграція NUnit з додатковими помічниками.

Створення базового тесту класу

Подібний до PuppeterSap, але з підтримкою багатоброю:

Структура класу

using Microsoft.Playwright;
using Xunit.Abstractions;

namespace Mostlylucid.Test.E2E;

public abstract class PlaywrightTestBase : IAsyncLifetime
{
    protected IPlaywright Playwright = null!;
    protected IBrowser Browser = null!;
    protected IBrowserContext Context = null!;
    protected IPage Page = null!;

    protected readonly ITestOutputHelper Output;
    protected const string BaseUrl = "http://localhost:8080";

    // Override this in derived classes to test different browsers
    protected virtual BrowserType BrowserType => BrowserType.Chromium;

    protected PlaywrightTestBase(ITestOutputHelper output)
    {
        Output = output;
    }

    public async Task InitializeAsync()
    {
        // Create Playwright instance
        Playwright = await Microsoft.Playwright.Playwright.CreateAsync();

        // Launch the specified browser
        Browser = await LaunchBrowserAsync();

        // Create a new context (like an incognito window)
        Context = await Browser.NewContextAsync(new BrowserNewContextOptions
        {
            ViewportSize = new ViewportSize { Width = 1400, Height = 900 },
            IgnoreHTTPSErrors = true
        });

        // Create a new page
        Page = await Context.NewPageAsync();

        // Set default timeout
        Page.SetDefaultTimeout(30000);
    }

    private async Task<IBrowser> LaunchBrowserAsync()
    {
        var options = new BrowserTypeLaunchOptions
        {
            Headless = true, // Set to false for debugging
        };

        return BrowserType switch
        {
            BrowserType.Chromium => await Playwright.Chromium.LaunchAsync(options),
            BrowserType.Firefox => await Playwright.Firefox.LaunchAsync(options),
            BrowserType.Webkit => await Playwright.Webkit.LaunchAsync(options),
            _ => throw new ArgumentException($"Unknown browser type: {BrowserType}")
        };
    }

    public async Task DisposeAsync()
    {
        await Page?.CloseAsync()!;
        await Context?.CloseAsync()!;
        await Browser?.CloseAsync()!;
        Playwright?.Dispose();
    }
}

public enum BrowserType
{
    Chromium,
    Firefox,
    Webkit
}

Чому контексти переглядача?

Помітьте, ми створили Context перед створенням PageЦе концепція Playwright, яку не має PuppeterSap:

  • Контекст = Ізолізований сеанс переглядача (наприклад, режим incognito)
  • Сторінка = Вкладка у цьому контексті

Контексти, за допомогою яких ви зможете:

  • Тестувати з різними сеансами користувача одночасно
  • Встановити різні куки, права доступу або локалі на контекст
  • Повністю згладжені тести (навіть всередині одного переглядача)

Допоміжні методи

// Navigation with better waiting
protected async Task NavigateAsync(string path)
{
    var url = path.StartsWith("http") ? path : $"{BaseUrl}{path}";
    await Page.GotoAsync(url, new PageGotoOptions
    {
        WaitUntil = WaitUntilState.NetworkIdle
    });
}

// Playwright has better built-in waiting, but these are still useful
protected async Task<IElementHandle?> WaitForSelectorAsync(string selector)
{
    try
    {
        return await Page.WaitForSelectorAsync(selector, new PageWaitForSelectorOptions
        {
            State = WaitForSelectorState.Visible
        });
    }
    catch (TimeoutException)
    {
        return null;
    }
}

// Improved element operations with auto-waiting
protected async Task<bool> ElementExistsAsync(string selector)
{
    return await Page.Locator(selector).CountAsync() > 0;
}

protected async Task<string?> GetTextContentAsync(string selector)
{
    var locator = Page.Locator(selector);
    return await locator.TextContentAsync();
}

protected async Task TypeAsync(string selector, string text)
{
    await Page.Locator(selector).FillAsync(text);
}

protected async Task ClickAsync(string selector)
{
    await Page.Locator(selector).ClickAsync();
}

Таємна зброя ошуканців - зброя Playwright

Зверніть увагу на Page.Locator() це відрізняється від PuppeterSap's QuerySelectorЛучники:

  • ЛазіCity in Florida USA - Они не спрашивают в дом до тех пор, пока не используют их.
  • Повторна спроба - Вони автоматично чекають і повторюють дії
  • Строго - Помилка під час пошуку декількох елементів (запуск тестів flacy)
// PuppeteerSharp way (manual waiting)
await Page.WaitForSelectorAsync("#button");
await Page.ClickAsync("#button");

// Playwright way (auto-waiting)
await Page.Locator("#button").ClickAsync(); // Waits automatically!

Тестування декількох переглядачів

Ось де світиться Playwright. Ви можете виконати однакову перевірку у всіх переглядачах:

Використання теорії XUnit для тестів з декількома версіями

public class CrossBrowserTests : PlaywrightTestBase
{
    public CrossBrowserTests(ITestOutputHelper output) : base(output) { }

    [Theory]
    [InlineData(BrowserType.Chromium)]
    [InlineData(BrowserType.Firefox)]
    [InlineData(BrowserType.Webkit)]
    public async Task HomePage_LoadsCorrectly_InAllBrowsers(BrowserType browserType)
    {
        // Override the browser type for this test
        BrowserType = browserType;
        await InitializeAsync();

        // Arrange & Act
        await NavigateAsync("/");

        // Assert
        var title = await Page.TitleAsync();
        Assert.Contains("Mostlylucid", title);

        Output.WriteLine($"✓ Test passed in {browserType}");
    }
}

Специфічні класи навігатора

Або створіть окремі тестові класи для кожного переглядача:

public class ChromiumTests : PlaywrightTestBase
{
    protected override BrowserType BrowserType => BrowserType.Chromium;

    public ChromiumTests(ITestOutputHelper output) : base(output) { }

    [Fact]
    public async Task FilterBar_WorksInChrome()
    {
        await NavigateAsync("/blog");

        await Page.Locator("#LanguageDropDown button").ClickAsync();
        await Page.Locator("#LanguageDropDown li:has-text('Spanish')").ClickAsync();

        var url = Page.Url;
        Assert.Contains("language=es", url);
    }
}

public class FirefoxTests : PlaywrightTestBase
{
    protected override BrowserType BrowserType => BrowserType.Firefox;

    public FirefoxTests(ITestOutputHelper output) : base(output) { }

    [Fact]
    public async Task FilterBar_WorksInFirefox()
    {
        // Same test, different browser!
        await NavigateAsync("/blog");

        await Page.Locator("#LanguageDropDown button").ClickAsync();
        await Page.Locator("#LanguageDropDown li:has-text('Spanish')").ClickAsync();

        var url = Page.Url;
        Assert.Contains("language=es", url);
    }
}

public class SafariTests : PlaywrightTestBase
{
    protected override BrowserType BrowserType => BrowserType.Webkit;

    public SafariTests(ITestOutputHelper output) : base(output) { }

    [Fact]
    public async Task FilterBar_WorksInSafari()
    {
        await NavigateAsync("/blog");

        await Page.Locator("#LanguageDropDown button").ClickAsync();
        await Page.Locator("#LanguageDropDown li:has-text('Spanish')").ClickAsync();

        var url = Page.Url;
        Assert.Contains("language=es", url);
    }
}

Тести на письмі - правильний шлях

Давайте поглянемо на реальні приклади, що показують переваги Playwright:

Перевірка HTMX у автоматичному очікуванні

[Fact]
public async Task SortingDropdown_UpdatesContentViaHTMX()
{
    // Arrange
    await NavigateAsync("/blog");

    // Get first post title before sorting
    var firstPostBefore = await Page.Locator("article h2 a").First.TextContentAsync();
    Output.WriteLine($"First post before: {firstPostBefore}");

    // Act - Change sort order
    await Page.Locator("#orderSelect").SelectOptionAsync("date_asc");

    // Playwright automatically waits for HTMX to update the DOM!
    await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);

    // Assert - Content should have changed
    var firstPostAfter = await Page.Locator("article h2 a").First.TextContentAsync();
    Output.WriteLine($"First post after: {firstPostAfter}");

    var selectValue = await Page.Locator("#orderSelect").InputValueAsync();
    Assert.Equal("date_asc", selectValue);
}

Перевірка взаємодії між альпійськими.js

Керування Playwright Альпійський.js реагентність і анімація безперешкодно:

[Fact]
public async Task AlpineDropdown_OpensAndCloses()
{
    await NavigateAsync("/blog");

    // Click to open dropdown (Alpine.js controlled)
    await Page.Locator("#LanguageDropDown button").ClickAsync();

    // Wait for Alpine.js animation
    await Page.WaitForSelectorAsync("#LanguageDropDown div[x-show]", new()
    {
        State = WaitForSelectorState.Visible
    });

    // Check dropdown is visible
    var isVisible = await Page.Locator("#LanguageDropDown div[x-show]").IsVisibleAsync();
    Assert.True(isVisible);

    // Click outside to close
    await Page.Locator("body").ClickAsync(new LocatorClickOptions
    {
        Position = new Position { X = 0, Y = 0 }
    });

    // Verify closed
    await Page.WaitForSelectorAsync("#LanguageDropDown div[x-show]", new()
    {
        State = WaitForSelectorState.Hidden
    });

    isVisible = await Page.Locator("#LanguageDropDown div[x-show]").IsVisibleAsync();
    Assert.False(isVisible);
}

Перевірка форм з перевіркум

[Fact]
public async Task CommentForm_ValidatesRequiredFields()
{
    await NavigateAsync("/blog/some-post");

    // Try to submit without filling fields
    await Page.Locator("#comment-submit").ClickAsync();

    // Check HTML5 validation messages
    var nameInput = Page.Locator("#comment-name");
    var validationMessage = await nameInput.EvaluateAsync<string>("el => el.validationMessage");

    Assert.NotEmpty(validationMessage);
    Output.WriteLine($"Validation message: {validationMessage}");

    // Fill form properly
    await nameInput.FillAsync("Test User");
    await Page.Locator("#comment-email").FillAsync("test@example.com");
    await Page.Locator("#comment-content").FillAsync("Great article!");

    // Submit
    await Page.Locator("#comment-submit").ClickAsync();

    // Wait for success
    await Page.Locator(".comment-success").WaitForAsync();
}

Додаткові можливості відтворення

Перев' язання мережі - потужніше за PuppeterSap

[Fact]
public async Task PageLoadsWithoutImages_ToTestPerformance()
{
    // Block all image requests
    await Page.RouteAsync("**/*.{png,jpg,jpeg,gif,webp}", route => route.AbortAsync());

    await NavigateAsync("/blog");

    // Page should still function without images
    var title = await Page.Locator("h1").TextContentAsync();
    Assert.NotEmpty(title);
}

[Fact]
public async Task MockAPIResponse_ForTesting()
{
    // Intercept API calls and return mock data
    await Page.RouteAsync("**/api/posts", route => route.FulfillAsync(new()
    {
        Status = 200,
        ContentType = "application/json",
        Body = System.Text.Json.JsonSerializer.Serialize(new
        {
            posts = new[]
            {
                new { id = 1, title = "Mock Post 1" },
                new { id = 2, title = "Mock Post 2" }
            }
        })
    }));

    await NavigateAsync("/blog");

    // Should show mock data
    var posts = await Page.Locator(".post-title").CountAsync();
    Assert.Equal(2, posts);
}

Переглядач траєкторії - зневаджування зазнало невдачі

public async Task InitializeAsync()
{
    Playwright = await Microsoft.Playwright.Playwright.CreateAsync();
    Browser = await LaunchBrowserAsync();

    // Start tracing
    Context = await Browser.NewContextAsync();
    await Context.Tracing.StartAsync(new()
    {
        Screenshots = true,
        Snapshots = true,
        Sources = true
    });

    Page = await Context.NewPageAsync();
}

public async Task DisposeAsync()
{
    // Save trace on test completion
    var tracePath = Path.Combine("traces", $"{TestContext.TestName}.zip");
    await Context.Tracing.StopAsync(new()
    {
        Path = tracePath
    });

    // View trace with: playwright show-trace traces/TestName.zip

    await Page?.CloseAsync()!;
    await Context?.CloseAsync()!;
    await Browser?.CloseAsync()!;
    Playwright?.Dispose();
}

Потім подивіться на слід:

playwright show-trace traces/TestName.zip

Це відкриває ШІ-шоу:

  • Кожна дія, яку ви зробили тест
  • Знімки вікон на кожному кроці
  • Запити на мережу
  • Журнали консолі
  • Знімки DOM

Це абсолютно блискуче для усування вад.

Знімок вікна про невдалу роботу

public async Task DisposeAsync()
{
    // Take screenshot if test failed
    if (TestContext.CurrentTestOutcome != TestOutcome.Passed)
    {
        var screenshot = await Page.ScreenshotAsync();
        File.WriteAllBytes($"failure-{TestContext.TestName}.png", screenshot);
        Output.WriteLine($"Screenshot saved: failure-{TestContext.TestName}.png");
    }

    await Page?.CloseAsync()!;
    await Context?.CloseAsync()!;
    await Browser?.CloseAsync()!;
    Playwright?.Dispose();
}

Емуляція мобільного

[Fact]
public async Task BlogPage_WorksOnMobile()
{
    // Create context with mobile emulation
    var iPhone = Playwright.Devices["iPhone 13"];
    await using var context = await Browser.NewContextAsync(iPhone);
    await using var page = await context.NewPageAsync();

    await page.GotoAsync($"{BaseUrl}/blog");

    // Check mobile menu is visible
    var mobileMenu = page.Locator(".mobile-menu");
    await Expect(mobileMenu).ToBeVisibleAsync();

    // Desktop menu should be hidden
    var desktopMenu = page.Locator(".desktop-menu");
    await Expect(desktopMenu).Not.ToBeVisibleAsync();
}

З Playwright дескриптори пристрою для:

  • iPhone 13, 13 Pro, 12, 11 SE
  • iPad, iPad Pro
  • Галактика Самсунг, піксель
  • І багато більше

Перевірка темного режиму

[Fact]
public async Task DarkMode_TogglesCorrectly()
{
    // Start with dark color scheme
    await using var context = await Browser.NewContextAsync(new()
    {
        ColorScheme = ColorScheme.Dark
    });
    await using var page = await context.NewPageAsync();

    await page.GotoAsync($"{BaseUrl}");

    // Check dark mode is active
    var isDark = await page.EvaluateAsync<bool>(
        "() => window.matchMedia('(prefers-color-scheme: dark)').matches"
    );
    Assert.True(isDark);

    // Check background color reflects dark mode
    var bgColor = await page.Locator("body").EvaluateAsync<string>(
        "el => getComputedStyle(el).backgroundColor"
    );
    Assert.Contains("rgb(0, 0, 0)", bgColor); // Dark background
}

Playwright vs PuppeterSapher - поручStencils

Ось один і той самий тест у обох бібліотеках, який показує відмінності:

Версія PuppeterSharp

[Fact]
public async Task FilterTest_PuppeteerSharp()
{
    await Page.GoToAsync("http://localhost:8080/blog");

    // Manual waiting required
    await Page.WaitForSelectorAsync("#LanguageDropDown button");
    await Page.ClickAsync("#LanguageDropDown button");

    // Wait for dropdown animation
    await Task.Delay(300);

    // Click Spanish option
    await Page.WaitForSelectorAsync("#LanguageDropDown li:nth-child(2) a");
    await Page.ClickAsync("#LanguageDropDown li:nth-child(2) a");

    // Wait for navigation
    await Task.Delay(500);

    // Check URL
    var url = Page.Url;
    Assert.Contains("language=", url);
}

Версія Playwright

[Fact]
public async Task FilterTest_Playwright()
{
    await Page.GotoAsync("http://localhost:8080/blog");

    // Auto-waiting built in
    await Page.Locator("#LanguageDropDown button").ClickAsync();

    // Click Spanish option (waits automatically for visibility)
    await Page.Locator("#LanguageDropDown li:has-text('Spanish')").ClickAsync();

    // Check URL (waits automatically for navigation)
    await Expect(Page).ToHaveURLAsync(new Regex(".*language=.*"));
}

Зауважте:

  • Немає інструкції WaitForSelectorAsync потрібна
  • Ні Task.Delay потрібна
  • Чисті твердження за допомогою Expect
  • Більше придатний для читання з has-text інструмент вибору

Створення PDF з Playwright

Подібно до PuppeterSap, Playwright може створювати файли PDF. Програмний інтерфейс програм майже ідентичний:

public async Task<byte[]> GeneratePdfAsync(string url)
{
    await using var browser = await Playwright.Chromium.LaunchAsync();
    await using var page = await browser.NewPageAsync();
    await page.GotoAsync(url);

    return await page.PdfAsync(new()
    {
        Format = "A4",
        PrintBackground = true,
        Margin = new()
        {
            Top = "20mm",
            Right = "20mm",
            Bottom = "20mm",
            Left = "20mm"
        }
    });
}

Те саме PDF отрималаchas зі статті PuppeterSapher так само треба застосовувати і в цьому випадку.

Коли вибрати Playwright

graph TD
    A[Need E2E Testing?] --> B{Multi-browser required?}
    B -->|Yes| C[Playwright]
    B -->|No| D{Chrome only?}
    D -->|Yes| E[PuppeteerSharp or Playwright]
    D -->|No| C

    C --> F[Benefits]
    F --> F1[Test all major browsers]
    F --> F2[Better debugging tools]
    F --> F3[More reliable waiting]
    F --> F4[Mobile emulation]

    E --> G[PuppeteerSharp Benefits]
    G --> G1[Simpler setup]
    G --> G2[Smaller overhead]
    G --> G3[Chromium focused]

    style C stroke:#00aa00,stroke-width:3px
    style E stroke:#0066cc,stroke-width:2px

Виберіть Playwright, якщо:

  • Вам слід перевірити багаторядкові параметри
  • Вам потрібні кращі інструменти для усування вад (переглядач трасування)
  • Ви перевіряєте складні сучасні веб-програми
  • Вам потрібна емуляція мобільних телефонів
  • Ви хочете, щоб дані тестів були більш достовірними.

Виберіть PuppeterSharp, якщо:

  • Тільки Chrome/Edge добре
  • Вам потрібне простіше налаштування
  • Ви вже знайомі з Puppeter
  • Вам потрібно трохи менше ресурсів над головою

Запуск у CI/CD

Приклад дій GitHub

Playwright працює безперешкодно у трубопроводах CI/CD. Ось завершена програма Дії GitHub процес:

name: Playwright Tests

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

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

    - name: Install dependencies
      run: dotnet restore

    - name: Build
      run: dotnet build --no-restore

    - name: Install Playwright browsers
      run: pwsh Mostlylucid.Test/bin/Debug/net9.0/playwright.ps1 install --with-deps

    - name: Start application
      run: |
        dotnet run --project Mostlylucid/Mostlylucid.csproj &
        echo $! > app.pid

    - name: Wait for application
      run: |
        timeout 60 bash -c 'until curl -f http://localhost:8080/health; do sleep 2; done'

    - name: Run Playwright tests
      run: |
        dotnet test Mostlylucid.Test/Mostlylucid.Test.csproj \
          --filter "Category=E2E" \
          --logger "console;verbosity=detailed"

    - name: Upload test results
      if: always()
      uses: actions/upload-artifact@v3
      with:
        name: playwright-results
        path: |
          **/test-results/
          **/traces/

    - name: Stop application
      if: always()
      run: kill $(cat app.pid) || true

Підтримка DockName

Виконання тестів Playwright у Панель потребує встановлення залежностей системи:

FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build

# Install Playwright dependencies
RUN apt-get update && apt-get install -y \
    libnss3 \
    libnspr4 \
    libatk1.0-0 \
    libatk-bridge2.0-0 \
    libcups2 \
    libdrm2 \
    libxkbcommon0 \
    libxcomposite1 \
    libxdamage1 \
    libxfixes3 \
    libxrandr2 \
    libgbm1 \
    libasound2

WORKDIR /app
COPY . .

RUN dotnet restore
RUN dotnet build
RUN pwsh Mostlylucid.Test/bin/Debug/net9.0/playwright.ps1 install

CMD ["dotnet", "test"]

Порівняння швидкодії

З мого тестування в цьому блозі:

Д. д. д. д. д. д. д. д. д. д. д. д. д. ст. |---------|---------------|------------| | Частота перевірки Хрома 2.5s] ~2.8s} | Багаторядковий переглядач А. О. А. С. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . | Автоматична очікувана надійність ♪ Wello (manual)} (автоматичний) ♪ | Пам' ять на переглядач +1/1/2 +180/00 | Налаштуйте складність Точно-модерний режим} | Інструмент для зневаджування ♪ Chhom DevTools + DevTools ♪ | Емуляція мобільнихComment

Граворіг трохи повільніший і використовує трохи більшу пам'ять, але користь від гри та зневадження, як правило, перевищують її.

Звичайні павичі

1. Строго режим

Типово, точки розташування Playwright є строгими:

// This errors if multiple buttons exist
await Page.Locator("button").ClickAsync();

// Be specific
await Page.Locator("button#submit").ClickAsync();

// Or use .First if you really want the first match
await Page.Locator("button").First.ClickAsync();

2. Встановлення переглядача

Не забудь бігти. playwright install Після додавання пакунка. Список переглядачів не буде включено до пакунка NuGet.

3. Сторінка контексту/ контексту

Пам' ятати тести із ізоляції контексту:

// Bad - state leaks between tests
await Page.GotoAsync("/login");
// Do stuff...
await Page.GotoAsync("/dashboard");
// Previous login state might still exist

// Good - fresh context per test
await using var context = await Browser.NewContextAsync();
await using var page = await context.NewPageAsync();
// Completely isolated

4. Різниця у інтернеті

Safari (WebKit) може по- різному поводитись:

// May work in Chrome but fail in WebKit
await Page.Locator(".dropdown").Hover();
await Page.Locator(".dropdown-item").ClickAsync();

// More reliable across browsers
await Page.Locator(".dropdown").ClickAsync();
await Page.WaitForSelectorAsync(".dropdown-item");
await Page.Locator(".dropdown-item").ClickAsync();

Висновки

Playwright представляє еволюцію автоматизації навігатора для розробників. NET. Якщо вам потрібна підтримка декількох бруківців, ви можете зробити чіткий вибір. Так, це трохи складніше, ніж PuppeterSap, але переваги суттєві:

  • Перевірити всі головні переглядачі з ідентичним кодом
  • Краща надійність з автоматичним очікуванням
  • Чудове усування вад з переглядачем трасування
  • Емуляція мобільних та планшетів вийшла зі скриньки
  • Поліпшувати часові питання

Моя рекомендація:

  • Нові проекти, які потребують перевірки міжброю: Почати з Playwright
  • Проекти тільки з криномами: PuppeterSharp простіший
  • Існуючі проекти PuppeterSharp: Міграція, лише якщо вам потрібен багаторядковий переглядач
  • Складні сучасні веб-програми: Програма Playwright варта над головою

Сам переглядач слідів зекономив мені час усування вад. Ви можете повторити перевірку, що зазнала невдачі, і побачити те, що побачив навігатор на кожному кроці, безцінне.

Дайте Playwright перейти до вашого наступного проекту - ви будете приємно здивовані як набагато легше це робить перехресне тестування.

Подальше читання

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.