Kevin
Kevin

Reputation: 15954

How do I test a script using RSpec?

I'm writing a script that will be run using rails runner on production to make some one-time changes to our database. I want to be sure that the script works as expected before we run it, so I'm writing RSpec tests to verify its behavior while I write it.

How can I invoke the script in my test examples? The script isn't a class or a module, so there aren't individual functions for me to test. Instead, the entire script will be loaded once, run from top to bottom, and then exited. I'm not sure how to invoke that from within an RSpec test.

I'm looking for something like:

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

Upvotes: 1

Views: 1915

Answers (4)

sah
sah

Reputation: 11

I would move the logic from the script into its own class. Then you can invoke the class in your script and in your tests or even when you're in the rails console. I've been using this pattern for a while and its pretty useful.

Upvotes: 1

sevensidedmarble
sevensidedmarble

Reputation: 683

We can help you with this, but this:

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

Is what migrations are for. One time changes like this to the db should be done in a migration. This circumvents the need for rspec, as any changes like this should be reversible, as migrations should be.

Upvotes: 0

Steve Redka
Steve Redka

Reputation: 218

I think you want to use system:

system('rails runner my_script.rb')

edit #1

If you are willing to butcher the script, you can move the active components of your script into separate module and require that:

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

Then, in test:

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

Upvotes: 0

Kevin
Kevin

Reputation: 15954

It looks like I can use Kernel#load to execute the script:

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

Upvotes: 0

Related Questions