首页 > 解决方案 > 从 LightBDD 装饰器中,如何从 DependencyResolver 中检索场景的当前 ChromeDriver?

问题描述

我正在使用LightBDD运行 Selenium 测试,并且我试图在场景失败时自动截取屏幕截图。我编写了一个类级别的 LightBDD 装饰器来执行此操作,但我从 检索 ChromeDriver 的一个实例,ResourcePool而不是检索当前的 ChromeDriver。

如何检索场景的当前ChromeDriver 而不是新实例?

更多细节

我正在按照提供的示例注册 ChromeDriver ,即:

private void ConfigureContainer(ContainerConfigurator config)
{
    config.RegisterInstance(
        new ResourcePool<ChromeDriver>(CreateDriver),
        new RegistrationOptions());
}

private ChromeDriver CreateDriver()
{
    var driver = new ChromeDriver();
    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(0);
    return driver;
}

我的装饰器:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class TakeScreenshotOnErrorAttribute : Attribute, IScenarioDecoratorAttribute
{
    public async Task ExecuteAsync(IScenario scenario, Func<Task> scenarioInvocation)
    {
        try {
            await scenarioInvocation();
        }
        catch (Exception ex) {
            await TakeScreenshot(scenario);
        }
    }

    public int Order { get; set; }

    private static async Task TakeScreenshot(IScenario scenario)
    {
        try {
            var driverHandle = scenario.DependencyResolver.Resolve(typeof(ResourceHandle<ChromeDriver>));
            var driver = await ((ResourceHandle<ChromeDriver>) driverHandle).ObtainAsync();
            var screenshot = driver.GetScreenshot();
            screenshot.SaveAsFile(@"c:\temp\error.png");
        }
        catch {
            /* Ignore */
        }
    }
}

调试器清楚地显示创建了第二个实例: 场景.DependencyResolver 调试器

版本:带有 NUnit3 的 LightBDD 3.0.1

标签: c#

解决方案


LightBDD DI 容器的默认行为是在每次Resolve()调用方法时提供所请求依赖项的新实例。

为了使其按预期工作,必须使用更高级的 DI(如LightBDD.Autofac包),并且ResourceHandle<ChromeDriver>必须使用作用域生命周期进行注册:

public class ConfiguredLightBddScopeAttribute : LightBddScopeAttribute
{
    protected override void OnConfigure(LightBddConfiguration configuration)
    {
        configuration.DependencyContainerConfiguration()
            .UseAutofac(ConfigureContainer());
    }

    private ContainerBuilder ConfigureContainer()
    {
        var builder = new ContainerBuilder();
        builder.RegisterInstance(new ResourcePool<ChromeDriver>(CreateDriver));
        builder.RegisterType<ResourceHandle<ChromeDriver>>().InstancePerLifetimeScope(); 
        // ^-- this makes the difference
        return builder;
    }

    private ChromeDriver CreateDriver()
    {
        var driver = new ChromeDriver();
        driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromMilliseconds(0);
        return driver;
    }
}

这意味着虽然每个场景都将获得自己的句柄副本,但场景代码和装饰器代码将获得相同的实例。

我在 LightBDD 问题页面的回复中提供了工作示例:https ://github.com/LightBDD/LightBDD/issues/186


推荐阅读