rspec-profiling-0.0.5/0000755000175100017510000000000013626132041013643 5ustar pravipravirspec-profiling-0.0.5/.gitignore0000644000175100017510000000023213626132041015630 0ustar pravipravi*.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp rspec-profiling-0.0.5/Rakefile0000644000175100017510000000010713626132041015306 0ustar pravipravirequire "bundler/gem_tasks" import "./lib/tasks/rspec_profiling.rake" rspec-profiling-0.0.5/rspec_profiling.gemspec0000644000175100017510000000202413626132041020373 0ustar pravipravi# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'rspec_profiling/version' Gem::Specification.new do |spec| spec.name = "rspec_profiling" spec.version = RspecProfiling::VERSION spec.authors = ["Ben Eddy"] spec.email = ["bae@foraker.com"] spec.description = %q{Profile RSpec test suites} spec.summary = %q{Profile RSpec test suites} spec.homepage = "https://github.com/foraker/rspec_profiling" spec.license = "MIT" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_dependency "sqlite3" spec.add_dependency "activerecord" spec.add_dependency "pg" spec.add_dependency "rails" spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" spec.add_development_dependency "rspec" end rspec-profiling-0.0.5/spec/0000755000175100017510000000000013626132041014575 5ustar pravipravirspec-profiling-0.0.5/spec/run_spec.rb0000644000175100017510000000636613626132041016753 0ustar pravipravirequire "active_support/core_ext" require "rspec_profiling/run" require "time" require "ostruct" module RspecProfiling describe Run do def simulate_query(sql) ActiveSupport::Notifications.instrument("sql.active_record", "sql", 100, 200, 1, { sql: sql }) end def simulate_request ActiveSupport::Notifications.instrument("process_action.action_controller", "request", 100, 400, 2, { view_runtime: 10 }) end describe "#run_example" do let(:collector) { CollectorDouble.new } let(:vcs) { VcsDouble.new } let(:run) { described_class.new(collector, vcs) } let(:result) { collector.results.first } let(:example) do ExampleDouble.new({ file_path: "/something_spec.rb", line_number: 15, full_description: "should do something" }) end def simulate_test_suite_run run.start run.example_started(double(example: example)) simulate_query "SELECT * FROM users LIMIT 1;" simulate_query "SELECT * FROM comments WHERE user_id = 1;" simulate_request run.example_passed end before do stub_const("ActiveSupport::Notifications", Notifications.new) simulate_test_suite_run end it "collects a single example" do expect(collector.count).to eq 1 end it "records the branch name" do expect(result.branch).to eq "master" end it "records the commit SHA" do expect(result.commit).to eq "abc123" end it "counts two queries" do expect(result.query_count).to eq 2 end it "counts one request" do expect(result.request_count).to eq 1 end it "records the file" do expect(result.file).to eq "/something_spec.rb" end it "records the file number" do expect(result.line_number).to eq 15 end it "records the description" do expect(result.description).to eq "should do something" end it "records the time" do expect(result.time).to eq 500 end it "records the query time" do expect(result.query_time).to eq 200 end it "records the request time" do expect(result.request_time).to eq 10 end end class CollectorDouble attr_reader :results def initialize @results = [] end def insert(result) @results << OpenStruct.new(result) end def count results.count end end class VcsDouble def branch "master" end def sha "abc123" end def time 0.1 end end class ExampleDouble attr_reader :metadata def initialize(metadata) @metadata = metadata end def execution_result OpenStruct.new({ run_time: 500, status: :passed }) end end class Notifications def initialize @subscriptions = Hash.new { |h, k| h[k] = [] } end def subscribe(event, &block) @subscriptions[event].push block end def instrument(event, *args) @subscriptions[event].each { |callback| callback.call(*args) } end end end end rspec-profiling-0.0.5/spec/vcs/0000755000175100017510000000000013626132041015370 5ustar pravipravirspec-profiling-0.0.5/spec/vcs/svn_spec.rb0000644000175100017510000000143113626132041017534 0ustar pravipravirequire "rspec_profiling/vcs/svn" module RspecProfiling describe VCS::Svn do describe "#branch" do it "calls Git to get the current branch" do expect(subject.branch).to be_nil end end describe "#sha" do it "calls Git to get the current commit's SHA" do expect(subject).to receive(:`).with("svn info -r 'HEAD' | grep \"Revision\" | cut -f2 -d' '").and_return("abc123") expect(subject.sha).to eq "abc123" end end describe "#time" do it "calls Git to get the current commit's datetime" do expect(subject).to receive(:`).with("svn info -r 'HEAD' | grep \"Last Changed Date\" | cut -f4,5,6 -d' '").and_return("2017-01-31") expect(subject.time).to eq Time.parse("2017-01-31") end end end end rspec-profiling-0.0.5/spec/vcs/git_spec.rb0000644000175100017510000000162113626132041017512 0ustar pravipravirequire "rspec_profiling/vcs/git" module RspecProfiling describe VCS::Git do describe "#branch" do it "calls Git to get the current branch" do expect(subject).to receive(:`).with("git rev-parse --abbrev-ref HEAD").and_return("master") expect(subject.branch).to eq "master" end end describe "#sha" do it "calls Git to get the current commit's SHA" do expect(subject).to receive(:`).with("git rev-parse HEAD").and_return("abc123") expect(subject.sha).to eq "abc123" end end describe "#time" do it "calls Git to get the current commit's datetime" do expect(subject).to receive(:`).with("git rev-parse HEAD").and_return("abc123") expect(subject).to receive(:`).with("git show -s --format=%ci abc123").and_return("2017-01-31") expect(subject.time).to eq Time.parse("2017-01-31") end end end end rspec-profiling-0.0.5/spec/collectors/0000755000175100017510000000000013626132041016746 5ustar pravipravirspec-profiling-0.0.5/spec/collectors/psql_spec.rb0000644000175100017510000000437313626132041021273 0ustar pravipravirequire "rspec_profiling/config" require "rspec_profiling/collectors/psql" module RspecProfiling module Collectors describe PSQL do before(:all) { described_class.install } after(:all) { described_class.uninstall } describe "#insert" do let(:collector) { described_class.new } let(:result) { collector.results.first } before do collector.insert({ branch: "master", commit: "ABC123", date: "Thu Dec 18 12:00:00 2012", file: "/some/file.rb", line_number: 10, description: "Some spec", time: 100, status: :passed, exception: "some issue", query_count: 10, query_time: 50, request_count: 1, request_time: 400 }) end it "records a single result" do expect(collector.results.count).to eq 1 end it "records the branch name" do expect(result.branch).to eq "master" end it "records the commit SHA" do expect(result.commit).to eq "ABC123" end it "records the commit date" do expect(result.date).to eq Time.utc(2012, 12, 18, 12) end it "records the file" do expect(result.file).to eq "/some/file.rb" end it "records the line number" do expect(result.line_number).to eq 10 end it "records the description" do expect(result.description).to eq "Some spec" end it "records the time" do expect(result.time).to eq 100.0 end it "records the passing status" do expect(result.status).to eq 'passed' end it "records the exception" do expect(result.exception). to eq 'some issue' end it "records the query count" do expect(result.query_count).to eq 10 end it "records the query time" do expect(result.query_time).to eq 50 end it "records the request count" do expect(result.request_count).to eq 1 end it "records the request time" do expect(result.request_time).to eq 400 end end end end end rspec-profiling-0.0.5/spec/collectors/sql_spec.rb0000644000175100017510000000437113626132041021111 0ustar pravipravirequire "rspec_profiling/config" require "rspec_profiling/collectors/sql" module RspecProfiling module Collectors describe SQL do before(:all) { described_class.install } after(:all) { described_class.uninstall } describe "#insert" do let(:collector) { described_class.new } let(:result) { collector.results.first } before do collector.insert({ branch: "master", commit: "ABC123", date: "Thu Dec 18 12:00:00 2012", file: "/some/file.rb", line_number: 10, description: "Some spec", time: 100, status: :passed, exception: "some issue", query_count: 10, query_time: 50, request_count: 1, request_time: 400 }) end it "records a single result" do expect(collector.results.count).to eq 1 end it "records the branch name" do expect(result.branch).to eq "master" end it "records the commit SHA" do expect(result.commit).to eq "ABC123" end it "records the commit date" do expect(result.date).to eq Time.utc(2012, 12, 18, 12) end it "records the file" do expect(result.file).to eq "/some/file.rb" end it "records the line number" do expect(result.line_number).to eq 10 end it "records the description" do expect(result.description).to eq "Some spec" end it "records the time" do expect(result.time).to eq 100.0 end it "records the passing status" do expect(result.status).to eq 'passed' end it "records the exception" do expect(result.exception). to eq 'some issue' end it "records the query count" do expect(result.query_count).to eq 10 end it "records the query time" do expect(result.query_time).to eq 50 end it "records the request count" do expect(result.request_count).to eq 1 end it "records the request time" do expect(result.request_time).to eq 400 end end end end end rspec-profiling-0.0.5/rspec_profiling0000755000175100017510000003000013626132041016747 0ustar pravipraviSQLite format 3@ ——-ýp R @ƒ=99†tablespec_profiling_resultsspec_profiling_resultsCREATE TABLE "spec_profiling_results" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "branch" varchar, "commit" varchar, "date" datetime, "file" text, "line_number" integer, "description" text, "time" decimal, "status" varchar, "exception" text, "query_count" integer, "query_time" decimal, "request_count" integer, "request_time" decimal, "created_at" datetime, "updated_at" datetime)P++Ytablesqlite_sequencesqlite_sequenceCREATE TABLE sqlite_sequence(name,seq)®99…qtablespec_profiling_resultsspec_profiling_resultsCREATE TABLE "spec_profiling_results" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "commit" varchar, "date" datetime, "file" text, "line_number" integer, "description" text, "time" decimal, "status" varchar, "exception" text, "query_count" integer, "query_time" decimal, "request_count" integer, "request_time" decimal, "created_at" datetime, "updated_at" dfÌ2 ˜ þ d Ê 0 – ü bÈ.”A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7781302017-02-09 04:29:49.778130 A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7748332017-02-09 04:29:49.774833 A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7714912017-02-09 04:29:49.771491 A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7684752017-02-09 04:29:49.768475 A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7648012017-02-09 04:29:49.764801 A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7610492017-02-09 04:29:49.761049A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7576742017-02-09 04:29:49.757674A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7542452017-02-09 04:29:49.754245A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7512112017-02-09 04:29:49.751211A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7477822017-02-09 04:29:49.747782A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7442872017-02-09 04:29:49.744287A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7412702017-02-09 04:29:49.741270A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7382512017-02-09 04:29:49.738251A'! AAmasterABC1232012-12-18 12:00:00.000000/some/file.rb Some specdpassedsome issue 22017-02-09 04:29:49.7346132017-02-09 04:29:49.734613 ä9spec_profiling_resultsrspec-profiling-0.0.5/.ruby-version0000644000175100017510000000001313626132041016302 0ustar pravipraviruby-2.2.1 rspec-profiling-0.0.5/.ruby-gemset0000644000175100017510000000002013626132041016077 0ustar pravipravirspec_profiling rspec-profiling-0.0.5/lib/0000755000175100017510000000000013626132041014411 5ustar pravipravirspec-profiling-0.0.5/lib/rspec_profiling.rb0000644000175100017510000000106113626132041020121 0ustar pravipravirequire "ostruct" require "rails" require "rspec_profiling/config" require "rspec_profiling/version" require "rspec_profiling/run" require "rspec_profiling/collectors/csv" require "rspec_profiling/collectors/sql" require "rspec_profiling/collectors/psql" require "rspec_profiling/vcs/git" require "rspec_profiling/vcs/svn" require "rspec_profiling/vcs/git_svn" module RspecProfiling class Railtie < Rails::Railtie railtie_name :rspec_profiling rake_tasks do load "tasks/rspec_profiling.rake" end end end RSpecProfiling = RspecProfiling rspec-profiling-0.0.5/lib/rspec_profiling/0000755000175100017510000000000013626132041017576 5ustar pravipravirspec-profiling-0.0.5/lib/rspec_profiling/rspec.rb0000644000175100017510000000050713626132041021241 0ustar pravipravirequire "rspec_profiling" RSpec.configure do |config| runner = RspecProfiling::Run.new(RspecProfiling.config.collector.new, RspecProfiling.config.vcs.new) config.reporter.register_listener( runner, :start, :example_started, :example_passed, :example_failed ) end rspec-profiling-0.0.5/lib/rspec_profiling/vcs/0000755000175100017510000000000013626132041020371 5ustar pravipravirspec-profiling-0.0.5/lib/rspec_profiling/vcs/svn.rb0000644000175100017510000000050313626132041021522 0ustar pravipravirequire 'time' module RspecProfiling module VCS class Svn def branch nil end def sha `svn info -r 'HEAD' | grep "Revision" | cut -f2 -d' '` end def time Time.parse `svn info -r 'HEAD' | grep "Last Changed Date" | cut -f4,5,6 -d' '` end end end end rspec-profiling-0.0.5/lib/rspec_profiling/vcs/git_svn.rb0000644000175100017510000000142213626132041022366 0ustar pravipravirequire 'time' module RspecProfiling module VCS class GitSvn # returns nil if using `git svn` def version_control `[ -d .git/svn ] && [ x != x"$(ls -A .git/svn/)" ]` RspecProfiling::VCS::Svn unless $CHILD_STATUS.success? end def branch nil end def sha if version_control.nil? `git svn info | grep "Revision" | cut -f2 -d' '` else `svn info -r 'HEAD' | grep "Revision" | cut -f2 -d' '` end end def time if version_control.nil? Time.parse `git svn info | grep "Last Changed Date" | cut -f4,5,6 -d' '` else Time.parse `svn info -r 'HEAD' | grep "Last Changed Date" | cut -f4,5,6 -d' '` end end end end end rspec-profiling-0.0.5/lib/rspec_profiling/vcs/git.rb0000644000175100017510000000043513626132041021503 0ustar pravipravirequire 'time' module RspecProfiling module VCS class Git def branch `git rev-parse --abbrev-ref HEAD` end def sha `git rev-parse HEAD` end def time Time.parse `git show -s --format=%ci #{sha}` end end end end rspec-profiling-0.0.5/lib/rspec_profiling/example.rb0000644000175100017510000000316113626132041021557 0ustar pravipravirequire "benchmark" module RspecProfiling class Example IGNORED_QUERIES_PATTERN = %r{( pg_table| pg_attribute| pg_namespace| show\stables| pragma| sqlite_master/rollback| ^TRUNCATE TABLE| ^ALTER TABLE| ^BEGIN| ^COMMIT| ^ROLLBACK| ^RELEASE| ^SAVEPOINT )}xi def initialize(example) @example = example @counts = Hash.new(0) end def file metadata[:file_path] end def line_number metadata[:line_number] end def description metadata[:full_description] end def status execution_result.status end def exception execution_result.exception end def time execution_result.run_time end def query_count counts[:query_count] end def query_time counts[:query_time] end def request_count counts[:request_count] end def request_time counts[:request_time] end def log_query(query, start, finish) unless query[:sql] =~ IGNORED_QUERIES_PATTERN counts[:query_count] += 1 counts[:query_time] += (finish - start) end end def log_request(request, start, finish) counts[:request_count] += 1 counts[:request_time] += request[:view_runtime].to_f end private attr_reader :example, :counts def execution_result @execution_result ||= begin result = example.execution_result result = OpenStruct.new(result) if result.is_a?(Hash) result end end def metadata example.metadata end end end rspec-profiling-0.0.5/lib/rspec_profiling/console.rb0000644000175100017510000000011313626132041021560 0ustar pravipravidef results @results ||= RspecProfiling.config.collector.new.results end rspec-profiling-0.0.5/lib/rspec_profiling/config.rb0000644000175100017510000000042113626132041021365 0ustar pravipravimodule RspecProfiling def self.configure yield config end def self.config @config ||= OpenStruct.new({ collector: RspecProfiling::Collectors::SQL, vcs: RspecProfiling::VCS::Git, table_name: 'spec_profiling_results' }) end end rspec-profiling-0.0.5/lib/rspec_profiling/version.rb0000644000175100017510000000005613626132041021611 0ustar pravipravimodule RspecProfiling VERSION = "0.0.5" end rspec-profiling-0.0.5/lib/rspec_profiling/collectors/0000755000175100017510000000000013626132041021747 5ustar pravipravirspec-profiling-0.0.5/lib/rspec_profiling/collectors/psql.rb0000644000175100017510000000422513626132041023256 0ustar pravipravirequire "pg" require "active_record" module RspecProfiling module Collectors class PSQL def self.install new.install end def self.uninstall new.uninstall end def self.reset new.results.destroy_all end def initialize RspecProfiling.config.db_path ||= 'rspec_profiling' establish_connection end def install return if prepared? connection.create_table(table) do |t| t.string :branch t.string :commit t.datetime :date t.text :file t.integer :line_number t.text :description t.decimal :time t.string :status t.text :exception t.integer :query_count t.decimal :query_time t.integer :request_count t.decimal :request_time t.timestamps null: true end end def uninstall connection.drop_table(table) end def insert(attributes) results.create!(attributes.except(:created_at)) end def results @results ||= begin establish_connection Result.table_name = table Result.attr_protected if Result.respond_to?(:attr_protected) Result end end private def prepared? connection.table_exists?(table) end def connection @connection ||= results.connection end def establish_connection begin PG.connect(dbname: 'postgres').exec("CREATE DATABASE #{database}") rescue PG::DuplicateDatabase # no op end Result.establish_connection( :adapter => 'postgresql', :database => database ) end def table RspecProfiling.config.table_name end def database RspecProfiling.config.db_path end class Result < ActiveRecord::Base def to_s [description, location].join(" - ") end private def location [file, line_number].join(":") end end end end end rspec-profiling-0.0.5/lib/rspec_profiling/collectors/csv.rb0000644000175100017510000000161613626132041023073 0ustar pravipravirequire "csv" module RspecProfiling module Collectors class CSV HEADERS = %w{ branch commit date file line_number description status exception time query_count query_time request_count request_time } def self.install # no op end def self.uninstall # no op end def self.reset # no op end def initialize RspecProfiling.config.csv_path ||= 'tmp/spec_benchmarks.csv' end def insert(attributes) output << HEADERS.map do |field| attributes.fetch(field.to_sym) end end private def output @output ||= ::CSV.open(path, "w").tap { |csv| csv << HEADERS } end def path RspecProfiling.config.csv_path.call end end end end rspec-profiling-0.0.5/lib/rspec_profiling/collectors/sql.rb0000644000175100017510000000377313626132041023105 0ustar pravipravirequire "sqlite3" require "active_record" module RspecProfiling module Collectors class SQL def self.install new.install end def self.uninstall new.uninstall end def self.reset new.results.destroy_all end def initialize RspecProfiling.config.db_path ||= 'tmp/rspec_profiling' establish_connection end def install return if prepared? connection.create_table(table) do |t| t.string :branch t.string :commit t.datetime :date t.text :file t.integer :line_number t.text :description t.decimal :time t.string :status t.text :exception t.integer :query_count t.decimal :query_time t.integer :request_count t.decimal :request_time t.timestamps null: true end end def uninstall connection.drop_table(table) end def insert(attributes) results.create!(attributes.except(:created_at)) end def results @results ||= begin establish_connection Result.table_name = table Result.attr_protected if Result.respond_to?(:attr_protected) Result end end private def prepared? connection.table_exists?(table) end def connection @connection ||= results.connection end def establish_connection Result.establish_connection( :adapter => 'sqlite3', :database => database ) end def table RspecProfiling.config.table_name end def database RspecProfiling.config.db_path end class Result < ActiveRecord::Base def to_s [description, location].join(" - ") end private def location [file, line_number].join(":") end end end end end rspec-profiling-0.0.5/lib/rspec_profiling/run.rb0000644000175100017510000000373113626132041020733 0ustar pravipravirequire "rspec_profiling/example" require "rspec_profiling/vcs/git" require "rspec_profiling/vcs/svn" require "rspec_profiling/vcs/git_svn" require "rspec_profiling/collectors/sql" require "rspec_profiling/collectors/psql" require "rspec_profiling/collectors/csv" module RspecProfiling class Run def initialize(collector = RspecProfiling.config.collector.new, vcs = RspecProfiling.config.vcs.new) @collector = collector @vcs = vcs end def start(*args) start_counting_queries start_counting_requests end def example_started(example) example = example.example if example.respond_to?(:example) @current_example = Example.new(example) end def example_finished(*args) collector.insert({ branch: vcs.branch, commit: vcs.sha, date: vcs.time, file: @current_example.file, line_number: @current_example.line_number, description: @current_example.description, status: @current_example.status, exception: @current_example.exception, time: @current_example.time, query_count: @current_example.query_count, query_time: @current_example.query_time, request_count: @current_example.request_count, request_time: @current_example.request_time }) end alias :example_passed :example_finished alias :example_failed :example_finished private attr_reader :collector, :vcs def start_counting_queries ActiveSupport::Notifications.subscribe("sql.active_record") do |name, start, finish, id, query| @current_example.try(:log_query, query, start, finish) end end def start_counting_requests ActiveSupport::Notifications.subscribe("process_action.action_controller") do |name, start, finish, id, request| @current_example.try(:log_request, request, start, finish) end end end end rspec-profiling-0.0.5/lib/tasks/0000755000175100017510000000000013626132041015536 5ustar pravipravirspec-profiling-0.0.5/lib/tasks/rspec_profiling.rake0000644000175100017510000000101513626132041021564 0ustar pravipravirequire 'rake' namespace :rspec_profiling do desc "Install the collector" task install: :environment do collector.install end desc "Uninstall the collector" task uninstall: :environment do collector.uninstall end task console: :environment do require 'irb' require 'irb/completion' require 'rspec_profiling' require 'rspec_profiling/console' ARGV.clear IRB.start end task :reset do collector.reset end def collector RspecProfiling.config.collector end end rspec-profiling-0.0.5/README.md0000644000175100017510000001144313626132041015125 0ustar pravipravi# RspecProfiling Collects profiles of RSpec test suites, enabling you to identify specs with interesting attributes. For example, find the slowest specs, or the spec which issues the most queries. Collected attributes include: - git commit SHA (or SVN revision) and date - example file, line number and description - example status (i.e. passed or failed) - example exception (i.e. nil if passed, reason for failure otherwise) - example time - query count and time - request count and time ## Compatibility RspecProfiling should work with Rails >= 3.2 and RSpec >= 2.14. ## Installation Add this line to your application's Gemfile: ``` gem 'rspec_profiling' ``` And then execute: ``` bundle ``` Require the gem to your `spec_helper.rb`. ``` require "rspec_profiling/rspec" ``` Lastly, run the installation rake tasks to initialize an empty database in which results will be collected. ``` bundle exec rake rspec_profiling:install ``` ## Usage ### Choose a version control system Results are collected based on the version control system employed e.g. revision or commit SHA for `svn` and `git` respectively. #### Git By default, RspecProfiling expects Git as the version control system. #### Subversion RspecProfiling can be configured to use `svn` in `config/initializers/rspec_profiling.rb`: ```Ruby RspecProfiling.configure do |config| config.vcs = RspecProfiling::VCS::Svn end ``` #### Git / Subversion For those with a mixed project, with some developers using `git svn` and others regular `svn`, use this configuration to detect which is being used locally and behave accordingly. ```Ruby RspecProfiling.configure do |config| config.vcs = RspecProfiling::VCS::GitSvn end ``` ### Choose a results collector Results are collected just by running the specs. #### SQLite3 By default, profiles are collected in an SQL database. Make sure you've run the installation rake task before attempting. You can review results by running the RspecProfiling console. The console has a preloaded `results` variable. ``` bundle exec rake rspec_profiling:console > results.count => 1970 ``` You can find the spec that runs the most queries: ``` > results.order(:query_count).last.to_s => "Updating my account - ./spec/features/account_spec.rb:15" ``` Or find the spec that takes the most time: ``` > results.order(:time).last.to_s => "Updating my account - ./spec/features/account_spec.rb:15" ``` There are additional attributes available on the `Result` instances to enable debugging, such as `exception` and `status`. #### CSV You can configure `RspecProfiling` to collect results in a CSV in `config/initializers/rspec_profiling.rb`: ```Ruby RspecProfiling.configure do |config| config.collector = RspecProfiling::Collectors::CSV end ``` By default, the CSV is output to `cat tmp/spec_benchmarks.csv`. Rerunning spec will overwrite the file. You can customize the CSV path to, for example, include the sample time. ```Ruby RspecProfiling.configure do |config| config.collector = RspecProfiling::Collectors::CSV config.csv_path = ->{ "tmp/spec_benchmark_#{Time.now.to_i}" } end ``` #### Postgresql You can configure `RspecProfiling` to collect results in a Postgres database in your `spec_helper.rb` file. ```Ruby RspecProfiling.configure do |config| config.collector = RspecProfiling::Collectors::PSQL config.db_path = 'profiling' end ``` ## Configuration Options Configuration is performed like this: ```Ruby RspecProfiling.configure do |config| config.