C# C中的Selenium WebDriver;由「;类扩展

C# C中的Selenium WebDriver;由「;类扩展,c#,class,selenium,selenium-webdriver,extension-methods,C#,Class,Selenium,Selenium Webdriver,Extension Methods,我一直在一个webdriver项目中工作,以自动化我的测试,并尝试开发类似助手的东西。默认情况下,By类中有CssSelector()、XPath()、ClassName()等方法 我的问题是:我是否可能(以及如何?!)扩展这个类来创建另一个方法来简化我的代码?我希望通过调用我自己的方法。我搜索并得到了一些关于如何创建一个新手的结果,但我认为这会使我的代码在未来变得杂乱无章 Selenium中默认存在的内容: FindElement(By.CssSelector("#example")); 我

我一直在一个webdriver项目中工作,以自动化我的测试,并尝试开发类似助手的东西。默认情况下,By类中有CssSelector()、XPath()、ClassName()等方法

我的问题是:我是否可能(以及如何?!)扩展这个类来创建另一个方法来简化我的代码?我希望通过调用我自己的方法。我搜索并得到了一些关于如何创建一个新手的结果,但我认为这会使我的代码在未来变得杂乱无章

Selenium中默认存在的内容:

FindElement(By.CssSelector("#example"));
我想发展的是:

FindElement(By.MyOwnMethod("example"));
谢谢

在css中,
#
符号是ID选择器。您可以使用
By.Id(string)
方法


编辑:

如果您真的想自定义它,您可以通过定义自己的
实现。但是,您不能扩展静态方法,因此需要创建一个新类来承载它们。在这里,我将通过
使用
,您可以始终使用对您更有意义的名称,如网站名称:

public class Via
{
    public static By AdminMenu(string Id) // could also just use int
    {
        return By.CssSelector(string.Format("[selenium-admin-menu='{0}']", Id));
    }

    public static By ImgSrc(string source)
    {
        return By.CssSelector(string.Format("img[src='{0}']", source));
    }
}

//usage: 
var menu3 = driver.FindElement(Via.AdminMenu("3"));
在css中,
#
符号是ID选择器。您可以使用
By.Id(string)
方法


编辑:

如果您真的想自定义它,您可以通过
定义自己的
实现。但是,您不能扩展静态方法,因此需要创建一个新类来承载它们。在这里,我将通过
使用
,您可以始终使用对您更有意义的名称,如网站名称:

public class Via
{
    public static By AdminMenu(string Id) // could also just use int
    {
        return By.CssSelector(string.Format("[selenium-admin-menu='{0}']", Id));
    }

    public static By ImgSrc(string source)
    {
        return By.CssSelector(string.Format("img[src='{0}']", source));
    }
}

//usage: 
var menu3 = driver.FindElement(Via.AdminMenu("3"));

简而言之,你不应该这样做。这并不能使您的代码更干净,它会使您的代码更难阅读,因为任何具有Selenium经验的人都无法阅读您的代码。不要添加另一层抽象,只需使用编写好的Selenium即可。如果HTML中有多个管理菜单,但这些菜单仅因索引而不同,例如.CssSelector(“[selenium admin menu='3']”)中的

public WebElement getAdminMenu(int index)
{
    return driver.findElement(By.cssSelector("[selenium-admin-menu='" + index + "']"));
}
或者更好的方法是,根据每个管理菜单的实际名称为其创建一个函数,这样该函数的使用者就可以确切地知道该函数的作用,而不必查看页面的HTML并计算管理菜单的数量来返回正确的菜单

public WebElement getAdminMenuManageUsers()
{
    return driver.findElement(By.cssSelector("[selenium-admin-menu='1']"));
}

public WebElement getAdminMenuManageSite()
{
    return driver.findElement(By.cssSelector("[selenium-admin-menu='2']"));
}

显然,这些都是虚构的例子,因为我不知道你的网站。

简而言之,你不应该这样做。这并不能使您的代码更干净,它会使您的代码更难阅读,因为任何具有Selenium经验的人都无法阅读您的代码。不要添加另一层抽象,只需使用编写好的Selenium即可。如果HTML中有多个管理菜单,但这些菜单仅因索引而不同,例如.CssSelector(“[selenium admin menu='3']”)中的

public WebElement getAdminMenu(int index)
{
    return driver.findElement(By.cssSelector("[selenium-admin-menu='" + index + "']"));
}
或者更好的方法是,根据每个管理菜单的实际名称为其创建一个函数,这样该函数的使用者就可以确切地知道该函数的作用,而不必查看页面的HTML并计算管理菜单的数量来返回正确的菜单

public WebElement getAdminMenuManageUsers()
{
    return driver.findElement(By.cssSelector("[selenium-admin-menu='1']"));
}

public WebElement getAdminMenuManageSite()
{
    return driver.findElement(By.cssSelector("[selenium-admin-menu='2']"));
}

显然,这些都是虚构的例子,因为我不知道你的站点。

如果你想让你的驱动程序有使用特定于用例的DOM的快捷方式,你总是可以扩展
IWebDriver
,而不是通过
扩展

using OpenQA.Selenium;

namespace Tests.Selenium.Utils
{
    public static class DriverExtensions
    {
        public static IWebElement FindAdminMenu(this IWebDriver driver, string Id)
        {
            return driver.FindElement(By.CssSelector(
                string.Format("[selenium-admin-menu='{0}']", Id)
            ));
        }
    }
}
然后这一行

沦为

var menu3 = driver.FindAdminMenu("3");
这是一个有趣的故事
FindAdminMenu
可能是不透明的,特别是当你真的在输入时。如果可以更改DOM的编写方式,那么在那里使用人类可读的类名可能会更好


对于人类可读的类,我不关心方便的方法。你所做的和硒没有太大区别,我认为硒通常是一件好事。POM将使测试的操作/业务逻辑层从DOM更改中抽象出来。而且会有DOM更改[与业务逻辑更改一样或更频繁];^)

如果您希望您的驱动程序具有利用特定于用例的DOM的快捷方式,您可以始终扩展
IWebDriver
,而不是通过
扩展

using OpenQA.Selenium;

namespace Tests.Selenium.Utils
{
    public static class DriverExtensions
    {
        public static IWebElement FindAdminMenu(this IWebDriver driver, string Id)
        {
            return driver.FindElement(By.CssSelector(
                string.Format("[selenium-admin-menu='{0}']", Id)
            ));
        }
    }
}
然后这一行

沦为

var menu3 = driver.FindAdminMenu("3");
这是一个有趣的故事
FindAdminMenu
可能是不透明的,特别是当你真的在输入时。如果可以更改DOM的编写方式,那么在那里使用人类可读的类名可能会更好


对于人类可读的类,我不关心方便的方法。你所做的和硒没有太大区别,我认为硒通常是一件好事。POM将使测试的操作/业务逻辑层从DOM更改中抽象出来。而且会有DOM更改[与业务逻辑更改一样或更频繁];^)

是的,我知道。但我想创建自己的选择器,使其成为易于阅读的代码(并更快地开发)。类似于从html中寻找另一个属性并返回其css选择器的方法。类似于.ImgSrc(string)
或.MySeleniumTag(string)
。是的,我可以用CssSelector来做,但是创建一个方法来做,我的代码看起来比反复使用类似的选择器更干净。将.CssSelector(“[selenium admin menu='3']”)的
更改为
By.AdminMenu(“3”)
谢谢。我注意到
By
类不是静态的,所以我可以扩展它。我只有一个名称空间冲突的问题,因为我需要在原始的
by
名称空间中使用更多的类。如果我看不到解决方案,我将下载Selenium源代码并在其中实现该方法,并生成dll(甚至在解决方案中添加Selenium)。因此,我将对您的建议和JeffC建议进行编程,因为我需要在C#编程中了解更多内容,然后选择其中一个进行使用。太谢谢你了!是的,我知道。但我想创建自己的选择器,使其成为易于阅读的代码(并更快地开发)。类似于从html和