SpecFlow生成LivingDoc报告仅显示最后执行测试结果问题排查
SpecFlow LivingDoc报告仅显示最后一个Feature通过的排查方案
问题现象
项目中20个Feature测试用例均执行通过,但生成LivingDoc报告时,仅最后执行的Feature显示为通过状态,其余Feature均显示「Not executed(未执行)」。
项目结构
|-Project +----Feature |------Login.feature +----Steps |------Login.cs +----Drivers |------SetDriver.cs +----Hooks |------BrowserHook.cs +----Pages |------PageObjectManager.cs |------LoginPage.cs
现有代码配置
Driver配置
public class SetDrivers { private Lazy<IWebDriver> _driver; public SetDrivers() { _driver = new Lazy<IWebDriver>(Setup); } public IWebDriver Current => _driver.Value; public IWebDriver Setup() { var chromeDriverServices = ChromeDriverService.CreateDefaultService(); var browserOption = GetBrowserOptions("chrome"); var driver = new ChromeDriver(chromeDriverServices, browserOption); driver.Manage().Window.Maximize(); return driver; } private dynamic GetBrowserOptions(String browserName) { if (browserName.ToLower() == "chrome") { return new ChromeOptions(); } else if (browserName.ToLower() == "firefox") { return new FirefoxOptions(); } else { return new ChromeOptions(); } } }
Hooks配置
[Binding] public sealed class BrowserHooks { [BeforeTestRun] public static void BeforeTestRun(ObjectContainer objectContainer) { objectContainer.BaseContainer.Resolve<SetDrivers>(); } [BeforeScenario ("Smoke")] public static void BeforeSenerio(SetDrivers drivers) { var pageObjects = new PageObjectManager(drivers.Current); pageObjects.loadUrl(); } [AfterScenario] public void AfterScenario(SetDrivers drivers) { var pageObjects = new PageObjectManager(drivers.Current); pageObjects.tearDown(); } }
步骤定义
[Binding] public class LoginSteps { private LoginPage _loginPage; public LoginSteps(SetDrivers drivers) { _loginPage = new LoginPage(drivers.Current); } [Given(@"user is in login page")] public void GivenUserIsInLoginPage() { _loginPage.clickLoginBtn(); } [When(@"user Enters ""(.*)"" and ""(.*)""")] public void WhenUserEntersAnd(string email, string password) { _loginPage.setUserEmail(email); _loginPage.setPassword(password); } [When(@"click Login Button")] public void WhenClickLoginButton() { _loginPage.clickLogin(); } [Then(@"Home Page should be visible")] public void ThenHomePageShouldBeVisible() { Assert.IsTrue(_loginPage.isLoggedIn()); } }
Feature用例
Feature: Login User login test @Smoke Scenario Outline: User wants to login with valid email and password Given user is in login page When user Enters "<Email>" and "<Password>" And click Login Button Then Home Page should be visible Examples: | Email | Password | | mail@mail.com | 121212A |
页面对象管理器
public class PageObjectManager { private const string url = "https://www.pinterest.com/"; private readonly IWebDriver _webDriver; public PageObjectManager(IWebDriver webDriver) { _webDriver = webDriver; } public void loadUrl() { _webDriver.Url = url; } public void tearDown() { if (_webDriver != null) { _webDriver.Quit(); } } }
异常截图


根因与修复方案
核心原因(直接导致报告显示异常)
报告生成逻辑配置错误:如果分批次执行Feature,每次执行都将测试结果输出到同一路径的文件,默认dotnet test会覆盖旧的结果文件,不会追加内容;若生成LivingDoc时未开启结果合并参数,最终只会读取到最后一次执行的结果记录,因此仅最后一个Feature显示通过,其余均显示未执行。
修复方式二选一:
- 单次执行全量用例:执行测试时指定统一的结果输出文件,确保20个Feature在同一次测试运行中完成,命令参考:
执行完成后基于这个全量结果文件生成LivingDoc即可。dotnet test --logger "trx;LogFileName=all_test_results.trx" - 分批执行后合并结果:如果必须分批次跑用例,生成LivingDoc时添加
--merge参数,传入所有批次的结果文件做合并,再生成报告。
附带代码问题(会导致用例执行不稳定,间接影响结果采集)
- SetDrivers未正确注册到SpecFlow DI容器:现有BeforeTestRun逻辑仅解析了一次SetDrivers实例,未做单例注册,SpecFlow会在不同请求域生成新的SetDrivers实例,导致driver实例不唯一。
修复:修改BeforeTestRun逻辑,注册SetDrivers为全局单例:[BeforeTestRun] public static void BeforeTestRun(ObjectContainer objectContainer) { var driver = new SetDrivers(); objectContainer.BaseContainer.RegisterInstanceAs<SetDrivers>(driver); } - Driver实例未做重置:现有AfterScenario逻辑执行
Quit()后没有重置Lazy包装的driver实例,下一个Scenario执行时会复用已经退出的driver,触发执行错误。
修复:给SetDrivers类增加驱动重置方法:
替换原有tearDown逻辑,Scenario执行完成后调用该方法重置驱动。public void ResetDriver() { if (_driver.IsValueCreated) { _driver.Value.Quit(); _driver.Value.Dispose(); _driver = new Lazy<IWebDriver>(Setup); } } - BeforeScenario加了Smoke标签过滤:现有初始化逻辑仅对打了@Smoke标签的Scenario生效,未加该标签的Scenario不会触发页面加载,直接执行失败。需要确认其余19个Feature的Scenario是否都添加了@Smoke标签,若没有则去掉标签过滤,或给对应Scenario补上标签。
内容的提问来源于stack exchange,提问作者Tariful Islam Abir
相关产品推荐
相关产品推荐

