使用 RSpec 为 TDD/BDD 建立帮助

Build up help for TDD/BDD with RSpec

大约 2 周前我开始学习 Ruby,我使用 'open-uri' 和 'nokogiri' 制作了一个 WebParser / Page WordCounter。所以我只是 运行 使用 'ruby counter.rb http://test.com word' 和我以及那个词的匹配数量,不区分大小写,所以我可以抓住一切。

所以我在这里学习 RSpec、TDD、BDD 和所有这些东西,我想知道如何使用 RSpec 示例和期望来构造我的代码。我已经阅读了所有文档,我正在构建简单的示例进行测试等。

我想知道是否有人可以将我的代码构建到 RSpec 示例和期望中,这样我就可以研究你做了什么以及你是怎么做的。

这是我的代码:

require 'open-uri'
require 'nokogiri'

class Counter   

    def initialize(url)
      @url = url
    end

    def count(word, url)
      doc = Nokogiri::HTML(open(url))
      doc.css('head').remove
      doc.text.scan(/#{word}/i).size
    end
end

url, word = ARGV
puts "Found: #{Counter.new(url).count(word, url)} matches."

希望有人能帮助我,我真的很喜欢 ruby 并且发现这个 RSpec 太棒了,

谢谢大家,我会学习等待的!

有一个 rspec --init 命令可以创建您的样板文件。

完成此操作后,打开 spec_helper.rb 并需要您的代码文件。

顺便说一下,您的初始化接受 url 并将其分配给实例变量有点奇怪,但是 count 方法将 url 作为参数。

所以假设它被重构为:

attr_reader :url
def initialize(url)
  @url = url
end

def count(word)
  doc = Nokogiri::HTML(open(url)) # this uses the attr_reader
  doc.css('head').remove
  doc.text.scan(/#{word}/i).size
end

那么你可以这样写一个测试用例(这里不是全面覆盖,只是一个例子):

describe "Counter" do
  let(:url) { "http://some_url" }
  let(:counter) { Counter.new url }
  it "counts words" do
    expect(counter.count("foo")).to(
      eq("<whatever the expected result is>")
    )
  end
end

使用let设置变量是可选的。您也可以在 it ... do 块内设置变量,但您必须对每种情况重复一次。

除了.to你还有.not_to,除了eq还有很多有用的方法。我建议阅读 RSpec 匹配器文档以熟悉这些内容。

还值得一提的是,此测试用例将进行 HTTP 调用,有时需要,有时不需要。例如,如果您有很多案例并希望快速 运行 它们,那么删除 HTTP 调用将是有益的。但是这样做意味着您实际上不再测试 url 的状态。如果标记发生变化怎么办?除非您的测试用例实际进行了 HTTP 调用,否则您无法确定。

不过,了解如何删除 HTTP 调用还是有好处的,因为基础概念("mocking" 或 "stubbing")有很多用途。像这样:

  it "counts words" do
    mock_html = <<-HTML
      <!doctype html>
      <html lang='en'>
        <head></head>
        <body>foo</body>
      </html>
    HTML
    expect(Object).to(
      receive(:open).with(any_args).at_least(1).times.and_return(mock_html)
    )
    expect(counter.count("foo")).to eq(1)
    expect(counter.count("bar")).to eq(0)
  end

any_args 是一个可以在存根方法时使用的特殊术语。你也可以在这里使用 url 因为你知道传递的参数是什么。

有关更多信息,我将再次向您推荐 RSpec 的文档,这次是关于模拟/存根的文档。

通常您希望主要关注 input/output 函数。有时您会想要检查是否调用了另一个方法(为此您会使用 mock/stub),但您可能不希望您测试每一行代码。