如何使用 RSpec 测试脚本?

How do I test a script using RSpec?

我正在编写一个脚本,该脚本将 运行 在生产环境中使用 rails runner 对我们的数据库进行一些一次性更改。我想确保脚本在我们 运行 之前按预期工作,所以我正在编写 RSpec 测试来验证它在我编写时的行为。

如何在测试示例中调用脚本?该脚本不是 class 或模块,因此没有单独的功能供我测试。相反,整个脚本将加载一次,运行 从上到下,然后退出。我不确定如何从 RSpec 测试中调用它。

我正在寻找类似的东西:

describe "my script" do
  it "should create the correct record" do
    before_count = Orders.count

    rails runner my_script.rb # What goes here?

    expect(Orders.count).to eq(before_count + 1)
  end
end

我想你想使用 system:

system('rails runner my_script.rb')

编辑 #1

如果您愿意修改脚本,您可以将脚本的活动组件移动到单独的模块中,require 即:

# my_script.rb
require './lib/my_script.rb'
MyScript.call()
# lib/my_script.rb
module MyScript
  def self.call
    # your code
  end
end

然后,在测试中:

require './lib/my_script.rb'

describe "my script" do
  it "should create the correct record" do
    before_count = Orders.count

    MyScript.call() # here

    expect(Orders.count).to eq(before_count + 1)
  end
end

我会将脚本中的逻辑移到它自己的 class 中。然后,您可以在脚本和测试中甚至在 rails 控制台中调用 class。我已经使用这个模式一段时间了,它非常有用。

看来我可以使用Kernel#load来执行脚本:

describe "my script" do
  it "should create the correct record" do
    before_count = Orders.count

    load(Rails.root.join("path", "to", "my-script.rb")

    expect(Orders.count).to eq(before_count + 1)
  end
end

我们可以帮助您解决这个问题,但是:

I'm writing a script that will be run using rails runner on production to make some one-time changes to our database.

是迁移的目的。像这样对数据库的一次更改应该在迁移中完成。这避免了对 rspec 的需要,因为像这样的任何更改都应该是 可逆的 ,因为迁移应该是。