如何解决“RSpec::Expectations::ExpectationNotMetError: expected”错误?
Posted
技术标签:
【中文标题】如何解决“RSpec::Expectations::ExpectationNotMetError: expected”错误?【英文标题】:How to resolve "RSpec::Expectations::ExpectationNotMetError: expected" error? 【发布时间】:2016-03-01 15:17:38 【问题描述】:我正在从 XML 中提取一个值并使用该值来检查它是否存在于 PDF 文件中:
我拥有的 XML 是
<RealTimeLetter>
<Customer>
<RTLtr_Acct>0163426</RTLtr_Acct>
<RTLtr_CustomerName>LSIH JHTWVZ</RTLtr_CustomerName>
<RTLtr_CustomerAddress1>887 YPCLY THYZO SU</RTLtr_CustomerAddress1>
<RTLtr_CustomerAddress2 />
<RTLtr_CustomerCity>WOODSTOCK,</RTLtr_CustomerCity>
<RTLtr_CustomerState>GA</RTLtr_CustomerState>
<RTLtr_CustomerZip>30188</RTLtr_CustomerZip>
<RTLtr_ADAPreference>NONE</RTLtr_ADAPreference>
<RTLtr_Addressee>0</RTLtr_Addressee>
</Customer>
</RealTimeLetter>
PDF 文件包含客户名称和地址
LSIH JHTWVZ
887 YPCLY THYZO SU
WOODSTOCK, GA 30188
我正在使用 PDF Reader 和 Nokogiri gems 从 PDF 中读取文本,从 XML 中提取客户名称并检查 PDF 中是否包含客户名称。
PDF阅读器被解析为
require 'pdf_reader'
def parse_pdf
PDF::Reader.new(@filename)
end
@reader = file('C:\Users\ecz560\Desktop\30004_Standard.pdf').parse_pdf
require 'nokogiri'
@xml = Nokogiri::XML(File.open('C:\Users\ecz560\Desktop\30004Standard.xml'))
@CustName = @xml.xpath("//Customer[RTLtr_Loancust='0163426']//RTLtr_CustomerName").map(&:text).to_s
page_index = 0
@reader.pages.each do |page|
page_index = page_index+1
if expect(page.text).to include @CustName
valid_text = "Given text is present in -- #page_index"
puts valid_text
end
end
但我收到一个错误:
RSpec::Expectations::ExpectationNotMetError: expected "LSIH JHTWVZ\n 887 YPCLY THYZO SU\n WOODSTOCK, GA 30188\n Page 1 of 1" to include "[\"LSIH JHTWVZ\"]"
Diff:
@@ -1,2 +1,80 @@
-["LSIH JHTWVZ"]
+ LSIH JHTWVZ
+ 887 YPCLY THYZO SU
+ WOODSTOCK, GA 30188
./features/step_definitions/Letters/Test1_Letters.rb:372:in `block (2 levels) in <top (required)>'
./features/step_definitions/Letters/Test1_Letters.rb:370:in `each'
./features/step_definitions/Letters/Test1_Letters.rb:370:in `/^I validate the PDF content$/'
C:\Users\ecz560\Documents\GitHub\ATDD Local\features\FeatureFiles\Letters\Test1_Letters.feature:72:in `Then I validate the PDF content'
在理解问题在于我比较@Custname 的方式上。 我该如何解决这个问题?
【问题讨论】:
欢迎来到 Stack Overflow。请阅读“minimal reproducible example”。我们没有足够的信息来帮助您,我们无法复制问题。您没有向我们展示完整的错误信息。作为旁注,您对实例变量的使用表明您不了解如何使用它们。此外,在 Ruby 中,我们不会将@CustName
之类的名称用于变量或常量。
我用所有必需的信息编辑了问题。
【参考方案1】:
我看到的一件事是您的 XPath 选择器不起作用。
//Customer[RTLtr_Loancust='0163426']//RTLtr_CustomerName
测试它:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<RealTimeLetter>
<Customer>
<RTLtr_Acct>0163426</RTLtr_Acct>
<RTLtr_CustomerName>LSIH JHTWVZ</RTLtr_CustomerName>
<RTLtr_CustomerAddress1>887 YPCLY THYZO SU</RTLtr_CustomerAddress1>
<RTLtr_CustomerAddress2 />
<RTLtr_CustomerCity>WOODSTOCK,</RTLtr_CustomerCity>
<RTLtr_CustomerState>GA</RTLtr_CustomerState>
<RTLtr_CustomerZip>30188</RTLtr_CustomerZip>
<RTLtr_ADAPreference>NONE</RTLtr_ADAPreference>
<RTLtr_Addressee>0</RTLtr_Addressee>
</Customer>
</RealTimeLetter>
EOT
doc.search("//Customer[RTLtr_Loancust='0163426']//RTLtr_CustomerName").to_xml # => ""
使用一点修改找到<Customer>
节点:
doc.search('//Customer/RTLtr_Acct/text()[contains(., "0163426")]/../..').to_xml
# => "<Customer>\n <RTLtr_Acct>0163426</RTLtr_Acct>\n <RTLtr_CustomerName>LSIH JHTWVZ</RTLtr_CustomerName>\n <RTLtr_CustomerAddress1>887 YPCLY THYZO SU</RTLtr_CustomerAddress1>\n <RTLtr_CustomerAddress2/>\n <RTLtr_CustomerCity>WOODSTOCK,</RTLtr_CustomerCity>\n <RTLtr_CustomerState>GA</RTLtr_CustomerState>\n <RTLtr_CustomerZip>30188</RTLtr_CustomerZip>\n <RTLtr_ADAPreference>NONE</RTLtr_ADAPreference>\n <RTLtr_Addressee>0</RTLtr_Addressee>\n</Customer>"
此时很容易从<Customer>
中的元素中获取内容:
customer = doc.search('//Customer/RTLtr_Acct/text()[contains(., "0163426")]/../..')
customer.at('RTLtr_Acct').text # => "0163426"
customer.at('RTLtr_CustomerAddress1').text # => "887 YPCLY THYZO SU"
【讨论】:
我可以通过使用@CustName = @xml.xpath("//Customer[RTLtr_Loancust='0163426']//RTLtr_CustomerName").map(&:text) 来解决这个问题.first 是的,这会起作用,但这不是你应该如何编写选择器。//
表示从 DOM 顶部开始向下搜索。所以你说从顶部开始找到Customer
然后从顶部开始找到RTLtr_CustomerName
,而不是在Customer
中找到RTLtr_CustomerName
。 //RTLtr_CustomerName
的完整选择器将使用给定的 XML 示例完成相同的操作,但如果您需要特定的客户,更复杂的示例将导致它失败。
我在 XML 文件中尝试了多个客户,它为我提供了我需要的元素。我的 XML 总是很简单。如果我有任何问题,我会尝试你的建议。谢谢你:)【参考方案2】:
if expect(page.text).to include @CustName
expect
不是这样使用的。
在测试中使用期望值来验证您的代码是否按应有的方式工作。它不应该在正常代码中使用。
预期会引发异常并在失败时停止所有代码。它不会返回 true/false - 如果失败,您将无法继续 - 它会像在您的代码中那样(正确地)抛出异常,然后您的所有代码都将停止并且不会再次启动。
您可能想要做的只是检查这样的值:
if page.text.includes?(@CustName)
(注意:我没有对此进行错误测试......您可能需要在谷歌上搜索正确的编写方式并编写类似的实际工作。)
【讨论】:
这里的问题是我存储在@custName 中的值是一个数组 ["LSIH JHTWVZ"]。但我想将它存储为字符串“LSIH JHTWVZ”。我无法找到如何从 XML 中提取元素作为字符串。 1) 这不是您唯一的问题;) 2) 为什么不直接执行以下操作:@custName = @custName.first
从数组中提取字符串?
或@CustName = @xml.xpath("//Customer[RTLtr_Loancust='0163426']//RTLtr_CustomerName").map(&:text).first
使用@CustName = @xml.xpath("//Customer[RTLtr_Loancust='0163426']//RTLtr_CustomerName").map(&:text).first 工作。
如果你能把它放在你的答案中,我可以接受。谢谢你:)以上是关于如何解决“RSpec::Expectations::ExpectationNotMetError: expected”错误?的主要内容,如果未能解决你的问题,请参考以下文章