Selenium-Webdriver:找到元素后获取属性

时间:2013-01-12 00:35:43

标签: ruby selenium-webdriver

我对自动化的东西还是比较新的,所以这听起来像是一个愚蠢的问题。 在发布问题之前,我确实谷歌搜索了它的地狱:)

无论如何,这是问题

我在Android设备上自动化测试 其中一项测试是验证某件商品是否已标记为“收藏” 页面的代码段是:

<li class = "resultItem isFavorite" data-index="2">
<div class="name" data-cis="4ced6feb-3b5c-415a-ae1c-0b8bca8e3c85" onclick="return true">f,f</div>
</li>

我可以在列表中找到el = @driver.find_element(:xpath, "//*[class='name' and text() ='f,f']")的元素。我希望el.class会告诉我resultItem isFavorite。 相反,我得到的是:Selenium:WebDriver :: Element

如果某个项目未标记为收藏,则该字段中不会添加isFavorite标记。 我希望使用isFavorite来验证项目是否被标记为收藏,但我似乎无法将其变为变量。

任何帮助都将不胜感激。

谢谢,

杰夫

4 个答案:

答案 0 :(得分:12)

您真正想要的是以下内容:

# Note: Possibly incorrect Ruby code here. 
# Written from memory.
el = @driver.find_element(:xpath, "/your/xpath/here")
# Could also your el["class"]
element_class_attribute = el.attribute("class")

通常,使用大多数属性名称(如src)(如el.src)会给您一个运行时错误。但是,class在Ruby中具有特殊含义,并且每个对象都有一个class属性,这是Ruby类。

答案 1 :(得分:3)

我在这里读两个问题。首先,简短易行。

问:现在我找到了el,如何访问其类HTML属性?

答:使用el.attribute('class')或其简写el['class']。请参阅Selenium::WebDriver::Element.attribute

现在时间越长。

问:如何测试el表示的项目是否标记为收藏?

答:见下文。

为了给出更好的答案,我需要有关我们正在测试的页面组成的更多信息。我做了一些基本的假设:

  • 该网页包含一个或多个li个元素,其中包含'resultItem'个类,其中一些元素还包含类'isFavorite'
  • 这些li元素中的每一个都有一个或多个子元素,其中一个元素保证为div,类别为'name'
  • 只有一个这样的孩子div会有文字'f,f'

从广义上讲,我们有两种方法可以解决这个问题。

  1. 我们可以找到相关的div,然后验证其父li是否有'isFavorite'类。
  2. 我们可以找到包含课程li的所有'isFavorite'个元素,然后验证其中一个元素是否包含相关的div
  3. 我们需要注意很多事情。

    对于Selenium,XPath选择器擅长通过文本查找,但poor at finding by class。 CSS选择器擅长按类查找,但cannot find by text。这些都不是找到我们追随的div的理想选择。

    如上所述,我们可以使用element['class']获取元素的类(属性)。我们发现,element.class致电Object#class,给我们Selenium::WebDriver::Element。在这种情况下,el['class']为我们提供了字符串'name'。如果在其父元素上调用,我们将获得'resultItem isFavorite'

    我们可以使用element.text获取元素的文本。在这种情况下,el.text会给我们'f,f'。与JavaScript's textContent function一样,它返回元素及其所有后代的文本,因此在父元素上调用text()也会给我们'f,f'。请注意,此方法可能很慢,如果元素以某种方式不可见,则返回空字符串。谨慎使用。有关详细信息,请参阅Selenium::WebDriver::Element.text

    鉴于上述情况,让我们看看方法#1和#2如何发挥作用。 (以下是Ruby 1.9.3。)

    方法#1

    div_elements = @driver.find_elements(:css, 'li > div.name').select { |e| e.text == 'f,f' }
    div_element = div_elements.first
    
    parent_li = div_element.find_element(:xpath, './..')
    parent_li_classes = parent_li['class'].scan(/\S+/)
    if parent_li_classes.include?('isFavorite')
      # PASS
    else
      # FAIL
    end
    

    方法#2

    favorite_items = @driver.find_elements(:css, 'li.isFavorite')
    if favorite_items.any? { |item| item.find_element(:css, 'div.name').text == 'f,f' }
      # PASS
    else
      # FAIL
    end
    

    方法#2,重构

    if @driver.find_elements(:css, 'li.isFavorite').any? { |item| item.text == 'f,f' }
      # PASS
    else
      # FAIL
    end
    

答案 2 :(得分:0)

我能够通过另一种方式解决这个问题:

element = @driver.find_elements(:class, "isFavorite")
element.each do |t|
   if t.text() == 'f,f' then
       result = "pass"
   end
end

我有一种感觉,如果列表很长,这可能会很慢......但至少它有效:)

由于

杰夫

答案 3 :(得分:0)

<强>红宝石

element.GetAttribute("attribute name");

<强>的Python

this.server = new WebSocket.Server({
   port: this.config.port,
   verifyClient: this.authenticate.bind(this)
});

<强>爪哇

this.api = express.createServer({
  key: config.certs.key,
  cert: config.certs.cert,
  dhparam: config.certs.dh,
  secureOptions: constants.SSL_OP_NO_SSLv3 | constants.SSL_OP_NO_SSLv2
});
this.api.use(helmet.hsts({
  maxAge: 31536000000,
  includeSubdomains: true,
  force: true
}));

<强> C#

df = pd.DataFrame(dict(A=['s', np.nan], B=['s', 'x'], C=[np.nan, 'x']))