-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
Make the test environment show rescuable exceptions in responses #45867
Conversation
c06c27d
to
c1f89ca
Compare
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.
Feature makes sense to me. this is one of things that annoyed me for too long. Implementation can be improved. commented inline on how.
if config == :none | ||
false | ||
elsif config == :rescuable | ||
ActionDispatch::ExceptionWrapper.rescue_responses.include?(exception.class.name) |
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.
Request should not know about the existence of the ExceptionWrapper
. Isn't the exception already wrapped when we call this method? I think it can be since we wrap it in invoke_interceptors
and also later in render_exception
. We should just ask to the exception if it is a rescue_response?
. I'd even move this entire implementation out of Request
since it belongs more to the ExceptionWrapper
than to the request. We should just read the get_header("action_dispatch.show_exceptions")
from the request.
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.
@rafaelfranca Thanks for the review and sorry for the late reply. I have applied this suggestion in the latest revision. Please let me know if it is what you had in mind. All additional feedback is welcome.
cab4cf8
to
fa418e2
Compare
b1e98b4
to
c885746
Compare
Thanks @skipkayhil I applied both suggestions in the latest push. |
c885746
to
2506ada
Compare
2506ada
to
8322b96
Compare
8322b96
to
87481bd
Compare
87481bd
to
880c73b
Compare
fe8cf2b
to
445c9bc
Compare
c7fd2b8
to
c6eaad0
Compare
7dcd6f8
to
deb9d92
Compare
Background ---------- During integration tests, it is desirable for the application to respond as closely as possible to the way it would in production. This improves confidence that the application behavior acts as it should. In Rails tests, one major mismatch between the test and production environments is that exceptions raised during an HTTP request (e.g. `ActiveRecord::RecordNotFound`) are re-raised within the test rather than rescued and then converted to a 404 response. Setting `config.action_dispatch.show_exceptions` to `true` will make the test environment act like production, however, when an unexpected internal server error occurs, the test will be left with a opaque 500 response rather than presenting a useful stack trace. This makes debugging more difficult. This leaves the developer with choosing between higher quality integration tests or an improved debugging experience on a failure. I propose that we can achieve both. Solution -------- Change the configuration option `config.action_dispatch.show_exceptions` from a boolean to one of 3 values: `:all`, `:rescuable`, `:none`. The values `:all` and `:none` behaves the same as the previous `true` and `false` respectively. What was previously `true` (now `:all`) continues to be the default for non-test environments. The new `:rescuable` value is the new default for the test environment. It will show exceptions in the response only for rescuable exceptions as defined by `ActionDispatch::ExceptionWrapper.rescue_responses`. In the event of an unexpected internal server error, the exception that caused the error will still be raised within the test so as to provide a useful stack trace and a good debugging experience.
deb9d92
to
e28f147
Compare
@@ -174,6 +174,29 @@ def self.status_code_for_exception(class_name) | |||
Rack::Utils.status_code(@@rescue_responses[class_name]) | |||
end | |||
|
|||
def show?(request) | |||
# We're treating `nil` as "unset", and we want the default setting to be | |||
# `:all`. This logic should be extracted to `env_config` and calculated |
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.
Explore if we can really move this logic to env_config
.
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.
Previous exploration: #46609 (comment)
Ah, I had looked at making it configurable on middleware initialization and not just setting on env_config
...
The `request.show_exceptions?` method will be removed in Raiils 7.1 PR: rails/rails#45867 So this commit adopts the new API to check whether to show exception if the Rails version is 7.1 or later.
I don't have strong feeling about the change, but I want to share how we can debug such problem, perhaps in a even better way, by utilising the Because I'm a maintainer of (BTW this is how I actually pinned down the problem and found this PR.) This is essentially how the test looks like: it "test something" do
get "/posts"
expect(response).to have_http_status(:internal_server_error)
expect(transport.events.count).to eq(2)
end And with this change, it breaks as
As described in the PR, it's a request spec so there's not much information when the test failed. What the failure means is that So I added these 2 lines it "test something" do
+ debugger(do: "trace exception")
get "/posts"
+ debugger(do: "trace off")
expect(response).to have_http_status(:internal_server_error)
expect(transport.events.count).to eq(2)
end They enable the And here's the output: As you can see, with this feature, we get to see all exceptions raised during the request, which significantly increases its visibility for debugging. I also have revived the Tracer.trace_exception do
get "/posts"
end And it will output very similar output: I think by utilising the |
* Update sentry-rails' show_exception check The `request.show_exceptions?` method will be removed in Raiils 7.1 PR: rails/rails#45867 So this commit adopts the new API to check whether to show exception if the Rails version is 7.1 or later. * Update changelog
* Update 7_1_release_notes.md For context see #45867 Include in release notes the deprecation of `true` and `false` values for `config.action_dispatch.show_exceptions` in favor of `:all`, `:rescuable` and `:none`. * Update 7_1_release_notes.md Co-authored-by: Hartley McGuire <skipkayhil@gmail.com> --------- Co-authored-by: Hartley McGuire <skipkayhil@gmail.com> Co-authored-by: Rafael Mendonça França <rafael@rubyonrails.org>
in my Rails 7 I had to change this to :all, because I use a custom error handler using: |
Background
During integration tests, it is desirable for the application to respond
as closely as possible to the way it would in production. This improves
confidence that the application behavior acts as it should.
In Rails tests, one major mismatch between the test and production
environments is that exceptions raised during an HTTP request (e.g.
ActiveRecord::RecordNotFound
) are re-raised within the test ratherthan rescued and then converted to a 404 response.
Setting
config.action_dispatch.show_exceptions
totrue
will make thetest environment act like production, however, when an unexpected
internal server error occurs, the test will be left with a opaque 500
response rather than presenting a useful stack trace. This makes
debugging more difficult.
This leaves the developer with choosing between higher quality
integration tests or an improved debugging experience on a failure.
I propose that we can achieve both.
Solution
Change the configuration option
config.action_dispatch.show_exceptions
from a boolean to one of 3 values:
:all
,:rescuable
,:none
. Thevalues
:all
and:none
behaves the same as the previoustrue
andfalse
respectively. What was previouslytrue
(now:all
) continuesto be the default for non-test environments.
The new
:rescuable
value is the new default for the test environment.It will show exceptions in the response only for rescuable exceptions as
defined by
ActionDispatch::ExceptionWrapper.rescue_responses
. In theevent of an unexpected internal server error, the exception that caused
the error will still be raised within the test so as to provide a useful
stack trace and a good debugging experience.
Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]