C# 扩展 Selenium Webdriver 类

3
我想添加一个静态字符串属性来跟踪当前运行的测试名称。我认为最好的方法是使用WebDriver,因为它是贯穿所有页面对象的唯一对象。
有没有办法扩展WebDriver类以添加可以设置的字符串属性呢?
编辑:由于WebDriver使用IWebDriver接口,因此我应该扩展接口吗?
编辑#2:添加我目前加载WebDriver的示例:
protected static NLog.Logger _logger = LogManager.GetCurrentClassLogger();
protected static IWebDriver _driver;

/// <summary>
/// Spins up an instance of FireFox webdriver which controls the browser using a
/// FireFox plugin using a stripped down FireFox Profile.
/// </summary>
protected static void LoadDriver()
{
    ChromeOptions options = new ChromeOptions();
    try
    {
        var profile = new FirefoxProfile();
        profile.SetPreference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream doc xls pdf txt");

        _driver = new FirefoxDriver(profile);
        _driver.Navigate().GoToUrl("http://portal.test-web01.lbmx.com/login?redirect=%2f");
    }
    catch(Exception e)
    {
        Console.WriteLine(e.Message);
        throw;
    }
}

你能提供一个例子吗? - Florent B.
添加了一个我目前用来加载WebDriver的示例。这是在一个抽象类中,该类负责测试的设置/清理/实用程序。 - Milo
为什么不要在执行函数中初始化静态字符串? - Leon Barkan
@LeonBarkan 这个类是抽象的,带有静态方法用于执行。我不认为可以设置一个字符串,以便我可以为每个不同的测试更改它。如果我错了,请举个例子。 - Milo
4个回答

5

好的,让我们停止使用不完整的回答(这是通用IWebDriver的完整实现),在那之后,您可以调用所有常规方法,就像在标准驱动程序中一样 + 您还有额外的CurrentTest变量。

您可以添加更多构造函数以获得最佳兼容性。

class MyWebDriver<T> where T : IWebDriver, new()
{
    IWebDriver driver;
    public string CurrentTest { get; set; }

    public MyWebDriver()
    {
        driver = new T();
    }

    public void Dispose()
    {
        this.driver.Dispose();
    }

    public IWebElement FindElement(By by)
    {
        return this.driver.FindElement(by);
    }

    public ReadOnlyCollection<IWebElement> FindElements(By by)
    {
        return this.driver.FindElements(by);
    }

    public void Close()
    {
        this.driver.Close();
    }

    public void Quit()
    {
        this.driver.Quit();
    }

    public IOptions Manage()
    {
        return this.driver.Manage();
    }

    public INavigation Navigate()
    {
        return driver.Navigate();
    }

    public ITargetLocator SwitchTo()
    {
        return this.SwitchTo();
    }

    public string Url
    {
        get
        {
            return this.driver.Url;
        }
        set
        {
            this.driver.Url = value;
        }
    }

    public string Title
    {
        get
        {
            return this.driver.Title;
        }
    }

    public string PageSource
    {
        get
        {
            return this.driver.PageSource;
        }
    }

    public string CurrentWindowHandle
    {
        get
        {
            return this.driver.CurrentWindowHandle;
        }
    }

    public ReadOnlyCollection<string> WindowHandles
    {
        get
        {
            return this.WindowHandles;
        }
    }
}

public class MyTest
{
    public void main()
    {
        MyWebDriver<FirefoxDriver> driver = new MyWebDriver<FirefoxDriver>();
        driver.CurrentTest = "Entering to google website with Firefox Driver";
        driver.Navigate().GoToUrl("www.google.com");
    }
}

感谢 @LeonBarkan 给出的直截了当的答案! - Milo
很棒的答案!唯一的缺点是它不能与RemoteWebDriver一起使用,因为它的构造函数需要参数... - Samuel Rondeau-Millaire
2
实际上,这个答案也是不完整的。你忘记提到 using 语句了:using OpenQA.Selenium;using System.Collections.ObjectModel; 无论如何,我为你的努力点赞。+1 - Happy Bird
和命名空间 :D - Leon Barkan

3
您需要使用“装饰器”设计模式来包装WebDriver。
public class MyWebDriver : IWebDriver
{
    private IWebDriver webDriver;
    public string CurrentTest { get; set; }

    public MyWebDriver(IWebDriver webDriver)
    {
        this.webDriver = webDriver
    }

    public Method1()
    {
        webDriver.Method1();
    }

    public Method2()
    {
        webDriver.Method2();
    }

    ...
}

然后传入当前正在使用的驱动程序。

var profile = new FirefoxProfile();
MyWebDriver driver = new MyWebDriver(new FirefoxDriver(profile));

这样,您就可以将IWebDriver的接口方法委托给FirefoxDriver,但可以添加适当的任何附加内容。


1
谢谢。这与@LeonBarkan建议的类似,但这似乎是最正确的实现。我已经开始实施它,如果我成功了,我会回报的。 - Milo
我正在尝试实现这个问题,Intellisense 强制要求我实现所有 IWebDriver 方法,其中方法体都是 'throw new NotImplementedException()'。那么在大多数情况下,我如何使用 IWebDriver 默认的方法呢?例如 FindElement 方法:public IWebElement FindElement(By by) { throw new NotImplementedException(); } - Milo
你不需要在MyWebDriver中实现IWebDriver,如果你这样做了,你必须实现(编写)所有接口方法,如FindElement、navigate等等... - Leon Barkan
@Milo 假设MyWebDriver是经理,而FirefoxDriver是员工,经理实现了IWebDriver并说“嘿,看看我能为你做所有这些事情” - 但实际上会发生什么呢?经理已经雇用了FirefoxDriver,因为他也实现了IWebDriver并且“确定”可以将所有责任委托给他。因此,对于您需要实现的每个IWebDriver方法-只需将其委托给在构造函数中传递的驱动程序即可。如何实现呢?public IWebElement FindElement(By by) { return webDriver.FindElement(by); } - Nick Spicer
感谢大家的帮助。最终,我通过在代码中正确的位置实现try/catch来解决了我的初始问题(即适当的测试结果记录)。我进一步提出了另一个与此相关的问题在这里 - 您可以在那里查看答案以找到可能的解决方法。 - Milo
显示剩余3条评论

1
如果你做类似于以下的事情,会怎么样呢?
class MyWebDriver
{
   private IWebDriver driver;
   private static string CurrentTest;
   ....
   //make constractors / getters, setters
}

执行
MyWebDriver d = new MyWebDriver(....)
...

1
有道理!我会尝试实现并在之后报告。谢谢! - Milo

-2

只需使用一个以WebDriver为父类的子类:

public class MyWebDriver : WebDriver
{
    private string _currentTest;
}

然后您可以在任何地方使用MyWebDriver并根据需要设置_currentTest


WebDriver使用IWebDriver接口。我尝试了上面的方法,但是在IntelliSense中没有显示出WebDriver,只有IWebInterface。是否有一种方法可以扩展接口?谢谢。 - Milo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接