GVKun编程网logo

在Selenium C#中使用PageFactory / FindsBy时如何初始化SelectElements?(selenium find_element_by_class)

8

如果您想了解在SeleniumC#中使用PageFactory/FindsBy时如何初始化SelectElements?和seleniumfind_element_by_class的知识,那么本篇文章

如果您想了解在Selenium C#中使用PageFactory / FindsBy时如何初始化SelectElements?selenium find_element_by_class的知识,那么本篇文章将是您的不二之选。我们将深入剖析在Selenium C#中使用PageFactory / FindsBy时如何初始化SelectElements?的各个方面,并为您解答selenium find_element_by_class的疑在这篇文章中,我们将为您介绍在Selenium C#中使用PageFactory / FindsBy时如何初始化SelectElements?的相关知识,同时也会详细的解释selenium find_element_by_class的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

在Selenium C#中使用PageFactory / FindsBy时如何初始化SelectElements?(selenium find_element_by_class)

在Selenium C#中使用PageFactory / FindsBy时如何初始化SelectElements?(selenium find_element_by_class)

我正在使用PageFactory在Selenium WebDriver for C#中构建页面对象模型。

不幸的是,我发现FindsByAttribute不会初始化SelectElement(HTML
<select>标签/下拉菜单)。到目前为止,我已经遇到或想出了一些解决方案,但没有一个是理想的:

  1. PageFactory并且FindsByAttributesealed,因此我不能仅通过继承它们来强制使用。
  2. 在每种方法中SelectElement从实例手动实例化a IWebElement都是很麻烦且重复的。除非我每次都添加一个等待,否则它也会忽略明显的内置等待PageFactory并抛出NoSuchElementExceptions,这将需要在各处重复定位器,从而破坏了POM的(部分)用途。
  3. IWebElement属性包装每个属性的SelectElement麻烦程度较小,但仍存在与上述相同的等待问题。

到目前为止,最好的选择是#3,为此编写一个包装器SelectElement只会给每个方法增加一个等待时间。尽管此解决方案可以 工作
,但它将大量堆积每个页面的代码,而不是下面的(假设的)漂亮代码:

[FindsBy(How = How.Id, Using = "MonthDropdown")]public SelectElement MonthDropdown;

我被包装纸包裹住了(我宁愿避免),并且:

[FindsBy(How = How.Id, Using = "MonthDropdown")]private IWebElement _monthDropdown;public Selector MonthDropdown{    get { return new Selector(MonthDropdown, Wait); }}

随着Selector作为SelectElement包装,也必须采取的IWait<IWebDriver>,因此它可以等待,和一个新的实例Selector访问它的每一次。

有更好的方法吗?

编辑: 悄悄地放错了访问修饰符。固定。谢谢@JimEvans。

答案1

小编典典

首先,.NET PageFactory实现中没有“内置等待”
。您可以在调用中轻松指定一个InitElements(稍后对此进行详细说明)。目前,最适合您的选择是您的选择3,尽管我不会公开该IWebElement成员。我会做到的private,因为PageFactory可以像枚举公共成员一样轻松地枚举私有成员。因此您的页面对象将如下所示:

[FindsBy(How = How.Id, Using = "MonthDropdown")]private IWebElement dropDown;public SelectElement MonthDropdownElement{    get { return new SelectElement(dropdown); }}

IWebElement在需要时如何获得实际值?自从SelectElement实现以来IWrappedElementWrappedElement如果您需要访问IWebElement接口提供的元素的方法和属性,则可以简单地调用属性。

.NET绑定的最新版本已将重组PageFactory为更可扩展。要添加所需的“内置等待”,可以执行以下操作:

// Assumes you have a page object of type MyPage.// Note the default timeout for RetryingElementLocator is// 5 seconds, if unspecified.// The generic version of this code looks like this:// MyPage page = PageFactory.InitElements<MyPage>(new RetryingElementLocator(driver), TimeSpan.FromSeconds(10));MyPage page = new MyPage();PageFactory.InitElements(page, new RetryingElementLocator(driver, TimeSpan.FromSeconds(10)));

此外,如果您 确实
需要自定义事物的工作方式,那么始终欢迎您实施IPageObjectMemberDecorator,它使您可以完全自定义枚举属性的方式以及将值设置为用这些属性修饰的属性或字段的方式。的(非泛型)重载之一PageFactory.InitElements采用对象实现的实例IPageObjectMemberDecorator

我将撇开严格定义的页面对象模式的正确实现,不要在每个页面对象之外公开任何WebDriver对象。否则,您所实现的只是一个“页面包装器”,这是一种非常有效的方法,而不是所谓的“页面对象”。

document.all与getElementById、getElementsByName、getElementsByTagName用法区别

document.all与getElementById、getElementsByName、getElementsByTagName用法区别

理解这句话可看以下:
例1(这个可以让你理解文档中哪些是对象) 

 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
  <html xmlns="http://www.w3.org/1999/xhtml"> 
  <head> 
  <title>Document.All Example</title> 
  <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> 
  </head> 
  <body> 
  <h1>Example Heading</h1> 
  <hr /> 
  <p>This is a <em>paragraph</em>. It is only a <em>paragraph.</em></p> 
  <p>Yet another <em>paragraph.</em></p> 
  <p>This final <em>paragraph</em> has <em id="special">special emphasis.</em></p> 
  <hr /> 
  <script type="text/javascript"> 
  <!-- 
  var i,origLength; 
  origLength = document.all.length; 
  document.write(&#39;document.all.length=&#39;+origLength+"[br /]"); 
  for (i = 0; i < origLength; i++) 
  { 
  document.write("document.all["+i+"]="+document.all[i].tagName+"[br /]"); 
  } 
  //--> 
  </script> 
  </body> 
  </html>
登录后复制

输出结果

Example Heading 
  This is a paragraph. It is only a paragraph. 
  Yet 
another paragraph. 
  This final paragraph has special emphasis. 
  document.all.length=18 
  document.all[0]=! 
  document.all[1]=HTML 
  document.all[2]=HEAD 
  document.all[3]=TITLE 
  document.all[4]=META 
  document.all[5]=BODY 
  document.all[6]=H1 
  document.all[7]=HR 
  document.all[8]=P 
  document.all[9]=EM 
  document.all[10]=EM 
  document.all[11]=P 
  document.all[12]=EM 
  document.all[13]=P 
  document.all[14]=EM 
  document.all[15]=EM 
  document.all[16]=HR 
  document.all[17]=SCRIPT
登录后复制

可以通过ID,NAME或INDEX属性访问某个具体的元素
例2(访问一个特定元素)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
  "http://www.w3.org/TR/html4/loose.dtd"> 
  <html> 
  <head> 
  <meta http-equiv="Content-Type" content="text/html; 
charset=gb2312"> 
  <title>单击DIV变色</title> 
  <style 
type="text/css"> 
  <!-- 
  #docid{ 
  height:400px; 
  width:400px; 
  background-color:#999;} 
  --> 
  </style> 
  </head> 
  <body><p id="docid" 
name="docname" onClick="bgcolor()"></p> 
  </body> 
  </html> 
  <script language="javascript" 
type="text/javascript"> 
  <!-- 
  function bgcolor(){ 
  document.all[7].style.backgroundColor="#000" 
  } 
  --> 
  </script> 
  上面的这个例子让你了解怎么访问文档中的一个特定元素,比如文档中有一个DIV 
  <p 
id="docid" name="docname"></p>,你可以通过这个DIV的ID,NAME或INDEX属性访问这个DIV: 
  document.all["docid"] 
  document.all["docname"] 
  document.all.item("docid") 
  document.all.item("docname") 
  document.all[7] 
  document.all.tags("p")则返回文档中所有DIV数组,本例中只有一个DIV,所以用document.all.tags("p")[0]就可以访问了。
登录后复制

可以用document.all["元素名"].属性名="属性值"来动态改变元素的属性。用这条语句,可以做出许许多多动态网页效果,如:动态变换图片、动态改变文本的背景、动态改变网页的背景、动态改变图片的大小、动态改变文字的大小各颜色等等

<script language="JavaScript"> 
function cardClick(cardID){ 
var 
obj; 
for (var i=1;i<7;i++){ 
obj=document.all("card"+i); 
obj.style.backgroundColor="#3A6EA5"; 
obj.style.color="#FFFFFF"; 
} 
obj=document.all("card"+cardID); 
obj.style.backgroundColor="#FFFFFF"; 
obj.style.color="#3A6EA5"; 

for (var i=1;i<7;i++){ 
obj=document.all("content"+i); 
obj.style.display="none"; 
} 
obj=document.all("content"+cardID); 
obj.style.display=""; 
} 
</script>
登录后复制

document.all可以判断浏览器是否是IE
if(document.all){
alert("is IE!");
}
使用document.all注意的地方
代码1:

<input name=aaa value=aaa> 
<input id=bbb value=bbb> 
<script language=Jscript> 
alert(document.all.aaa.value) 
//根据name取value 
alert(document.all.bbb.value) //根据id取 value 
</script>
登录后复制

代码2:
但是常常name可以相同(如:用checkbox取用户的多项爱好的情况)

<input name=aaa value=a1> 
<input name=aaa value=a2> 
<input id=bbb value=bbb> 
<script language=Jscript> 
alert(document.all.aaa(0).value) //显示a1 
alert(document.all.aaa(1).value) 
//显示a2 
alert(document.all.bbb(0).value) //这行代码会失败 
</script>
登录后复制

代码3:理论上一个页面中的id是互不相同的,如果出现不同tags有相同的id

document.all.id 就会失败,就象这样: 
<input id=aaa value=a1> 
<input 
id=aaa value=a2> 
<script language=Jscript> 
alert(document.all.aaa.value) //显示 undefined 而不是 a1或者a2 
</script>
登录后复制

代码4:
对于一个复杂的页面(代码很长,或者id是由程序自动产生),或着一个
javascript初学者写的程序,很有可能出现两个tags有相同id的情况。
为了编程的时候不出错,我推荐这样的写法:

<input id=aaa value=aaa1> 
<input id=aaa value=aaa2> 
<input name=bbb value=bbb> 
<input name=bbb value=bbb2> 
<input id=ccc value=ccc> 
<input name=ddd value=ddd> 
<script language=Jscript> 
alert(document.all("aaa",0).value) 
alert(document.all("aaa",1).value) 
alert(document.all("bbb",0).value) 
alert(document.all("bbb",1).value) 
alert(document.all("ccc",0).value) 
alert(document.all("ddd",0).value) 
</script>
登录后复制

这样最安全.
以下是我自己的测试:

 
<html> 
<head> 
<title> 
document.all test 
</title> 
<script language="javascript"> 
function view() 
{ 
/* 
//通过name两种访问格式 
alert(document.all.aaa.value); 
alert(document.all["aaa"].value); 
//通过id的两种访问格式 
alert(document.all.ccc.value); 
alert(document.all["ccc"].value); 
*/ 
//当一页中存在两个name相同的input时不能使用上面的访问方法,因为将返回undefine,请使用下面方式访问 
alert(document.all.aaa(0).value); 
alert(document.all.aaa(1).value); 
//安全的写法 
alert(document.all("aaa",0).value); 
alert(document.all("aaa",1).value); 
} 
</script> 
</head> 
<body> 
<form name="form1" id="f1"> 
<input type="text" name="aaa" > 
<input type="text" name="aaa" id="ccc"> 
<input type="button" name="bbb" value="click" onclick="view();"> 
</form> 
</body> 
</html>
登录后复制

从上面可以看到我们在使用document.all的时候可能会返回一个值或多个值的情况,所以使用之前一定要判断长度,要不然会出现错误。
如下面的问题:两个函数对多个checkbox进行处理,分别执行全部选中和取消全选功能如果按下面使用会出现什么问题呢?

 
<HTML> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
function checkall(){ 
var huang = document.all[&#39;huang&#39;]; 
for(i = 0;i < huang.length;i++){ 
if(huang[i].type == "checkbox") 
{ 
huang[i].checked = true; 
} 
} 
} 
function centerall(){ 
var huang = document.all[&#39;huang&#39;]; 
for(i = 0;i < huang.length;i++){ 
huang[i].checked = false; 
} 
} 
//--> 
</SCRIPT> 
<BODY> 
<input type="checkbox" name="huang" value="OFF"> 
<input type="checkbox" name="huang" value="OFF"> 
<input type="checkbox" name="huang" value="OFF"> 
<br> 
<input type="button" value = "checkall" onclick = "checkall();"> 
<input type="button" value = "centerall" onclick = "centerall();"> 
</BODY> 
</HTML>
登录后复制

看上面的代码,当表单中有多个checkbox的时候是没有问题的,但当其中只有一个checkbox的时候就会有问题,即点全选的时候不起作用,因为当其中只有一个checkbox的时候不再用document.all["huang"][0].checked来访问,而是直接用document.all["huang"].checked来访问了
看当只有一个checkbox的时候应改成下面代码

<HTML> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
function 
checkall(){ 
var huang = document.all[&#39;huang&#39;]; 
if(huang.length){ 
for(i = 0;i < huang.length;i++){ 
if(huang[i].type == "checkbox") 
{ 
huang[i].checked = true; 
} 
} 
}else{ 
huang.checked = 
true; 
} 
} 
function centerall(){ 
if(huang.length){ 
for(i = 
0;i < huang.length;i++){ 
if(huang[i].type == "checkbox") 
{ 
huang[i].checked = false; 
} 
} 
}else{ 
huang.checked = false; 
} 
} 
//--> 
</SCRIPT> 
<BODY> 
<input 
type="checkbox" name="huang" value="OFF"> 
[br] 
<input 
type="button" value = "checkall" onclick = "checkall();"> 
<input 
type="button" value = "centerall" onclick = "centerall();"> 
</BODY> 
</HTML>
登录后复制

或者使用另一种形式,使用getElementsByTagName,如下:

<HTML> 
<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
function 
checkall() 
{ 
var huang = document.getElementsByTagName("input"); 
for(i = 0;i < huang.length;i++){ 
if(huang[i].type == "checkbox") 
{ 
huang[i].checked = true; 
} 
} 
} 
function centerall() 
{ 
var huang = document.getElementsByTagName("input"); 
for(i = 0;i 
< huang.length;i++){ 
if(huang[i].type == "checkbox") 
{ 
huang[i].checked = false; 
} 
} 
} 
//--> 
</SCRIPT> 
<BODY> 
<input type="checkbox" name="huang" value="OFF"> 
[br] 
<input type="button" value = "checkall" onclick = 
"checkall();"> 
<input type="button" value = "centerall" onclick = 
"centerall();"> 
</BODY> 
</HTML>
登录后复制

document.all与getElementById、getElementsByName、getElementsByTagName用法区别-getElementById_javascript技巧

document.all与getElementById、getElementsByName、getElementsByTagName用法区别-getElementById_javascript技巧

不过,如果您需要查找文档中的一个特定的元素,最有效的方法是 getElementById()。
不过要注意的是使用getElementById时对不同的浏览器执行的结果可能是不同的,以下有相关说明

复制代码 代码如下:

text1:



text2:





我在IE中测试了上面的代码,在第一个文本框中输入1,在第二个文本框中输入2,然后点下面的两个按钮,猜一下结果是什么?
我本意是按钮1返回第一个文本框的值,按钮2返回个文本框的值。
结果是两个按钮都返回了第一个文本框的值。
说明ie执行document.getElementById(elementName)的时候,返回的是第一个name或者id等于elementName的对象,并不是按照ID来查找的。
在fireFox中不存在这样的问题,fireFox执行document.getElementById(elementName)的时候只查找id等于elementName的对象,如果不存在则返回null。
可能IE是考虑的兼容性的问题才这么做的。

以下是我测试所用的代码:

[Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

这个时候我在两个text中输入的值分别为:eee, www
IE中测试结果为:eee , eee
再看当我把中的id去除时,也即上面代码使用注释中的内容时
我同样输入eee, www
IE中测试结果为:www ,eee
仔细分析上面两个测试的结果:得出结论是:每执行getElementById一次,会将web页面中的所有表单按顺序遍历一次,同时查找id,name两个值,如果存在所要找的id则不再继续查找,如果没有相应的id与之对应则看name值是否与之对应,如果有相应的name与之对应,则不再继续查找。也就是说:
ie执行document.getElementById(elementName)的时候,返回的是第一个name或者id等于elementName的对象,并不是仅按照ID来查找的。
而同样的两个测试在firefox下第一个结果为eee,www,而第二个结果因为没有找到id="ccc"所以返回null
对于这个结果还可参见
http://www.jb51.net/article/16852.htm
他还对getElementById与getElementByName进行了分析,值得一看。

JavaScript 中的 querySelector 和 querySelectorAll 与 getElementsByClassName 和getElementById

JavaScript 中的 querySelector 和 querySelectorAll 与 getElementsByClassName 和getElementById

我想知道querySelectorquerySelectorAll反对
getElementsByClassName和之间到底有什么区别getElementById

从这个链接我可以收集到,querySelector我可以写document.querySelector(".myclass")来获取带有
class 的元素myclassdocument.querySelector("#myid")获取带有 ID
的元素myid。但我已经可以做到这一点getElementsByClassName并且getElementById. 应该首选哪一个?

我也在XPages中工作,其中 ID
是用冒号动态生成的,看起来像这样view:_id1:inputText1。所以当我写document.querySelector("#view:_id1:inputText1")它不起作用。但写作document.getElementById("view:_id1:inputText1")有效。任何想法为什么?

jquery-selectors – Selenium WebDriver PageFactory使用jQuery Selector FindsBy?

jquery-selectors – Selenium WebDriver PageFactory使用jQuery Selector FindsBy?

为了解释我的问题,我给出了一个小方案:

说我有一个登录页面.

public class LoginPage
{
    [FindsBy(How = How.Id,Using = "SomeReallyLongIdBecauSEOfAspNetControlsAndPanels_username"]
    public IWebElement UsernameField { get; set; }

    [FindsBy(How = How.Id,Using = "SomeReallyLongIdBecauSEOfAspNetControlsAndPanels_password"]
    public IWebElement PasswordField { get; set; }

    [FindsBy(How = How.Id,Using = "submitButtonId")]
    public IWebElement SubmitButton { get; set; }

    private readonly IWebDriver driver;

    public LoginPage(IWebDriver driver)
    {
        this.driver = driver;

        if(!driver.Url.Contains("Login.aspx"))
        {
            throw new NotFoundException("This is not the login page.");
        }
        PageFactory.InitElements(driver,this);
    }

    public HomePage Login(Credentials cred)
    {

       UsernameField.sendKeys(cred.Username);
       PasswordField.SendKeys(cred.Password);
       SubmitButton.Click();

       return new HomePage(driver);
    }

}

[TestFixture]
public class Test : TestBase
{
    private IWebDriver driver;

    [SetUp]
    public void SetUp()
    {

       driver = StartDriver(); // some function which returns my driver in a wrapped event or something so I can log everything it does.
    }

    [Test]
    public void test()
    {
        new LoginPage(driver)
                .Login(new Credentials 
                           { Username = "username",Password = "password" })
                .someHomePageFunction()

    }

最后,我知道页面配置会发生变化,id会大致保持不变,但是我的项目的情况正在迅速改变.我知道xPath是另一种选择,但是由于页面是如何基于某些标准生成的,所以这仍然会变得很痛苦,因为路径并不总是相同的.

使用上面的当前代码,页面被加载,PageFactory init是通过Page Constructor的元素.太棒了这就是我目前使用的.

目前,如果某些事情并非总是在页面上生成,直到某一步骤.我通常会做以下事情:

private const string ThisIsTheUserNameFieldId = "usernamefield";

然后使用以下命令启动webdriver:

// Navigate to login page

// code here

// Enter in credentials

driver.FindElement(By.Id(ThisIsTheUserNameFieldId)).SendKeys(cred.Username);

不像PageFactory那样结构良好,但它肯定是我无法解决的要求.

我最近遇到了一些与C#.Net一起使用的jQuery Selector代码,它扩展了RemoteWebDriver的功能,我可以使用jQuery选择器在页面上查找我的Elements.

Selenium jQuery for C#.Net (Including Source)

// So I can do things like this:
driver.FindElement(By.jQuery("a").Find(":contains('Home')").Next())

有谁知道如何扩展Selenium WebDriver中的[FindsBy]属性,以便可以使用类似下面的内容(伪代码)?

[FindsBy(How = How.jQuery,Using = "div[id$='txtUserName']")]
public IWebElement UsernameField { get; set; }

解决方法

这不会扩展[FindsBy],但是你知道你可以使用javascript返回的元素吗?

var driver = new FirefoxDriver { Url = "http://www.google.com" };
var element = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript("return document.getElementsByName('q')[0];");
element.SendKeys("hello world");

您可以通过首先注入jquery(取自JQuerify并修改)来轻松扩展它以允许jquery选择器:

const string js =
     @"{var b=document.getElementsByTagName('body')[0]; if(typeof jQuery=='undefined'){var script=document" +
     @".createElement('script'); script.src='http://code.jquery.com/jquery-latest.min.js';var head=document" +
     @".getElementsByTagName('head')[0],done=false;script.onload=script.onreadystatechange=function(){if(!" +
     @"done&&(!this.readyState||this.readyState=='loaded'||this.readyState=='complete')){done=true;script." +
     @"onload=script.onreadystatechange=null;head.removeChild(script);}};head.appendChild(script);}}";
((IJavaScriptExecutor)driver).ExecuteScript(js);

然后运行javascript来选择你想要的元素:

var driver = new FirefoxDriver { Url = "http://www.google.com" };
var element = (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(@"return $('input[name*=""q""]')[0];");
element.SendKeys("hello world");

关于在Selenium C#中使用PageFactory / FindsBy时如何初始化SelectElements?selenium find_element_by_class的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于document.all与getElementById、getElementsByName、getElementsByTagName用法区别、document.all与getElementById、getElementsByName、getElementsByTagName用法区别-getElementById_javascript技巧、JavaScript 中的 querySelector 和 querySelectorAll 与 getElementsByClassName 和getElementById、jquery-selectors – Selenium WebDriver PageFactory使用jQuery Selector FindsBy?的相关信息,请在本站寻找。

本文标签:

上一篇什么是PHPSESSID?(什么是妇科白斑)

下一篇使用Python使用Selenium设置chromedriver代理身份验证(python selenium 代理)