假设我有一个使用包含在两个不同类中的步骤的场景。有没有办法让他们两个都可以在IWebDriver
不经过的情况下处理同一个实例ScenarioContext.Current["webdriverVariableName"]
?
太丑了 有没有更清洁的方法?
我打算创建一个具有public static IWebDriver
在每个场景开始时分配的属性的类,以便我的所有步骤都可以引用它,但我认为当我开始并行运行它们时这将不起作用,因为每个场景将覆盖全局驱动程序。
Specflow 提供了依赖注入机制,因此您可以在步骤中注入 Web 驱动程序实例。
见https://github.com/techtalk/SpecFlow/wiki/Context-Injection
请参阅“高级选项”部分。
我刚刚开始使用 Specflow,但这似乎可行;
创建一个以 IObjectContainer 作为构造函数并具有 BeforScenario 方法来创建 WebDriver 实例的类;
[Binding]
public class WebDriverSupport
{
private readonly IObjectContainer _objectContainer;
public WebDriverSupport(IObjectContainer objectContainer)
{
_objectContainer = objectContainer;
}
[BeforeScenario]
public void InitializeWebDriver()
{
var webDriver = DriverFactory.CreateDriver();
_objectContainer.RegisterInstanceAs<RemoteWebDriver>(webDriver);
}
}
使用带有 RemoteWebDriver 的构造函数创建您的步骤类;
[Binding]
public class POCSteps
{
private readonly IdlWebDriver _driver;
public POCSteps(IdlWebDriver driver)
{
_driver = driver;
}
}
您的步骤步骤现在可以访问完全实例化的 WebDriver 对象
我的测试,目前运行良好的多线程 webdriver 实例,正在使用基本步骤定义类来保存驱动程序实例。所有步骤定义都继承自此,因此驱动程序可用于所有步骤。
namespace Project.StepDefinitions
{
[Binding]
public class BaseStepDefinitions
{
private const string CurrentPageKey = "Current.Page";
public static IWebDriver Driver { get; set; }
protected LogonPageModel LogonPage
{
get { return (LogonPageModel)ScenarioContext.Current[CurrentPageKey]; }
set { ScenarioContext.Current[CurrentPageKey] = value; }
}
protected RegisterPageModel RegisterPage
{
get { return (RegisterPageModel)ScenarioContext.Current[CurrentPageKey]; }
set { ScenarioContext.Current[CurrentPageKey] = value; }
}
}
}
//////////////
namespace SpecDriver.StepDefinitions
{
[Binding]
public class LoginSteps : BaseStepDefinitions
{
[Given(@"I navigate to the homepage")]
public void GivenINavigateToTheHomepage()
{
Driver.Navigate().GoToUrl(SettingsManager.BaseUrl);
}
}
}
等等等等……
只需使用返回驱动程序的静态属性创建一个新的分离类:
static class DriverProvider
{
private static IWebDriver _driver;
public static IWebDriver Driver
{
get
{
if (_driver == null)
{
_driver = new ChromeDriver();
_driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(40);
_driver.Manage().Window.Maximize();
}
return _driver;
}
}
}
每次您需要对驱动程序做某事时,只需以这样的方式调用它:
SomeMethod(DriverProvider.Driver);
//
IWebelement e = DriverProvider.Driver.FindElement(By.XPath("you_XPath"));
e.Click();
// etc etc etc