Skip to content

splitwise/full_table_scan_matchers

 
 

Repository files navigation

Gem VersionBuild StatusCoveralls branchCode Climate

full_table_scan_matchers

Detect full table scans in your unit tests! As opposed to just doing basic regexes on the db/schema.rb like rails-best-practices does, this actually checks queries made against the database, to ensure and assert that there are indexes for it to use.

Requirements/Support

  • Ruby 2.0+
  • ActiveRecord 4+
  • ActiveSupport 4+
  • mysql2 adapter

Installation

Add to your Gemfile, in the test group:

group :test do
  gem 'full_table_scan_matchers'
end

Usage

# No full table scans at all please:
expect { user.posts }.not_to full_table_scan

# Or on just a specific thing:
expect {
  user.posts.joins(:comments).first.comments
}.not_to full_table_scan.on :posts

How's it work?

  • It logs all SQL queries made inside the expect block
    • ..optionally filtering them to table(s) you care about
  • Afterwards, it runs all those through EXPLAIN
  • Instead of checking type for ALL, it checks the keys instead
    • Because in test mode, mysql may ignore the index and scan the whole table because it's so small
    • But your production database is much, much larger - we just want to make sure that indexes are available

Configuration

You can optionally configure a few things:

FullTableScanMatchers.configure do |config|
  # Tables to ignore - defaults to none
  # Default: none
  config.ignores = []

  # Database adapter to use - only one for now
  # Default (and only): mysql
  config.adapter = FullTableScanMatchers::DBAdapters::MySql

  # Includes a backtrace in the fail output if this is set to true
  # Default: false
  config.log_backtrace = false

  # Add a proc to strip things from the logged backtraces
  # Default: None
  config.backtrace_filter = Proc.new { |backtrace| backtrace }

  # Run EXPLAIN on each SELECT statement immediately after it is executed
  # Default: false
  config.eager = false

  # Ignore full table scan on materialized subquery tables
  # Default: false
  config.ignore_materialized = false
end

Postgres?

Currently, this just support mySql. However, I tried to keep the part that's most-tied to that database (parsing the EXPLAIN output) silo'd in an adapter - I'd happily merge any clean PRs that add Postgres (or others)!

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests.

Credits

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/JustinAiken/full_table_scan_matchers.

License

The gem is available as open source under the terms of the MIT License.

About

Matchers for rspec to detect full table scans

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Ruby 99.5%
  • Shell 0.5%