I'm writing tests for a Ruby Rails application, and I have a block of code that is supposed to catch an error thrown by my Redis server if Ruby cannot connect to it. Currently, the code looks like this:
begin
config.before(:all) { Resque.redis.select 1 }
config.after(:all) { Resque.redis.keys("queue:*").each { |key| Resque.redis.del key } }
rescue Exception
puts "RESCUED REDIS ERROR"
end
According to the stack trace when I try to run the tests, the second line of that code snippet -- config.before(:all) {...} -- throws a Redis::CannotConnectError. After a lot of "e.class.superclass.superclass..." commands, I determined that this error inherited from StandardError.
After that I got stuck. I tried catching the error with "rescue Redis::CannotConnectError", then "rescue", and finally "rescue Exception", but the error is still thrown. However, I tried the same things in the Ruby command prompt, and the exception was caught every time
Could anyone help me work out what's happening here? Thanks!
The problem is that the blocks passed to before and after are not being executed at the time they're defined; instead, they're being stored and then called later by Rspec before and after each spec file runs.
You'll probably want to move the begin/rescue within the blocks instead:
config.before(:all) do
begin
Resque.redis.select 1
rescue Exception
puts "RESCUED REDIS ERROR"
end
end
# same for config.after(:all)
Related
class **ConverterFile**
attr_accessor :old_file
SUPPORT_IMAGE_FORMAT = %w[png jpg jpeg pdf].freeze
def initialize(old_file)
#old_file = old_file
end
def to_image_type(file_format)
raise 'format not support' if file_format.blank? || SUPPORT_IMAGE_FORMAT.exclude?(file_format)
return old_file if File.extname(#old_file) == ".#{file_format}"
converted_file = MiniMagick::Image.open(#old_file.path)
converted_file.format(file_format)
File.open(converted_file.path)
rescue StandardError => e
nil
end
end
describe '#to_image_type' do
let(:png_file) { File.open(Rails.root.join('spec/support/files/logo.png')) }
context 'when convert to jpg file' do
it 'convert png file to jpg successfuly' do
new_file = described_class.new(png_file).to_image_type('jpg')
expect(File.extname(new_file)).to eq('.jpg')
end
end
end
error-in-gitlab-ci-cd
I'am confusing because i' try run spec in env dev local is pass but gitlab ci/cd error every times. I think error is about reference file missing not sure.
The error says that File.extname is being called with a nil argument:
File.extname(nil)
#=> TypeError: no implicit conversion of nil into String
This means new_file must be nil.
This means described_class.new(png_file).to_image_type('jpg') must be returning nil.
Why is this happening? Well, it's hard for me to say for sure without taking a closer look at the CI setup, but I am highly suspicious of this part of the code:
rescue StandardError => e
nil
end
Your method is silently swallowing errors, and returning nil. That doesn't seem like a good idea here in general, and it's probably hiding the true cause of the test failure!
My suspicion is that you have not committed the file 'spec/support/files/logo.png' into source control. So the test passes locally, but fails on CI where this file does not exist.
I think an exception is being raised when the non-existed file gets opened, but you're capturing the exception and returning nil -- which results in this more confusing test failure message.
I'm trying to reduce the amount of noise in my logs and would like to disable Rails from logging the stack trace during errors.
Since I am using an error reporting service (Honeybadger.io) I don't need to see the stack trace in the logs as it's already available in the exception report from the error handling service.
The default Rails middleware DebugExceptions is what logs the errors.
You can remove it with config.middleware.delete(ActionDispatch::DebugExceptions) in your config/environment.rb or config/environments/production.rb
According to the docs you should be able to add a backtrace silencer that excludes every line by returning true in the block.
But, at least with Rails 4.2.5.2, this doesn't appear to be working and even if it did work you would still end up with a line in log about the exception.
Accidentally I discovered that if you raise an error inside a silencer block that this will suppress the error message and the entire backtrace which turns out to be exactly what I'm looking for.
Rails.backtrace_cleaner.add_silencer { |_line| raise }
Combining this hack with the concise_logging gem I can now have logs that look like the following:
Well, Rails.backtrace_cleaner.add_silencer works, but I woulnd call its behaviour predictable
https://github.com/vipulnsward/rails/blob/ecc8f283cfc1b002b5141c527a827e74b770f2f0/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb#L155-L156
Since application_trace is empty(This is because error is not from user code but route error), we are falling back to framework_trace, which does not filter it (it filters only noise).
You can solve it with creating your own log_formatter. In your development.rb and/or test.rb add
config.log_formatter = SilentLogger.new
config.log_formatter.add_silencer { |line| line =~ /lib/ }
And create simple class in models with only method call required. There you can modify your backtrace as you wish.
class SilentLogger
def initialize
#silencers = []
end
def add_silencer(&block)
#silencers << block
end
def call(severity, timestamp, progname, msg)
backtrace = (String === msg) ? "#{msg}\n" : "#{msg.inspect}\n"
return backtrace if #silencers.empty?
#silencers.each do |s|
backtrace = backtrace.split("\n").delete_if { |line| s.call(line) }
end
backtrace.join("\n")
end
end
Currently for a project I am using api_auth gem. I am hitting on an external api in a function by making a signed request. Currently my code looks like this.
access_id = "someKey"
secret_key = "someRandomGeneratedKey"
request = RestClient::Request.new(url: 'serverUrl', method: get, headers:'headers')
#signed_request = ApiAuth.sign!(access_id, secret_key, request)
#signed_request.execute
I am unable to apply any error handling code to that last statement where I execute the request. Any suggestions?
You have to use begin rescue block to exception handling.
begin
#TODO Exception occurring statement
rescue
#Exception handling code
end
As you should only rescue specific exception, rather than all.
So as your code suggest that you are using rest_client & api-auth gem so from documentation you can get list of exception that this gem raise.
Example - For rest_client below exceptions need to be handled. (probably this is the solution of your problem, just replace last line as given below)
begin
#signed_request.execute
rescue RestClient::ExceptionWithResponse, URI::InvalidURIError, RestClient::InternalServerError => err
p err
end
There are few Exceptions also generated by api-auth gem also like
ApiAuth::ApiAuthError, ApiAuth::UnknownHTTPRequest so you need to rescue all this exceptions.
Reference link -
http://www.rubydoc.info/gems/api-auth/1.4.0/
Thanks!
I was trying to run rspec from a model spec file, but I got this error: "An error occurred in an after hook"
"An error occurred in to after hook PG :: InFailedSqlTransaction:
ERROR: current transaction is aborted, commands ignored until end of
transaction. occurred at C :/ Ruby193/lib/.../postgresql_adapter: 294 "
I googled this issue, and I found a suggestion to downgrade my 'database_cleaner' to '1.0.1'. I did, but it doesn't work.
Does anyone have any idea how to solve this? Thanks in advance!
This can happen if you execute a bad SQL statement in the scope of a transaction, you rescue the exception from that statement, and then try and execute another SQL statement in the same transaction.
Once one statement in a transaction fails no more statements can be executed in that transaction.
Here's an example:
ActiveRecord::Base.transaction do
begin
ActiveRecord::Base.connection.execute "A bad query"
rescue => ex
puts ex.message
end
puts User.count
end
User.count raises PG::InFailedSqlTransaction because the previous SQL statement raised ActiveRecord::StatementInvalid and that was swallowed by the rescue.
So I would look for code that rescues in the scope of a transaction and then tries to run additional SQL statements.
I'm using some ruby code wrapped in a begin - rescue block but somehow it manages to still crash.
the block of code looks like this:
# Retrieve messages from server
def get_messages
#connection.select('INBOX')
#connection.uid_search(['ALL']).each do |uid|
msg = #connection.uid_fetch(uid,'RFC822').first.attr['RFC822']
begin
process_message(msg)
add_to_processed_folder(uid) if #processed_folder
rescue
handle_bogus_message(msg)
end
# Mark message as deleted
#connection.uid_store(uid, "+FLAGS", [:Seen, :Deleted])
end
end
Given this code i would assume that if process_message or add_to_processed_folder could not execute then rescue would kick in and call handle_bogus_message. That being said I'm running this code in a production environment and sometimes when i "get" an email message (this is run from a rake task) it dies with a SyntaxError.
For a look at the error message check out http://pastie.org/1028479 and not that process_message that it is referring to is the same process_message above. Is there any reason why begin - rescue won't catch this exception?
rescue without a parameter just rescues exceptions that inherit from StandardError. To rescue a SyntaxError use rescue SyntaxError.
To rescue all exceptions you would use rescue Exception, but note that that's a bad idea (which is why it's not the default behavior of rescue) as explained here and here. Especially this part:
Rescuing Interrupt prevents the user from using CTRLC to exit the program.
Rescuing SignalException prevents the program from responding correctly to signals. It will be unkillable except by kill -9.
rescue without any parameter accepts exceptions raised by StandardError class. Your error type is SyntaxError which is inherited from a different class called ScriptError. All these error classes are subclasses of Exception class. So as sepp2k suggested use rescue Exception to catch all kinds of exceptions.