minitest/minitest-rails

Issue with Global before each and after

Closed this issue · 9 comments

So I am confused how I can I enforce a global before and after

I just upgraded to Rails 4.2 from 4.0 andn I am seeing a difference in behavior

I have this in my test_helper

class MiniTest::Spec
  include FactoryGirl::Syntax::Methods
  include ResqueUnit::Assertions
  include ResqueUnit::SchedulerAssertions

  before :each do
    p :global_before
    ActiveRecord::Base.establish_connection(:test)

    DatabaseCleaner.start
  end

  after :each do
    p :global_after

    DatabaseCleaner.clean
  end

  include SharedHelpers
end

unfortunately, when I run

rake tests

I would expect the global before to always be called.. but I am not seeing that at all. It s like the before and after are completely ignore in some case. And not in some other

% ruby -Itest test/models/app_test.rb 
Started with run options --seed 7562

App
  test_0001_must have a name                                      PASS (0.22s)
  test_0002_must have a name less than 64 char                    PASS (0.03s)

Seems to happens when for Model and Controller tests. When I create my own folder like says services, I see them being called all the time

RetrieveRecentStatuses::Recent for feeds::Recent for feeds with hubs
:global_before
:global_after
  test_0001_should include hub feeds if any                       PASS (0.37s)

RetrieveRecentStatuses::Recent for feeds
:global_before
:global_after
  test_0004_should have crawling run in (starting) reported as failed due to too long starting PASS (0.07s)
:global_before
:global_after
  test_0010_should have passed the last recurring frequency parsing run reported as failed  PASS (0.12s)
:global_before
:global_after
  test_0006_should have passed the last recurring frequency crawling run reported as failed  PASS (0.09s)
:global_before
:global_after

How can I enforce to have a before and after for every tests?

forgot to mention but I am using
minitest-rails (2.2.0)
minitest (> 5.7)
railties (
> 4.1)

what I am seeing in the 2 previous case is a different inheritance tree and I am thinking this might be the reason why it breaks?

[#Class:0x007ffd56c71d88,
#Class:0x007ffd56c8bf08,
ActiveSupport::TestCase,
ResqueUnit::SchedulerAssertions,
ResqueUnit::Assertions,
SharedHelpers,
Minitest::Rails::ConstantLookup,
Minitest::Spec::DSL::InstanceMethods,
ActiveRecord::TestFixtures,
ActiveSupport::Testing::TimeHelpers,
ActiveSupport::Testing::Deprecation,
ActiveSupport::Testing::Assertions,
ActiveSupport::Callbacks,
ActiveSupport::Testing::SetupAndTeardown,
ActiveSupport::Testing::TaggedLogging,
Minitest::Test,
Minitest::Guard,
Minitest::Test::LifecycleHooks,
Minitest::Assertions,
Minitest::Runnable,
Object,
PP::ObjectMixin,
Minitest::Rails::Expectations,
Minitest::Expectations,
ActiveSupport::Dependencies::Loadable,
JSON::Ext::Generator::GeneratorMethods::Object,
Kernel,
BasicObject]

vs

=> [#Class:0x007ffd56e4b460,
Minitest::Spec,
SharedHelpers,
ResqueUnit::SchedulerAssertions,
ResqueUnit::Assertions,
FactoryGirl::Syntax::Methods,
Minitest::Spec::DSL::InstanceMethods,
Minitest::Test,
Minitest::Guard,
Minitest::Test::LifecycleHooks,
Minitest::Assertions,
Minitest::Runnable,
Object,
PP::ObjectMixin,
Minitest::Rails::Expectations,
Minitest::Expectations,
ActiveSupport::Dependencies::Loadable,
JSON::Ext::Generator::GeneratorMethods::Object,
Kernel,
BasicObject]
[2] pry(#<Sea

So there are a couple issues here:

The Minitest Spec DSL does not support before :each and before :all. The before and after blocks run before and after each test. There is no way to do a before :all or after :all using the vanilla Minitest Spec DSL.

The model and controller tests are run by the ActiveSupport::TestCase and ActionController::TestCase classes respectively. Those classes no not inherit from Minitest::Spec, and minitest-rails is unable to change the inheritance. But it can (and does) add the Minitest::Spec::DSL module to enable the Spec DSL. This means that anything you add to Minitest::Spec won't be available on the model and controller tests.

The right way to go is to add all your changes to ActiveSupport::TestCase. All rails tests use this class or inherit from this class. If you specify Minitest::Test or Minitest::Spec in your tests then you will not have access to the database connection that is needed to run any tests that involves ActiveRecord or a web request.

Here are a few stackoverflow answers that involve minitest-rails and database cleaner.

yea I am already using FactoryGirl and trying to abstract most test from DB but there are still need at time to run test against it. the problem I am having is this https://github.com/DatabaseCleaner/database_cleaner/issues/395 as I cannot seem to run the database cleaner reliably. But now I am not seeing the before being called when needed

Seems to me that all I am trying to do is have a reliable before (wether I use database cleaner or not) but I can see that custom folders are not treated the same than Models/controllers from rails when it comes to a before/each that is the same for all of the tests? wHen I meant global, I meant more same code executed before each test. I was trying to share without having to reapeat it. . any suggestions?

To get non-ActiveRecord tests to use the same database setup that the rails tests use you should tell the test to treat it as a model test by setting the :model additional describe:

describe PoroObject, :model do
  it "has an active database connection" do
    # ...
  end
end

ah cool! I ll try that ! thanks!

Seems like this issue is resolved, so I'm closing it.