A gem to track all SQL queries performed inside a block of code.
With SqlSpy you can test:
- The total amount of queries performed by a piece of code
- The amount of queries performed on a specific table
- The type of these queries: SELECT, INSERT, UPDATE, DELETE
- The query duration
- The SQL produced by your ActiveRecord code
- N+1 queries
The implementation is inspired by how ActiveRecord is tested.
Check out my blog post about writing controller tests with SqlSpy in order to prevent N+1 regressions.
Add the gem to your Gemfile:
gem "sql_spy"Install it:
bundle installWrap the code you'd like to track inside SqlSpy.track {}:
require "sql_spy"
queries = SqlSpy.track do
# Some code that triggers ActiveRecord queries
endThe SqlSpy.track method will return an array containing all the queries performed inside the block. Every object inside this array exposes the following methods:
#model_name: The model name (e.g. "User").#sql: The SQL query that was performed.#duration: The duration of the query in milliseconds.#select?: Is this a SELECT query?#insert?: Is this an INSERT query?#update?: Is this an UPDATE query?#delete?: Is this a DELETE query?
Here are some ideas of how you could use this:
# Expect less than 5 queries
assert queries.count < 5
# Expect 1 INSERT query
assert_equal 1, queries.select(&:insert?).size
# Expect 2 queries to the posts table
assert_equal 2, queries.select { |query| query.model_name == "Post" }.size
# None of the queries should be slower than 100ms
assert queries.none? { |query| query.duration > 100 }
# Fail on N+1 queries: expect at most 1 query per table
queries_by_model = queries.group_by(&:model_name)
assert queries_by_model.none? { |model_name, queries| queries.count > 1 }The gem is tested with Postgres 9.6 and SQLite 3.
To run tests with SQLite:
rakeTo run tests with Postgres:
# Create a test database
cretedb sql_spy_test
DATABASE_URL=postgres:///sql_spy_test rakeThe gem is available as open source under the terms of the MIT License.