【问题标题】:Capybara/Rspec: Filling out Multiple Radio buttonsCapybara/Rspec:填写多个单选按钮
【发布时间】:2016-07-29 17:01:11
【问题描述】:

我认为可能有更好的方法来做到这一点,然后复制粘贴 100 次。

但本质上,我有一个包含很多单选按钮(准确地说是 95 个)的表单页面。我正在使用page.find(:xpath)trigger('click')

Xpath 看起来有点像这样:

page.find(:xpath, '/html/body/div/div[2]/div/div[2]/form/div[2]/table/tbody/tr[1]/td[2]/div/label').trigger('click')

每行单选按钮选项的 TR[x] 都会上升,其中 TD[x] 是要选择的 (1-10)

我真的只需要为每个 TD 选择一个 1-10 之间的随机数,用于自动化测试(只是为了确保它有效)。

某种 for 循环会完成这个吗?类似的东西:(我不熟悉 ruby​​,但这是我从快速谷歌中提取的)

for i in 1..85
   $h = 1 + rand(10)
   page.find(:xpath, '/html/body/div/div[2]/div/div[2]/form/div[2]/table/tbody/tr[i]/td[h]/div/label').trigger('click')
end

这行得通吗?

编辑:这是一行的 HTML:

<tr class="all no-rate complete" data-original="2" change-check="false" the-row="17">
<td class="face">
<td class="face">
<td class="face">
<td class="face">
<div class="radio-inline radio-inline--empty">
<input id="set_stuff_17_rating_3" type="radio" name="set[stuff][17][rating]" value="3" data-control="" data-rating="" filter-class="complete">
<label class="integer opt" for="set_stuff_17_rating_3">Number Rating</label>
</div>
</td>
<td class="face">
<td class="face">
<td class="face">

【问题讨论】:

  • 所有表格或 div 都没有类或 id 或文本来识别它们吗?使用像这样的长 xpath 确实会导致非常脆弱的测试。如果我不得不使用那个xpath,我会做rows = page.all(:xpath, '/html/body/div/div[2]/div/div[2]/form/div[2]/table/tbody/tr', count: 85); rows.each { |row| row.find(:xpath, ".//td[#{rand(10)+1}]/div/label").click }之类的事情,因为我认为它可以更清楚地说明发生了什么(不确定你在问题中提到的应该是85还是95,而在你的代码中提到了另一个跨度>
  • @TomWalpole 他们都共享相同的类名(所以这不起作用),我尝试过使用 ID ......但无论出于何种原因,水豚的“选择”选择器方法都不会工作。我不得不将“查找”与 xpath 选择器一起使用。我不确定为什么 id 不起作用,因为它看起来应该但选择器只是不想工作(我的超时设置为 10 秒,所以它有足够的时间)
  • 但是祖先表没有id吗?或类似的东西?我猜选择不起作用,因为单选/复选框是隐藏的-这就是您单击标签的原因(如果单选/复选框不可见,FYI Capybara 2.8 发布时将自动单击标签)-如果可以,只需附加页面的整个 html 以便我们查看
  • 原来我实际上可以使用 find_by_id,但是对于我必须使用的所有内容 .trigger('click') (我认为单选按钮本身与单选按钮所在的框重叠(通过查看屏幕截图)。所以我将把所有东西都改成那个(这将使它不那么脆弱)
  • 而不是使用trigger,您应该修复页面(使屏幕更宽,或任何必要的) - 如果您使用触发器,您实际上并没有测试用户是否可以点击它

标签: rspec capybara


【解决方案1】:

鉴于页面实际结构的更新信息,类似于

page.all("table.table--ratings tbody tr", minimum: 85).each do |row|  
  row.all("td label").sample.click
end

如果没有大而脆弱的 XPath 表达式,将执行所要求的操作。

【讨论】:

  • 我想我理解 page.all 语句中除了 tbody tr 之外的所有内容,这究竟是什么意思?抱歉所有问题
  • 它是一个 CSS 选择器,是 tbody 的 tr 后代 - 如果您有一个带有 tr 子代的 thead 元素,则需要将其指定为 tbody 的后代
  • css 选择器的 " " 和 ' ' 有什么区别(你现在有什么意义)。我认为在 capybara 中定义 css 时需要将 ':css' 放在开头?
  • 有一个与 Capybara 的 README 链接的邮件列表 - groups.google.com/group/ruby-capybara 并且人们有时会在 gitter.im/jnicklas/capybara 上查看
  • 比 XPath 好得多,.sample 使它更干净。 +1
【解决方案2】:

你可以遍历每一行:

page.all(:xpath, '/html/body/div/div[2]/div/div[2]/form/div[2]/table/tbody/tr').each do |el|
  $h = 1 + rand(10)
  el.find(:xpath, './td[#{h}]/div/label').click
end

请注意,您应该重构您的 XPath 以使其更易于维护。

使用您提供的 HTML:

page.all(:xpath, "//form//tr[td[@class='face']]").each do |el|
  h = 1 + rand(10)
  el.find(:xpath, "(.//input[@type='radio'])[#{h}]").click
end

【讨论】:

  • 如何重构 Xpath?我知道 Xpath 很脆弱,但不确定“正确”的做法。
  • @msmith1114 显示祖先html
  • @msmith1114,您的 Xpath 应该与具有 id 或特定属性/类的元素相关。您最初是如何获得这个 XPath 的? Google Chrome 中的开发工具应该提供更好的工具。请注意,您也可以使用 CSS 选择器。
  • 我在元素上使用了firebug(然后右键单击-->复制xpath)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-28
  • 1970-01-01
  • 1970-01-01
  • 2018-08-19
  • 2018-08-04
相关资源
最近更新 更多