This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Multi---Browser-Test mit Playwright für .-NET
Thursday, 27 November 2025
Playwright ist Microsoft®'s offizielle Lösung für die moderne Browser-Automatisierung., , bietet Multi-- , Browser-Unterstützung , ( , Chrome und mobile Emulation ,. Diese Anleitung umfasst alles von der Einrichtung bis zu fortgeschrittenen Testmustern , die es mit PuppeteerSharp vergleichen, um Ihnen zu helfen, das richtige Tool wählen , . , Wenn Sie nur benötigen Chrome und wollen einfachere Setup- -, PuppeteerSharp Stattdessen -, aber wenn Sie umfassende cross-Tests benötigen -Browser testing,... Playwright ist der Weg vorwärts
Einleitung
Wenn Sie lesen meinen Artikel auf PuppeteerSharp' ist ein Fan von modernen Test-Tools, die don.'t machen Sie wollen Ihre Haare ausreißen ? MS K5 puppeteerSharp ist brillant für Chrome ?- nur Tests ?, , aber was, wenn Sie über mehrere Browser testen müssen ? Wiedergaberecht kommt in.
Playwright ist eine Antwort von Microsoft auf das Problem der Browser-Automatisierung, , und sie ' haben aus allem gelernt, was zuvor gekommen ist... Es kommt wie PuppeteerSharp's ambitionierteres Geschwisterchen. -. Es macht alles, was Puppeteer tut, aber Firefox und Safari Unterstützung fügt hinzu: ,. Bessere auto.-.Warten mit ,. Und ein Haufen Debugging-Tools, die das Finden von Problemen zu einem absoluten Doddle machen.
In diesem Artikel zeigen Ihnen, wie man Playwright für Chrome-,., und Safari mit echten Codebeispielen und praktischen Mustern, die Sie heute verwenden können, zu testen
Warum Playwright über PuppenspielerSharp-?
Don-'-t bekommen Sie mich falsch PuppeteerSharp ist exzellent, wenn Sie nur Chrome benötigen, aber hier, wenn Playwright Sinn macht.
Das Problem des Multi---Browsers
Ihre Benutzer verwenden alle Chrome, die Sie benutzen
- Chrom-/.Edge,: , , ~65% , von den Benutzern ,( ,Chromium , - , auf der Grundlage von ) ,
- Safari.: . . ~20% . der Benutzer . ( . vor allem mobile
- Firefox.: . . ~5% . der Benutzer .( , aber oft andere Rendering .
Ein Fehler, der nur in Safari angezeigt wird, kann Sie verlieren 20%. von Ihren potentiellen Benutzern Mit dem Playwright können Sie alle drei mit derselben API testen.
Bessere Entwicklererfahrung
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
Die wichtigsten Vorteile
- Unterstützung für Multi--.browser Testen Sie Chrome , , , Firefox , , , Safari mit identischem Code
- Bessere Auto-Wartung Verlässlicher aus dem Kasten weniger schuppige Tests.
- Betrachter verfolgen Bezeichnen Sie vollständige Spuren von Testläufen zum Debuggen
- Codegen Erzeugen Sie Testcode durch Interaktion mit Ihrer Website
- Netzabhörung Stärker als PuppenspielerSharp
- Moderne Web-Funktionen Bessere Unterstützung für Schatten-DOM, ,, iframes, usw..
Einrichten des Playwrights für .NET
Installieren Microsoft®.-Playwright NuGet-Paket„:"
dotnet add package Microsoft.Playwright
dotnet add package Microsoft.Playwright.NUnit # Or use xUnit
Installieren Sie dann die Browser dieses Downloads Chromium, FirefoxL 347 vom 20.12.2013, S. 671. WebKit):
pwsh bin/Debug/net9.0/playwright.ps1 install
Oder unter Linux.
playwright install
Anmerkung: Die erste Browser-Installation Downloads rund um 400.MB... Nachfolgende Updates sind viel kleiner.
Hier sind meine Test-Projektkonfigurationen.
<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>
I'-M mit xEinheitAber Playwright funktioniert genauso gut mit NUnit oder MSTestTatsächlich hat der Playwright einen engagierten NUnit-Integration mit zusätzlichen Helfern
Erstellen einer Basistestklasse
Ähnlich wie PuppeteerSharp,, jedoch mit Multi--Browser Unterstützung
Die Klassenstruktur
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
}
Warum Browser-Kontexten?
Beachten wir, dass wir eine Context vor der Erstellung einer PageDies ist ein Playwright-Konzept, das PuppeteerSharp nicht hat.
- Kontext Getrennte Browser-Session - Inkognito-Modus - )
- Seite Eine Registerkarte in diesem Kontext
Kontexte lassen dich
- Testen Sie mit verschiedenen Benutzersitzungen gleichzeitig
- Setzen Sie verschiedene Cookies, die für den Kontext verwendet werden
- Isolationstests komplett -(-even innerhalb der gleichen Browser-Instanz - )-
Hilfsmethoden
// 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();
}
Ortungsgeräte für die geheime Waffe des Spielers
Beachten Sie die Page.Locator() calls-?-Dies unterscheidet sich von PuppeteerSharp-' QuerySelectorOrtungen sind ,:
- Faul Sie fragen das DOM nicht ab, bis du sie benutzt.
- Wiederholung Sie warten automatisch und wiederholen Operationen
- Streng Sie fälschen, wenn mehrere Elemente zusammenpassen.
// PuppeteerSharp way (manual waiting)
await Page.WaitForSelectorAsync("#button");
await Page.ClickAsync("#button");
// Playwright way (auto-waiting)
await Page.Locator("#button").ClickAsync(); // Waits automatically!
Prüfung des Multi---Browsers
Hier, wo Playwright glänzt, können Sie den gleichen Test über alle Browser durchführen.
Verwendung von xUnit-Theorie für Multi-Tests
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}");
}
}
Browser-Spezifische Testklassen
Oder separate Testklassen für jeden Browser erstellen
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);
}
}
Schreiben von Tests Die Playwright-Weg
Betrachten wir reale Beispiele, die Playwright-Vorteile zeigen
Testen von HTMX mit Auto.--Warten
[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);
}
Prüfung der Wechselwirkungen von Alpine-.
Handgriffe für Playwright Alpen-.-js Reaktivität und Animationen nahtlos
[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);
}
Prüfformulare mit Validierung
[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("[email protected]");
await Page.Locator("#comment-content").FillAsync("Great article!");
// Submit
await Page.Locator("#comment-submit").ClickAsync();
// Wait for success
await Page.Locator(".comment-success").WaitForAsync();
}
Erweiterte Playwright-Funktionen
Netzwerk-Abfangleistung ---- Leistungsstärker als PuppenspielerSharp
[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);
}
Trace Viewer - Fehler beim Debug fehlgeschlagene Tests
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();
}
Dann sehen Sie die Spur.
playwright show-trace traces/TestName.zip
Dies öffnet eine Benutzeroberfläche, die zeigt:
- Jede Aktion, die Ihr Test durchgeführt hat
- Screenshots bei jedem Schritt
- Netzanfragen
- Konsolenprotokolle
- DOM Snapshots
Es ist absolut brillant für Debugging.
Screenshots zum Scheitern
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();
}
Mobile Emulation
[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 kommt mit Gerätedeskriptoren für„:"
- iPhone , 13, , , 13, Pro , ,, MSSK3, 11,, SE
- iPad , , , iPad Pro
- Samsung Galaxy-Pixel
- Und viele mehr
Prüfung des Dunklen Modus
[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 PuppenspielerSharp Seite für Seite
Hier ist der gleiche Test in beiden Bibliotheken, um die Unterschiede zu zeigen.
PuppenspielerSharp Version
[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);
}
Wiedergaberecht-Version
[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=.*"));
}
Hinweis:
- Kein Handbuch
WaitForSelectorAsyncerforderlich - Nein
Task.Delayerforderlich - Saubere Behauptungen mit
Expect - Mehr lesbar mit
has-textWählgerät
PDF-Erstellung mit Playwright
Wie PuppeteerSharp-,-Playwright PDFs generieren kann, ist die API fast identisch.
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"
}
});
}
Das gleiche PDF gotchas aus dem PuppenspielerSharp Artikel Auch hier anwenden
Wann man Playwright wählt
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
Wählen Sie Playwright, wenn -:
- Sie benötigen Multi---Browser-Test
- Sie wollen bessere Debugging-Tools .( .Trace Viewer .
- Sie testen komplexe moderne Web-Apps
- Sie brauchen mobile Emulation
- Sie wollen zuverlässigere Tests aus dem Kasten heraus
Wählen Sie PuppeteerSharp, wenn
- Chrome-/.Edge ist nur in Ordnung
- Sie wollen einfachere Einrichtung
- Sie sind bereits vertraut mit Puppeteer
- Sie brauchen etwas weniger Ressourcenaufwand
Laufen in CI-/-CD
Beispiel für GitHub-Aktionen
Playwright arbeitet nahtlos in CI-/-CD-Pipelines, hier ist ein komplettes GitHub-Maßnahmen Arbeitsablauf
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
Docker-Unterstützung
Durchführung von Playwright Tests in Docker erfordert die Installation von Systemabhängigkeiten
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"]
Leistungsvergleich
Von meinem Testen auf diesem Blog
| Beschreibung des Merkmals | ||
|---|---|---|
| Chrom-Prüfgeschwindigkeit | -~2.5-M | -MNSK3-MSSK4-MUSK2 |
| Multi---Browser Weitere Informationen: http:europa.eu.int/en/comm/index_de.htm | ||
| Auto---Wartesicherheit Sehr gut, sehr gut | ||
| Speicher pro Browser | -MB- | -Mb-~180-MB |
| Komplexität einrichten Einfaches, mittelschweres und leichtes | ||
| Debugging-Werkzeuge Chrome-DevTools - Spurenbetrachter | ||
| Mobile Emulation Grundlegende Informationen Ausgezeichnet |
Playwright ist etwas langsamer und verwendet ein wenig mehr Speicher, aber die Zuverlässigkeit und Debugging Vorteile in der Regel überwiegen diese
Häufig Gotchas
Strikter Modus
Playwright-Lokatoren von ' sind standardmäßig streng
// 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();
Installation des Browsers
Nicht vergessen zu laufen playwright install nach dem Hinzufügen des Pakets... die Browser sind... die im NuGet Paket enthalten sind...
Kontext vs Seite
Kontexte isolieren Tests speichern
// 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
Unterschiede des Webkits
Safari (-WebKit)- kann anders verhalten
// 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();
Schlußfolgerung
Playwright stellt die Entwicklung der Browser-Automatisierung für Entwickler von .-NET dar, wenn Sie multi--browser Unterstützung benötigen.,e es ist die klare Wahl... PuppeteerSharpDie Vorteile sind jedoch erheblich.
- Test über alle gängigen Browser mit identischem Code
- Bessere Zuverlässigkeit durch automatisches Warten
- Ausgezeichnetes Debugging mit Trace Viewer
- Mobile und Tablet-Emulation aus dem Kasten
- Belastbarer gegenüber zeitlichen Problemen
Meine Empfehlung
- Neue Projekte, die Cross-Tests benötigenBeginnen Sie mit dem Playwright
- Nur Projekte von Chrome--PuppeteerSharp ist einfacher
- Bestehende PuppenspielerSharp-ProjekteMigrieren nur, wenn Sie Multi--browser benötigen
- Komplexe moderne Web-AppsPlaywright-Tooling ist das Overhead wert
Der Trace-Betrachter allein hat mir Stunden des Debuggens gespart. ,. , in der Lage zu sein, einen fehlgeschlagenen Test erneut abzuspielen und genau zu sehen, was der Browser bei jedem Schritt sah ist unschätzbar
Give Playwright a go on your next project Mehr erfahren Sie werden angenehm überrascht sein, wie viel einfacher es macht Cross--Browser-Testing