问题描述
我正在寻找一个好的 PageObject 示例::
这是我正在尝试的示例...但是当我从另一个文件开始测试时... InstallAsync() 反而开始测试,当然失败了,因为 ipage 为空
为什么没有返回 ipage 对象?
public async Task<IPage> LaunchChrome()
{
await Playwright.InstallAsync();
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Webkit.LaunchAsync(headless: false);
var page = await browser.NewPageAsync();
return page;
}
解决方法
我刚刚开始将我的框架从 Selenium 完全迁移到 Playwright,目前,我正在做一些事情:
using PlaywrightSharp;
using System.Threading.Tasks;
namespace Z34.PageTypes
{
public class LoginPage
{
private readonly IPage Self;
public LoginPage(IPage page) => Self = page;
private string UsernameInput => "#username";
private string PasswordInput => "#password";
private string LoginButton => "text='Sign In'";
private async Task ClickLoginButton() => await Self.ClickAsync(LoginButton);
public async Task LogIn(string user,string pass)
{
await Self.TypeAsync(UsernameInput,user);
await Self.TypeAsync(PasswordInput,pass);
await ClickLoginButton();
}
}
}
我想一种不同的方法可能是:
using PlaywrightSharp;
using System.Threading.Tasks;
namespace Z34.PageTypes
{
public class LoginPage
{
private readonly IPage Self;
public LoginPage(IPage page) => Self = page;
private async Task<IElementHandle> UsernameInput() => Self.QuerySelectorAsync("#username");
private async Task<IElementHandle> PasswordInput() => Self.QuerySelectorAsync("#password");
private async Task<IElementHandle> LoginButton() => Self.QuerySelectorAsync("text='Sign In'");
public async Task LogIn(string user,string pass)
{
await UsernameInput().TypeAsync(user);
await PasswordInput().TypeAsync(pass);
await LoginButton().ClickAsync();
}
}
}
我将在未来研究如何改进这一点,当官方文档出来时,但就目前而言,这对我有用。
,这看起来像是 Playwright Sharp 存储库中 a question we received 的“复制品”。
为了完整起见,我将在此处添加相同的代码。我假设这是关于在单元测试中运行 Playwright Sharp 的。具体来说,我为此使用了 Xunit。我们在 Playwright Sharp 自己的测试中使用了相同的方法。
首先,如果您想在测试中重复使用 Fixture
对象,请定义一个 Collection
和一个 Browser
。还有更多关于here的文章。
public class BrowserTestFixture : IAsyncLifetime
{
public IPlaywright PlaywrightContext { get; private set; }
public IChromiumBrowser Browser { get; private set; }
public async Task InitializeAsync()
{
this.PlaywrightContext = await Playwright.CreateAsync();
this.Browser = await this.PlaywrightContext.Chromium.LaunchAsync(headless: false);
}
public async Task DisposeAsync()
{
PlaywrightContext?.Dispose();
}
}
[CollectionDefinition("Browser Collection")]
public class BrowserCollection : ICollectionFixture<BrowserTestFixture>
{
// This class has no code,and is never created. Its purpose is simply
// to be the place to apply [CollectionDefinition] and all the
// ICollectionFixture<> interfaces.
}
此时,您的测试可以通过在构造函数中包含 Fixture
引用来重用这些对象。我使用的例子在这里:
public class UnitTest1 : IClassFixture<BrowserTestFixture>
{
private readonly BrowserTestFixture browserTestFixture;
public UnitTest1(BrowserTestFixture browserTestFixture)
{
this.browserTestFixture = browserTestFixture;
}
[Fact]
public async Task HeadlineIsThere()
{
var page = await browserTestFixture.Browser.NewPageAsync();
await page.GoToAsync("https://www.github.com");
var content = await page.GetTextContentAsync("h1");
Assert.Equal("...",content);
}
[Fact]
public async Task CookieConsentDialogIsShownAndDissmisable()
{
var page = await browserTestFixture.Browser.NewPageAsync();
await page.GoToAsync("https://www.github.com");
var cookieDialogContents = await page.GetTextContentAsync(".cc-message");
Assert.True(!string.IsNullOrEmpty(cookieDialogContents));
await page.ClickAsync("[aria-label='dismiss cookie message']");
// ...
}
}
现在,我明确希望每次都创建一个新的 IPage
对象,但如果您坚持要重用/共享它,则可以修改示例,即提供一个 PageTestFixture
。>
这是我所做的一个简单示例..
基础文件
namespace UsingPlayWriteSharp.PageObjects
{
[TestClass]
public abstract class WebBaseClient : IDisposable
{
public static string BaseURL { get; set; }
private static string _BaseURL = string.Empty;
private static string BrowserType { get; set; }
private static string _BrowserType = string.Empty;
//
public IPlaywright iplaywright;
public IBrowser ibrowser;
public IPage ipage;
public IBrowserContext icontext;
protected WebBaseClient()
{
BaseURL = _BaseURL;
BrowserType = _BrowserType;
}
[AssemblyInitialize]
public static void AssemblyTestInitialize(TestContext TestContext)
{
_BrowserType = TestContext.Properties["browser"].ToString();
_BaseURL = TestContext.Properties["appURL"].ToString();
}
[TestInitialize]
public virtual void TestInitialize()
{
InitializeWebDriver(BrowserType);
}
/// <summary>
/// Used to Select Browser and Device
/// </summary>
/// <param name="browsertype"></param>
protected void InitializeWebDriver(string browsertype)
{
switch (browsertype.ToLower())
{
case "firefox":
if (ibrowser == null)
{
ibrowser = Task.Run(() => GetBrowserFireFoxAsync()).Result;
};
break;
case "firefoxheadless":
if (ibrowser == null)
{
ibrowser = Task.Run(() => GetBrowserFireFoxAsync(true)).Result;
};
break;
case "chrome":
if (ibrowser == null)
{
ibrowser = Task.Run(() => GetBrowserChromeAsync()).Result;
};
break;
case "chromeheadless":
if (ibrowser == null)
{
ibrowser = Task.Run(() => GetBrowserChromeAsync(true)).Result;
};
break;
case "safari":
if (ibrowser == null)
{
ibrowser = Task.Run(() => GetBrowserSafariAsync()).Result;
};
break;
case "ipad":
if (icontext == null)
{
icontext = Task.Run(() => GetBrowseriPadPro()).Result;
};
break;
case "iphone11":
if (icontext == null)
{
icontext = Task.Run(() => GetBrowseriPhonePro()).Result;
};
break;
default:
throw new Exception("Invalid value for parameter named browser in the file *.runsettings. \r\n ");
}
}
/// <summary>
/// Select iPad headless or visible - default is false for testing
/// </summary>
/// <param name="headless"></param>
/// <returns></returns>
private async Task<IBrowserContext> GetBrowseriPadPro(bool headless = false)
{
IBrowserContext browserContext;
await Playwright.InstallAsync();
var playwright = await Playwright.CreateAsync();
ibrowser = await playwright.Webkit.LaunchAsync(headless);
var browserContextOptions = playwright.Devices["iPad Mini"].ToBrowserContextOptions();
browserContextOptions.AcceptDownloads = true;
browserContextOptions.IsMobile = true;
browserContextOptions.Locale = "en-US";
browserContext = await ibrowser.NewContextAsync(browserContextOptions);
return browserContext;
}
/// <summary>
/// Select iPhone headless or visible - default is false for testing
/// </summary>
/// <param name="headless"></param>
/// <returns></returns>
private async Task<IBrowserContext> GetBrowseriPhonePro(bool headless = false)
{
IBrowserContext browserContext;
await Playwright.InstallAsync();
var playwright = await Playwright.CreateAsync();
ibrowser = await playwright.Webkit.LaunchAsync(headless);
var browserContextOptions = playwright.Devices["iPhone 11 Pro"].ToBrowserContextOptions();
browserContextOptions.AcceptDownloads = true;
browserContextOptions.IsMobile = true;
browserContextOptions.Locale = "en-US";
browserContext = await ibrowser.NewContextAsync(browserContextOptions);
return browserContext;
}
/// <summary>
/// Select Safari headless or visible - default is false for testing
/// </summary>
/// <param name="headless"></param>
/// <returns></returns>
private async Task<IBrowser> GetBrowserSafariAsync(bool headless = false)
{
await Playwright.InstallAsync();
var playwright = await Playwright.CreateAsync();
if (headless)
{
ibrowser = await playwright.Webkit.LaunchAsync(headless: headless);
}
else
{
ibrowser = await playwright.Webkit.LaunchAsync(headless: headless);
}
return ibrowser;
}
/// <summary>
/// Select Chrome headless or visible - default is false for testing
/// </summary>
/// <param name="headless"></param>
/// <returns></returns>
private async Task<IBrowser> GetBrowserChromeAsync(bool headless = false)
{
IChromiumBrowser chrome;
await Playwright.InstallAsync();
var playwright = await Playwright.CreateAsync();
if (headless)
{
chrome = await playwright.Chromium.LaunchAsync(headless: headless);
}
else
{
chrome = await playwright.Chromium.LaunchAsync(headless: headless);
}
return chrome;
}
/// <summary>
/// Select FireFox headless or visible - default is false for testing
/// </summary>
/// <param name="headless"></param>
/// <returns></returns>
private async Task<IBrowser> GetBrowserFireFoxAsync(bool headless = false)
{
await Playwright.InstallAsync();
var playwright = await Playwright.CreateAsync();
if (headless)
{
ibrowser = await playwright.Firefox.LaunchAsync(headless: headless);
}
else
{
ibrowser = await playwright.Firefox.LaunchAsync(headless: headless);
}
return ibrowser;
}
public void Dispose()
{
iplaywright?.Dispose();
ipage?.CloseAsync();
}
}
}
页面对象
namespace UsingPlayWriteSharp.PageObjects {
public class LoginPageModel
{
private readonly string usrname = "input[id="UserName"]";
private readonly string loginButton = "#Login-Link";
private readonly string nextButton = "#next";
private IPage page;
public LoginPageModel(IPage ipage)
{
page = ipage;
}
public async Task ClickLoginButton()
{
await page.ClickAsync(loginButton);
}
public async Task EnterUserName(string username)
{
await page.TypeAsync(usrname,username);
}
public async Task ClickNextButton()
{
await page.ClickAsync(nextButton);
}
}
}
样品测试
namespace UsingPlayWriteSharp {
[TestClass]
public class DemoTest : WebBaseClient
{
private LoginPageModel login;
private PlaywrightSharp.IBrowserContext browserContext;
string username = "Aaron_Mraz@demo.com";
[TestMethod]
public async Task SimpleTestAsync()
{
await ipage.GoToAsync(BaseURL);
login = new LoginPageModel(ipage);
await login.ClickLoginButton();
await login.EnterUserName(username);
await login.ClickNextButton();
}
[TestInitialize]
public async Task TestInitializer()
{
browserContext = await ibrowser.NewContextAsync();
ipage = await browserContext.NewPageAsync();
}
}
}