SpecFlow多场景运行重复打开浏览器问题求助
解决SpecFlow多场景运行时重复打开浏览器的问题
问题描述
我创建了包含2个场景的Feature文件,并编写了对应的Step Definitions,但运行时会打开多个浏览器,希望全程仅使用一个浏览器实例完成所有测试。
Feature代码
Feature: Login Background: Given user navigated to SauceLap website @Login Scenario: user login with locked user When user enter the locked userName "locked_out_user" And user enter the password "secret_sauce" And click on login button Then An error message must be appears @Login Scenario: user login with valid credentials When user enter a valid userName "standard_user" And user enter a valid password "secret_sauce" And user click on login button Then automatically navigated to homePage
Step Definitions代码
namespace SpecFlowProject2.StepDefinitions { [Binding] public sealed class Login { private IWebDriver driver; public Login(IWebDriver driver) { this.driver = driver; } [Given(@"user navigated to SauceLap website")] public void GivenUserNavigatedToSauceLapWebsite() { driver.Url = "https://www.saucedemo.com/v1/"; } [When(@"user enter the locked userName ""([^""]*)""")] public void WhenUserEnterTheLockedUserName(string userName) { driver.FindElement(By.XPath("//input[@id='user-name']")).SendKeys(userName); } [When(@"user enter the password ""([^""]*)""")] public void WhenUserEnterThePassword(string Password) { driver.FindElement(By.Id("password")).SendKeys(Password); } [When(@"click on login button")] public void WhenClickOnLoginButton() { driver.FindElement(By.Id("login-button")).Click(); } [Then(@"An error message must be appears")] public void ThenAnErrorMessageMustBeAppears() { Thread.Sleep(3000); } [When(@"user enter a valid userName ""([^""]*)""")] public void WhenUserEnterAValidUserName(string userName) { driver.FindElement(By.XPath("//input[@id='user-name']")).SendKeys(userName); } [When(@"user enter a valid password ""([^""]*)""")] public void WhenUserEnterAValidPassword(string Password) { driver.FindElement(By.Id("password")).SendKeys(Password); } [When(@"user click on login button")] public void WhenUserClickOnLoginButton() { driver.FindElement(By.Id("login-button")).Click(); } [Then(@"automatically navigated to homePage")] public void ThenAutomaticallyNavigatedToHomePage() { Thread.Sleep(3000); } } }
原Hooks代码
namespace SpecFlowProject2.Hook { [Binding] public sealed class Hooks1 { private readonly IObjectContainer _container; public Hooks1(IObjectContainer container) { _container = container; } [BeforeScenario("@tag1")] public void BeforeScenarioWithTag() { // Example of filtering hooks using tags. (in this case, this 'before scenario' hook will execute if the feature/scenario contains the tag '@tag1') // See https://docs.specflow.org/projects/specflow/en/latest/Bindings/Hooks.html?highlight=hooks#tag-scoping //TODO: implement logic that has to run before executing each scenario } [BeforeFeature(Order = 1)] public void FirstBeforeScenario() { IWebDriver driver=new ChromeDriver(); driver.Manage().Window.Maximize(); _container.RegisterInstanceAs<IWebDriver>(driver); } [AfterScenario] public void AfterScenario() { //TODO: implement logic that has to run after executing each scenario } } }
问题原因
原代码使用[BeforeFeature]钩子初始化浏览器,但该钩子作用域为单个Feature,且依赖注入容器的实例注册逻辑无法保证多个场景间复用同一个WebDriver实例,导致每个场景运行时都会重新创建浏览器实例。
解决方案
修改Hooks代码,通过全局测试周期钩子控制WebDriver生命周期,确保全程复用一个浏览器实例,并在场景间重置状态避免污染:
修改后的Hooks代码
namespace SpecFlowProject2.Hook { [Binding] public sealed class Hooks1 { private static IWebDriver _driver; private readonly IObjectContainer _container; public Hooks1(IObjectContainer container) { _container = container; } [BeforeTestRun] public static void BeforeTestRun() { // 所有测试开始前仅初始化一次浏览器 _driver = new ChromeDriver(); _driver.Manage().Window.Maximize(); } [BeforeScenario] public void BeforeScenario() { // 将单例浏览器实例注册到容器,供当前场景的Step Definitions使用 _container.RegisterInstanceAs<IWebDriver>(_driver); } [AfterScenario] public void AfterScenario() { // 场景执行后重置浏览器状态,避免场景间数据残留 _driver.Navigate().GoToUrl("https://www.saucedemo.com/v1/"); _driver.FindElement(By.Id("user-name")).Clear(); _driver.FindElement(By.Id("password")).Clear(); } [AfterTestRun] public static void AfterTestRun() { // 所有测试完成后关闭浏览器,释放资源 _driver?.Quit(); _driver?.Dispose(); } } }
关键修改说明
[BeforeTestRun]钩子:在整个测试套件启动时仅执行一次,初始化全局单例WebDriver实例,保证全程复用同一个浏览器。[BeforeScenario]钩子:每个场景开始前将全局单例driver注册到容器,确保当前场景的所有Step Definitions都获取同一个实例。[AfterScenario]钩子:场景结束后重置浏览器到初始状态(回到登录页、清除输入框),避免前一个场景的操作影响后续场景。[AfterTestRun]钩子:所有测试执行完毕后关闭浏览器,释放系统资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Mohamed hakim
相关产品推荐
相关产品推荐

