我是 Playwright 和 specflow 的新手,我想知道在所有浏览器(chromium、firefox、webkit)上测试场景的最佳方法是什么。 当前的项目使用了Selenium,但现在我们想使用playwright来实现这一点。 您知道如何有效地实现这一目标吗? 谢谢!
我尝试在场景中使用标签 @chromium @firefox @webkit 并创建一个钩子类:
using TechTalk.SpecFlow;
using System;
using Microsoft.Playwright;
using System.Linq;
using BoDi;
using NLog.Targets;
namespace mynamespace.Steps
{
[Binding]
public class Hooks : IDisposable
{
private readonly IObjectContainer _container;
private readonly IPlaywright _playwright;
public Hooks(IObjectContainer container, IPlaywright playwright)
{
this._container = container;
this._playwright = playwright;
}
[BeforeScenario(Order = 0)]
public void InitializePlaywrightContext()
{
// Get the browser types from the command-line parameters
var browserTypes = GetBrowserTypesFromCommandLine();
var iBrowserTypes = browserTypes.Cast<IBrowserType>().ToArray();
// Initialize the Playwright context and register it in the ObjectContainer
var playwrightContext = new PlaywrightContext(iBrowserTypes);
_container.RegisterInstanceAs(playwrightContext);
}
private IBrowserType[] GetBrowserTypesFromCommandLine()
{
var browserArg = Environment.GetEnvironmentVariable("browser");
if (string.IsNullOrEmpty(browserArg))
{
var chromium = BrowserType.Chromium.ToArray();
// If no browser argument is specified, default to Chromium
return new IBrowserType[] { _playwright.Chromium };
}
else
{
// Split the browserArg by commas to get multiple browsers
var browserNames = browserArg.ToLower().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
// Map the browser names to corresponding BrowserType
IBrowserType[] browserTypes = browserNames.Select(browserName =>
{
return browserName switch
{
"chromium" => _playwright.Chromium,
"firefox" => _playwright.Firefox,
"webkit" => _playwright.Webkit,
_ => _playwright.Chromium,// If an invalid browser name is specified, default to Chromium
};
}).ToArray();
return browserTypes;
}
}
public void Dispose()
{
_container?.Dispose();
}
}
}
然后创建一个剧作家上下文:
using Microsoft.Playwright;
using BoDi;
using System.Collections.Generic;
using System;
using System.Threading.Tasks;
public class PlaywrightContext
{
private readonly IBrowserType[] browserTypes;
private readonly IPage[] pages;
public IBrowser[] Browsers { get; private set; }
public IPage[] Pages { get; private set; }
public PlaywrightContext(IObjectContainer container, IBrowserType[] browserTypes)
{
this.browserTypes = browserTypes;
Initialize(container);
}
private void Initialize(IObjectContainer container)
{
Browsers = new IBrowser[browserTypes.Length];
Pages = new IPage[browserTypes.Length];
for (int i = 0; i < browserTypes.Length; i++)
{
Browsers[i] = browserTypes[i].LaunchAsync().GetAwaiter().GetResult();
Pages[i] = Browsers[i].NewPageAsync().GetAwaiter().GetResult();
container.RegisterInstanceAs(Browsers[i]);
container.RegisterInstanceAs(Pages[i]);
}
}
public IBrowser GetBrowserForBrand(string branding)
{
// Implement logic to return the corresponding browser based on branding
// For example:
if (branding == "Chrome")
{
return Browsers[0]; // Assuming Chrome is the first browser in the array
}
else if (branding == "Firefox")
{
return Browsers[1]; // Assuming Firefox is the second browser in the array
}
else if (branding == "Webkit")
{
return Browsers[2]; // Assuming Webkit is the third browser in the array
}
else
{
throw new ArgumentException($"Invalid branding: {branding}");
}
}
public async ValueTask DisposeAsync()
{
foreach (var browser in Browsers)
{
await browser?.CloseAsync();
}
}
}
但不知道如何在我的步骤课中使用它:
namespace mynamespace.Steps
{
[Binding]
public sealed class TransactionStepsPlaywright
{
private readonly ScenarioContext _scenarioContext;
private readonly ITransactionService _transactionService;
private readonly ApiSettings _apiSettings;
private readonly ILoggingService _loggingService;
private readonly int _maxRetries = 3;
private readonly INavigationPane _navigationPane;
private readonly IOtpService _otpService;
private readonly IObjectContainer _container;
private readonly PlaywrightContext _playwrightContext;
private readonly IPlaywright _playwright; // Add IPlaywright dependency
public TransactionStepsPlaywright(ScenarioContext scenarioContext, PlaywrightContext playwrightContext, IObjectContainer container, ILoggingService loggingService, ITransactionService transactionService, IOtpService otpService, IPlaywright playwright, IOptions<ApiSettings> apiSettingsOption, INavigationPane navigationPane) // Add IPlaywright here
{
_scenarioContext = scenarioContext;
_transactionService = transactionService;
_playwright = playwright; // Use IPlaywright here
_apiSettings = apiSettingsOption.Value;
_loggingService = loggingService;
_navigationPane = navigationPane;
_otpService = otpService;
_container = container;
_playwrightContext = playwrightContext;
}
[Given(@"pw I open the login page for (.*)")]
public void GivenIOpenTheLoginPageFor(string branding)
{
try
{
var url = _apiSettings.EndPoints.FirstOrDefault(
ep => string.Compare(ep.Name, branding, StringComparison.InvariantCultureIgnoreCase) == 0
).Url;
var browser = _playwrightContext.GetBrowserForBrand(branding); // Get the corresponding browser for the given branding
var page = browser.NewPageAsync().GetAwaiter().GetResult(); // Create a new page for the browser
page.GotoAsync(url).GetAwaiter().GetResult();
Console.WriteLine($"Opened the login page for branding: {branding} in {browser.Name}.");
}
catch (Exception)
{
throw new Exception($"Could not navigate to login page for branding: {branding}.");
}
}
我对PlayWright不熟悉,但根据您提供的内容,它根据环境变量初始化浏览器。设置名为“browser”的环境变量,值为“chromium,firefox,webkit”,并在“Given”中使用它作为“pw我打开Chrome的登录页面”或“pw我打开Firefox的登录页面”。
初始化默认为
chromium
,您可以使用 Given
测试您的 "pw I open the login page for Chrome"
,看看它是否有效。
我使用以下代码在不同浏览器中进行测试:
namespace PlayWrightSpecFlow.Drivers
{
public class Driver : IDisposable
{
private readonly Task<IPage> _page;
private IBrowser? _browser;
public Driver()
{
_page = InitializePlaywright();
}
public IPage Page => _page.Result;
// creating/initializing playwright
private async Task<IPage> InitializePlaywright()
{
//Playwright >>> it will start downaloding things for us for automation.
var playwright = await Playwright.CreateAsync();
//create browser instance
_browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
{
Headless = false,
// SlowMo = 1000,
Timeout = 50000,
Channel = "chrome"
});
//create page instance
return await _browser.NewPageAsync();
}
public void Dispose() => _browser?.CloseAsync();
}
}
_browser = wait playwright.Chromium.LaunchAsync >>> 它将启动 Chromium 引擎。如果您选择频道为 Chrome,它将启动 Chrome 浏览器,如果您选择频道为 MS Edge(Edge 使用 chromium 浏览器引擎),它将启动 MS Edge 浏览器。
如果要打开 Firefox 或 webkit,请将 Chromium 替换为 Firefox,无需添加通道。