synapse
synapse

Reputation: 5728

Performance testing with RSpec

I'm trying to incorporate performance tests into a test suite for non-Rails app and have a couple problems.

  1. I don't need to run perf tests every time, how can I exclude them? Commenting and uncommenting config.filter_run_excluding :perf => true seems like a bad idea.
  2. How do I report benchmark results? I think RSpec has some mechanism for that.

Upvotes: 3

Views: 1545

Answers (2)

Piotr Murach
Piotr Murach

Reputation: 547

I created rspec-benchmark Ruby gem for writing performance tests in RSpec. It has many expectations for testing speed, resources usage, and scalability.

For example, to test how fast your code is:

expect { ... }.to perform_under(60).ms

Or to compare with another implementation:

expect { ... }.to perform_faster_than { ... }.at_least(5).times

Or to test computational complexity:

expect { ... }.to perform_logarithmic.in_range(8, 100_000)

Or to see how many objects get allocated:

expect {
  _a = [Object.new]
  _b = {Object.new => 'foo'}
}.to perform_allocation({Array => 1, Object => 2}).objects

To filter your tests you can separate the specs into a performance directory and add a rake task

require 'rspec/core/rake_task'

desc 'Run performance specs'
RSpec::Core::RakeTask.new(:perf) do |task|
  task.pattern = 'spec/performance{,/*/**}/*_spec.rb'
end

Then run them whenever you need them:

rake perf

Upvotes: 4

synapse
synapse

Reputation: 5728

First problem partially solved and second problem solved completely with this piece of code in spec/spec_helper.rb

class MessageHelper
  class << self
    def messages
      @messages ||= []
    end

    def add(msg)
      messages << msg
    end
  end
end

def message(msg)
  MessageHelper.add msg
end

RSpec.configure do |c|
  c.filter_run_excluding :perf => !ENV["PERF"]

  c.after(:suite) do
    puts "\nMessages:"
    MessageHelper.messages.each {|m| puts m}
  end
end

Upvotes: 2

Related Questions