Skip to content

Commit

Permalink
Add test environment
Browse files Browse the repository at this point in the history
  • Loading branch information
nepalez committed Feb 10, 2017
1 parent e5827f0 commit 37e2287
Show file tree
Hide file tree
Showing 17 changed files with 237 additions and 10 deletions.
13 changes: 10 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
require "bundler/gem_tasks"
require "bundler/setup"
Bundler::GemHelper.install_tasks

require "rspec/core/rake_task"

RSpec::Core::RakeTask.new(:spec)
# Adds dummy:db tasks.
load "spec/dummy/Rakefile"

task default: :spec
# Declares gem's own tasks.
desc "Runs test suite."
task default: %w(dummy:db:migrate) do
system "bundle exec rspec spec"
end
50 changes: 45 additions & 5 deletions lib/rspec/sqlimit.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,51 @@
require "active_record"
require "rspec"

module RSpec::SQLimit
require_relative "sqlimit/counter"
end
module RSpec
module SQLimit
require_relative "sqlimit/counter"
require_relative "sqlimit/reporter"
end

Matchers.define :exceed_query_limit do |expected, matcher = nil|
def counter
@counter ||= RSpec::SQLimit::Counter.new
end

def message(expected, matcher, negation = false)
if matcher
condition = negation ? "maximum" : "more than"
restriction = " that match #{matcher}"
suffix = " among others (see mark ->)"
end

reporter = RSpec::SQLimit::Reporter.new(counter, matcher)

<<-MESSAGE.gsub(/ +\|/, "")
|Expected to run #{condition} #{expected} queries#{restriction}
|The following #{reporter.count} queries were invoked#{suffix}:
|#{reporter.lines.join("\n")}
MESSAGE
end

match do |block|
counter.count(&block)
RSpec::SQLimit::Reporter.new(counter, matcher).count > expected
end

match_when_negated do |block|
counter.count(&block)
RSpec::SQLimit::Reporter.new(counter, matcher).count <= expected
end

failure_message do |_|
message(expected, matcher)
end

failure_message_when_negated do |_|
message(expected, matcher, true)
end

RSpec::Matchers.define :exceed_query_limit do
match do |block|
supports_block_expectations
end
end
26 changes: 26 additions & 0 deletions lib/rspec/sqlimit/counter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module RSpec::SQLimit
class Counter
attr_reader :queries

def initialize
@queries = []
end

# FIXME add mutex to ensure thread-safety
def count
@queries = []
ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
yield
end
end

private

def callback
@callback ||= lambda(_name, start, finish, _message_id, values) do
return if %w(CACHE SCHEMA).include? values[:name]
queries << { sql: values[:sql], duration: (finish - start) * 1_000 }
end
end
end
end
30 changes: 30 additions & 0 deletions lib/rspec/sqlimit/reporter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module RSpec::SQLimit
class Reporter
attr_reader :matcher

def initialize(counter, matcher = nil)
@counter = counter
@matcher = matcher
end

def count
return queries.count unless @matcher
queries.count { |query| query[:sql] =~ @matcher }
end

def lines
queries.map.with_index { |*args| line(*args) }
end

private

def line(query, index)
prefix = @matcher && query =~ @matcher ? "->" : " "
"#{prefix} #{index}) #{query[:sql]} (#{query[:duration].round(3)} ms)"
end

def queries
@queries ||= @counter.queries
end
end
end
7 changes: 5 additions & 2 deletions rspec-sqlimit.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ Gem::Specification.new do |gem|

gem.required_ruby_version = ">= 2.3"

gem.add_runtime_dependency "activerecord", "> 4.0", "< 6.0"
gem.add_runtime_dependency "rails", "> 4.0", "< 6.0"
gem.add_runtime_dependency "rspec", "~> 3.0"

gem.add_development_dependency "rake"
gem.add_development_dependency "rspec", "~> 3.0"
gem.add_development_dependency "rake", "> 10.0"
gem.add_development_dependency "sqlite3", "~> 1.3"
gem.add_development_dependency "database_cleaner", "~> 1.5"
gem.add_development_dependency "rubocop", "~> 0.44"
end
14 changes: 14 additions & 0 deletions spec/dummy/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require "active_record"
require "bundler/setup"

namespace :dummy do
task :environment do
require_relative "lib/dummy"
end

namespace :db do
task load_config: :environment
end

load "active_record/railties/databases.rake"
end
3 changes: 3 additions & 0 deletions spec/dummy/app/models/post.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Post < ActiveRecord::Base
belongs_to :user
end
3 changes: 3 additions & 0 deletions spec/dummy/app/models/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class User < ActiveRecord::Base
has_many :posts
end
6 changes: 6 additions & 0 deletions spec/dummy/config/database.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
test:
adapter: :sqlite3
database: spec/dummy/db/test.sqlite3
pool: 5
timeout: 5000
10 changes: 10 additions & 0 deletions spec/dummy/config/environment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Dummy::Application.configure do |config|
dummy = File.expand_path "../..", __FILE__
database_yml = File.join(dummy, "config/database.yml")

config.database_configuration = YAML.load File.read(database_yml)
config.db_dir = File.join(dummy, "db")
config.env = :test
config.migrations_paths = [File.join(dummy, "db/migrate")]
config.root = dummy
end
7 changes: 7 additions & 0 deletions spec/dummy/db/migrate/20170211104800_create_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name, index: true
end
end
end
9 changes: 9 additions & 0 deletions spec/dummy/db/migrate/20170211104823_create_posts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.references :users
t.string :title
t.text :text
end
end
end
26 changes: 26 additions & 0 deletions spec/dummy/db/schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20170211104823) do

create_table "posts", force: :cascade do |t|
t.integer "users_id"
t.string "title"
t.text "text"
end

create_table "users", force: :cascade do |t|
t.string "name"
t.index ["name"], name: "index_users_on_name"
end

end
Binary file added spec/dummy/db/test.sqlite3
Binary file not shown.
9 changes: 9 additions & 0 deletions spec/dummy/lib/dummy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require "active_record"
require "bundler/setup"

module Dummy
require_relative "dummy/application"
require_relative "../config/environment"
require_relative "../app/models/user.rb"
require_relative "../app/models/post.rb"
end
26 changes: 26 additions & 0 deletions spec/dummy/lib/dummy/application.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Dummy
class Application
class << self
# Configuration settings wrapper for the
# <tt>ActiveRecord::Tasks::DatabaseTasks</tt>.
#
# Establishes AR connection after configuration.
#
def configure
yield tasks
base.configurations = tasks.database_configuration
base.establish_connection(tasks.env)
end

private

def base
@base ||= ActiveRecord::Base
end

def tasks
@tasks ||= ActiveRecord::Tasks::DatabaseTasks
end
end
end
end
8 changes: 8 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
require "pry"
require "rspec-sqlimit"
require "database_cleaner"

require_relative "dummy/lib/dummy"

DatabaseCleaner.strategy = :truncation

RSpec.configure do |config|
config.order = :random
config.filter_run focus: true
config.run_all_when_everything_filtered = true

# Prepare the Test namespace for constants defined in specs
config.after(:each) { DatabaseCleaner.clean }
end

0 comments on commit 37e2287

Please sign in to comment.