Skip to content

Instantly share code, notes, and snippets.

@kerrizor
Last active January 31, 2024 00:07
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save kerrizor/8bb8f1528c88789c3435 to your computer and use it in GitHub Desktop.
Save kerrizor/8bb8f1528c88789c3435 to your computer and use it in GitHub Desktop.
Trigger MiniTest failures in Rails when Bullet detects N+1 query violations

In test/test_helper.rb...

### Bullet (N+1 queries)

if ENV['BULLET']
  Bullet.enable = true

  require 'minitest/unit'

  module MiniTestWithBullet
    def before_setup
      Bullet.start_request
      super if defined?(super)
    end

    def after_teardown
      super if defined?(super)

      if Bullet.warnings.present?
        warnings = Bullet.warnings.map{ |_k, warning| warning }.flatten.map{|warn| warn.body_with_caller}.join("\n-----\n\n")

        flunk(warnings)
      end

      Bullet.end_request
    end
  end

  class ActiveSupport::TestCase
    include MiniTestWithBullet
  end
end
@zenspider
Copy link

You should make this a minitest plugin!

@steveklebanoff
Copy link

Thanks for this! ❤️

@al3rez
Copy link

al3rez commented Dec 20, 2019

module BulletHelper
  def before_setup
    Bullet.start_request
    super if defined?(super)
  end

  def after_teardown
    super if defined?(super)

    Bullet.perform_out_of_channel_notifications if Bullet.notification?
    Bullet.end_request
  end
end

Tested with ActiveSupport::TestCase on Rails 6.x

@a320neo
Copy link

a320neo commented Mar 12, 2020

Thanks for sharing.

@nicklevenson
Copy link

nicklevenson commented Aug 30, 2021

I'm using Rails 4.2.11 & the configuration above raised bullet errors/detections, but wasn't showing a useful stack trace. I found using after_setup & before_teardown gave me the real stack trace in testing.

module BulletHelper
  def after_setup
    Bullet.enable = true
    # Bullet.bullet_logger = true
    Bullet.unused_eager_loading_enable = false
    Bullet.raise = true # raise an error if n+1 query occurs
    Bullet.start_request
    super
  end

  def before_teardown
    super
    Bullet.perform_out_of_channel_notifications if Bullet.notification?
    Bullet.end_request
    Bullet.enable = false
    # Bullet.bullet_logger = false
    Bullet.raise = false
  end
end

class ActiveSupport::TestCase
  include BulletHelper
...

@ybart
Copy link

ybart commented Aug 26, 2022

Also, using after_setup/before_teardown instead of before_setup/after_teardown allows to update the Bullet config in setup and teardown like this :

    setup do
      Bullet.unused_eager_loading_enable = false
    end

    teardown do
      Bullet.unused_eager_loading_enable = true
    end

Using before_setup/after_teardown, this code can fail because Bullet will check for unused eager loading after we re-enabled the setting and Bullet will then emit an error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment