New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce ApplicationTestCase #28243
Conversation
All Rails test classes extend `ActiveSupport::TestCase`. This makes it very had for applications to customize the test inheritance; they simply have to reopen/freedom-patch `ActiveSupport::TestCase`. Having a class implemented by the application would make it much more straightforward. It's also in line with the way Rails has moved from `ActiveRecord::Base` to `ApplicationRecord`, `ActiveJob::Base` to `ApplicationJob`, etc.
I like the idea of generating that in the application but the framework should not use internally. The classes you changed here are actual subclasses of |
@@ -1,7 +1,7 @@ | |||
require "active_support/test_case" | |||
|
|||
module ActiveJob | |||
class TestCase < ActiveSupport::TestCase | |||
class TestCase < ApplicationTestCase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the idea of ApplicationTestCase
applies to Rails projects, not the Rails test suite itself.
@@ -25,7 +25,7 @@ module Generators | |||
# destination File.expand_path("../tmp", File.dirname(__FILE__)) | |||
# setup :prepare_destination | |||
# end | |||
class TestCase < ActiveSupport::TestCase | |||
class TestCase < ApplicationTestCase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also generate ApplicationTestCase
for new Rails apps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But ApplicationTestCase
make not sense since the application may have view tests, controller tests, integrations tests, model tests. If we add new test case superclasses we would need ApplicationViewTestCase
, ApplicationModelTestCase
. I think this is a problem to the application solve. If they are doing things to ActiveSupport::TestCase
just because it is shared across all they test cases probably they want to add only in the places the thing is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It still means that Rails must provide the structure for that in generators, yes?
@rafaelfranca this is how I see the current hierarchy of Rails test: As implemented in this PR: Is this what you're asking? |
Yes, exactly that. |
I agree this seems very messy. @gmalette could you show some examples of the monkey-patching this aims to help / alleviate? |
@matthewd in our codebase we gradually, throughout the years, added
This is fine for controller tests, elastic model tests, etc. However, we have a bunch of objects that don't need access to any form of database. All this setup is not useful to them. Some people had used tests that extended Bottom line is, for ~50% (guesstimate) of our tests, we want the costly setup. For the rest, we don't, and we also don't want to use edit last sentence |
To be fair, the simplest way to solve our problem would be to add a layer between unit tests and |
And how would this PR, in its current form, help you there? |
I'd be able to shove all the setup in |
We have this exact problem in Basecamp as well. Here's what we currently do in test_helper.rb: class ActiveSupport::TestCase
include SignalId::Testing
include ActiveJob::TestHelper, ActionMailer::TestHelper, ActionCableTestHelper,
AttachmentTestHelper, BlobPreviewTestHelper, ContentTestHelper, ChatTestHelper, EmailTestHelper, IdentityTestHelper,
NotificationsTestHelper, ReadingsTestHelper, ReportTestHelper, ScheduledJobTestHelper, TimeTestHelper, UserTestHelper,
AccountTestHelper
set_fixture_class playground_prefabs: Playground::Prefab
fixtures :all
setup { FileUtils.mkdir_p BC3::Application.config.x.local_storage.root }
teardown { FileUtils.rm_rf BC3::Application.config.x.local_storage.root }
setup { FileRepository::Cleversafe::FakeServer.setup! }
teardown { travel_back }
teardown { Current.reset }
teardown { RedisConnectable.clear_all }
setup { ApplicationJob.skip_reset_current = true }
teardown { ActionMailer::Base.deliveries.clear }
teardown { Rails.cache.clear }
end
class ActionController::TestCase
include SessionTestHelper, CookieTestHelper
teardown { Time.zone = "UTC" }
setup do
@request.host = accounts('37s').domain
@request.env['bc3.account.queenbee_id'] = accounts('37s').queenbee_id
end
end
class ActionDispatch::IntegrationTest
include ApiTestHelper, SignalId::Testing, SessionIntegrationTestHelper
setup do
host! BC3.domain.hostname
# Nullify the reset so a session can carry on between requests
Current.singleton_class.send(:alias_method, :real_reset, :reset)
Current.singleton_class.send(:define_method, :fake_reset) { }
Current.singleton_class.send(:alias_method, :reset, :fake_reset)
WebMock.disable_net_connect!(allow_localhost: true)
WebMock.stub_request(:any, /#{Regexp.escape(Launchpad.url)}/).to_rack(Launchpup.new(Rails.logger))
end
teardown do
Current.singleton_class.send(:alias_method, :reset, :real_reset)
end
def page
Capybara::Node::Simple.new(@response.body)
end
end It'd be much better if that configuration happened in ApplicationTestCase and friends. So I'd definitely support this. Any time we're doing mixins and changes like this, it should happen in a Application* class rather than straight on the framework classes. |
Here would be my revised plan: change the generators, to introduce Ultimately this will introduce a layer between the test cases and Rails. Good to go? Also any thought about how to handle the "upgrade"? Will we need to generate those classes in applications? I think yes. I don't think it would be a breaking change, but how resistant will people be to this refactor? edit: class names |
As from the thing I posted, I think the biggest value is actually in
ApplicationTestCase. At least that's where we have the most specialization.
As that's where all the stuff that's shared around fixtures, DB cleanups,
etc will live. So I still see ModelTestCase < ApplicationTestCase as a good
structure.
Yeah, doesn't have to be a breaking change at all. We'd just introduce this
for the generators going forward with a flag.
…On Thu, Mar 2, 2017 at 2:29 PM, Guillaume Malette ***@***.***> wrote:
Here would be my revised plan: change the generators, to introduce
ModelTestCase, JobTestCase, ControllerTestCase, etc. Applications will be
free to have a broad-painting application-level mixin (ApplicationTestCase
in my diagram) they use in all of these, but not opinionated by Rails.
Ultimately this will introduce a layer between the test cases and Rails.
Good to go?
Also any thought about how to handle the "upgrade"? Will we need to
generate those classes in applications? I think yes. I don't think it would
be a breaking change, but how resistant will people be to this refactor?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#28243 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAAKtTnsO_kgUrdsEAdDPMvcHrjnb0dDks5rhsQzgaJpZM4MQDwm>
.
|
😕 I'm not sure how to do that... ? Can we really have both I guess we could move the whole content of all current base test classes to mixins, such that
I'm a bit unconvinced by the use of mixins in application level code, but if you think it's better I don't mind. Unless that's not what you meant and/or have better ideas? |
Actually, yes, sorry. You're right. The problem is that we have a shared
baseclass that we want to specialize but also specialize generic classes
below that. Hmm. Don't really like the idea of turning the ActionMailer or
whatever into concerns.
Maybe what we need is something like ApplicationTestConcerns that's mixed
into ActiveSupport::TestCase and then we have ApplicationModelTestCase and
such still decent from that. That isn't really much different from
reopening ActiveSupport::TestCase directly, though.
…On Thu, Mar 2, 2017 at 3:23 PM, Guillaume Malette ***@***.***> wrote:
So I still see ModelTestCase < ApplicationTestCase
😕 I'm not sure how to do that... ? Can we really have both ApplicationControllerTestCase
< ApplicationTestCase AND ApplicationJobTestCase < ApplicationTestCase
while preserving backward compatibility?
I guess we could move the whole content of all current base test classes
to mixins, such that ActionController::TestCase includes
ActionController::TestCaseConcern, then generate as
ApplicationControllerTestCase < ApplicationTestCase
includes ActionController::TestCaseConcern
[image: untitled diagram 7]
<https://cloud.githubusercontent.com/assets/351915/23510977/a25dffe4-ff29-11e6-96f7-c7e086b99210.png>
I'm a bit unconvinced by the use of mixins in application level code, but
if you think it's better I don't mind. Unless that's not what you meant
and/or have better ideas?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#28243 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAAKtY6uGiEvy29-8mBfbGRkQOFdoOmRks5rhtD_gaJpZM4MQDwm>
.
|
Do you dislike specializing all the base classes for the application and let applications decide whether they need shared concerns? Then they can use
|
I think the #1 area where app-concerns cluster currently is in
ActiveSupport::TestCase. So whatever solution we arrive at should address
that or it's not worth addressing at all.
…On Thu, Mar 2, 2017 at 3:41 PM, Guillaume Malette ***@***.***> wrote:
Do you dislike specializing all the base classes for the application and
let applications decide whether they need shared concerns? Then they can
use ApplicationTestConcern and mix it in all the application classes.
class ApplicationMailerTestCase < ActionMailer::TestCase
include ApplicationTestConcern
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#28243 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAAKtXRTg5py5_iVn0QYPl7WUZNm3MNXks5rhtURgaJpZM4MQDwm>
.
|
@dhh iirc most of the test cases have a behavior module that they mixin, so they already are concerns. How do we make sure that the behavior in |
Hmm, yeah, I think we're going to get a timing issue if we just had a specially named concern that the framework then knew to include. Perhaps there isn't an easy fix here. |
@dhh I see you're using At Shopify, we're using |
I'll close this as we couldn't find a good way to do this. I'll be more than happy to pick it up if anyone has suggestions that solves all the concerns. |
I understand this PR isn't complete; I'd like to see if the idea gets traction.
Summary
All Rails test classes extend
ActiveSupport::TestCase
. This makes itvery had for applications to customize the test inheritance; they simply
have to reopen/freedom-patch
ActiveSupport::TestCase
.Having a class implemented by the application would make it much more
straightforward. It's also in line with the way Rails has moved from
ActiveRecord::Base
toApplicationRecord
,ActiveJob::Base
toApplicationJob
, etc.