minitest snippets

MiniTest and "0 tests, 0 assertions, 0 failures, 0 errors"

Tagged minitest, test, ruby  Languages ruby

My test_helper.rb looked like this:

require 'minitest/autorun'
require 'app'

The output when running a unit test was this:

0 tests, 0 assertions, 0 failures, 0 errors

The solution was to move the minitest require:

require 'minitest/autorun'
require 'app'

Now my tests are run again when executing:

ruby test/functional/xxx_controller_test.rb

How to Test Authentication With Devise+Capybara+Minitest

Tagged devise, capybara, authentication, warden, transaction, gotcha, minitest  Languages ruby

Testing authentication functionality with Capybara and Devise? See the following checklist:

* Use shared connections or disable transactional fixtures. * Set Capybara.default_host to match config.session_store.domain or you'll get "401 Unauthorized" * Name of test should end with "integration", e.g. describe "Dashboard Business integration" do * Add the following to your integration tests:

include Warden::Test::Helpers
  Warden.test_mode!

  after do
    Warden.test_reset!
  end

Full example of integration test with Devise, Capybara, and minitest:

class IntegrationSpec < MiniTest::Spec
  include Rails.application.routes.url_helpers
  include Capybara::DSL
  include Warden::Test::Helpers
  Warden.test_mode!

  before do
    @routes = Rails.application.routes
  end

  after do
    Warden.test_reset!
  end

  def sign_in(user)
    login_as(user, scope: :user)
  end

  def sign_out
    logout(:user)
  end

  def default_url_options
    Rails.configuration.action_mailer.default_url_options
  end
end

MiniTest::Spec.register_spec_type( /integration$/, IntegrationSpec )

Integration Tests With Capybara, Devise, Minitest::Spec, and Capybara-Webkit

Tagged capybara, devise, minitest, spec, webkit, headless  Languages ruby

Does your boss want you to run integration tests with Capybara, Devise, Minitest::Spec, Capybara-Webkit, and the Headless gem?

Then use this code, which features: * Automatic test failure on JavaScript errors * Check for XSS attack vectors with assert_no_alerts. * Sign in/out with Devise

require 'headless'
require 'awesome_print'

headless = Headless.new(reuse: true, destroy_at_exit: false)
puts "Headless mode. Display :#{headless.display}. PID #{Process.pid}"
headless.start

class IntegrationSpec < MiniTest::Spec
  include Rails.application.routes.url_helpers
  include Capybara::DSL
  include Warden::Test::Helpers
  Warden.test_mode!

  before do
    assert_no_js_errors
  end

  after do
    Warden.test_reset!
  end

  def sign_in(user, scope = :user)
    login_as(user, scope: scope)
  end

  def sign_out(scope = :user)
    logout(scope)
  end

  def assert_no_js_errors
    errors = page.driver.error_messages
    assert_equal 0, errors.size, errors.ai
  end

  def assert_no_alerts(types = [:alert, :confirm, :prompt])
    types.each do |type|
      alerts = page.driver.send(:"#{type}_messages")
      assert_equal 0, alerts.size, alerts.ai
    end
  end

  def default_url_options
    Rails.configuration.action_mailer.default_url_options
  end
end

MiniTest::Spec.register_spec_type( /integration$/, IntegrationSpec )

Remember to name your tests like this:

require 'test_helper'

describe "Dashboard integration" do
...
end

Otherwise the tests won't inherit from the IntegrationSpec class.

MiniTest with Deferred Garbage Collection

Tagged minitest, deferred, gc  Languages ruby
class DeferredGarbageCollection
  DEFERRED_GC_THRESHOLD = (ENV['DEFER_GC'] || 10.0).to_f

  @last_gc_run = Time.now

  def self.start
    GC.disable if DEFERRED_GC_THRESHOLD > 0
  end

  def self.reconsider
    if DEFERRED_GC_THRESHOLD > 0 && Time.now - @last_gc_run >= DEFERRED_GC_THRESHOLD
      GC.enable
      GC.start
      GC.disable
      @last_gc_run = Time.now
    end
  end
end

module MiniTestDeferredGC
  def before_setup
    DeferredGarbageCollection.start
    super
  end

  def after_teardown
    super
    DeferredGarbageCollection.reconsider
  end
end

class MiniTest::Test
  include MiniTestDeferredGC
end

Timing and Benchmarking Minitest Tests

Tagged ruby, minitest, benchmark, timing  Languages ruby

Put this in test/support/timing.rb:

module MiniTestTiming
  class << self; attr_accessor :failure_threshold end

  def before_setup
    @start_time = Time.now
    super
  end

  def after_teardown
    super
    end_time = Time.now
    duration = (end_time - @start_time).seconds.round(1)
    time = duration.to_s + "s"
    name = "#{self.class.name}.#{__name__}"
    limit = MiniTestTiming.failure_threshold
    File.open 'log/test_duration.log', 'a' do |f|
      f << "#{time.ljust(5)}: #{name}\n"
    end
    assert duration < limit, "#{name} took too long (#{time} > #{limit}s)"
  end
end

# Set threshold for failing tests to 1 second
MiniTestTiming.failure_threshold = 1

class MiniTest::Test
  include MiniTestTiming
end

The time it takes your tests will show up in log/test_duration.log.

You can also output the time it took to run a test by using the verbose switch:

rake test TESTOPTS="--verbose"

undefined method `+' for nil:NilClass (NoMethodError)

Tagged capybara, cucumber, minitest  Languages ruby

When Capybara/Cucumber tests fail:

undefined method `+' for nil:NilClass (NoMethodError)
.../.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/minitest-5.10.1/lib/minitest/assertions.rb:135:in `assert'

Do this:

  1. Install test-unit
gem 'test-unit'
  1. Include assertions in env.rb
World Test::Unit::Assertions