RSpec - How to get a better error message? - ruby-on-rails

I am used to PHPUnit, so I found RSpec to be inferior when it comes to showing what has gone wrong, where and why.
For example, in PHPUnit, I can get the stack trace when an exception is raised (and even with -b option in RSpec, all I can get is the stack trace of RSpec exceptions, and not Rails's)
Also, when some error occurs, it shows you the ACTUAL value and the EXPECTED value.
Those two features I'd like to achieve in RSpec. Getting a detailed error message that includes the stack trace, in case of an Exception of Ruby or of Rails, and to know what was the actual value.
Any ideas of how to accomplish this?

If you run
rspec --help
you will see all the options you can pass (or configure via RSpec.configure) to the runner. One of the will force RSpec to show the entire backtrace
-b, --backtrace Enable full backtrace.
You can also configure the excluded/included lines to control how deep you want the backtrace to go.
As for the actuals vs expected value, this is supported by default in RSpec. See for example
For custom-defined objects, it also print out a diff.

Related

Possible to mute irrelevant error messages?

If I erroneously would call a private method in the console, I'm getting 25 lines of error messages like the following:
from /Users/Omonia/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/railties-4.2.4/lib/rails/commands/console.rb:110:in `start'
The first line normally gives meaningful information but the rest could easily be muted.
Is there any way to clean this up?
If you're using the standard IRB REPL as rails console, adding the following line :
IRB.conf[:BACK_TRACE_LIMIT] = 1
to your ~/.irbrc file truncates the output to the desired limit.
However I would advise against doing so, because error backtraces can be immensely helpful in complex debugging cases.

Showing only specific test case in test.log

I am writing Rails tests using the standard Test::Unit/TestCase.
Is there any way to somehow filter what gets printed to the log, so that you only print the stack for specific test cases.
I have a functional test file with many test cases in it, and I'm really only interested in debugging one test case. Printing my own log statements still requires searching through a few thousand lines of generated log. Or something similar to the RSpec 'pending' functionality.
Run from a command line ruby test/unit/my_model.rb to run one test suite. You can also use a debugger, such as (wrapped by) RubyMine or pry, to stop on a specific test case and look at the log.
But if a sledge-hammer does not solve the problem, you can use tweezers: config.logger.level = Logger::WARN in your test.rb, from Set logging levels in Ruby on Rails
It is probably better if instead of strangling the output to log/test.log, you become familiar with a command such as grep. Grep allows you to run very advanced search queries through files or directories, as long as your running on some flavor of *nix. The simplest use would be
grep search_term file_name
The reason I say you shouldn't constrict the log output is because someday that could bit you in the **s. Hope this helps.

Logging all method calls in a Rails app

Is there an easy way to log all method calls in a Rails app?
My main use for this would be in testing (and in debugging tests). I want to have more of a history than a stacktrace provides (for instance, when running rspec with the '-b' option).
It's easy to do. Just add 5 lines of code into your script/server:
#!/usr/bin/env ruby
set_trace_func proc {
|event, file, line, id, binding, classname|
if event == "call" or event == "return"
printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
end
}
require File.expand_path('../../config/boot', __FILE__)
require 'commands/server'
It's described at http://phrogz.net/ProgrammingRuby/ospace.html#tracingyourprogramsexecution
Your application will become quite slow and you might get more output than you want. You can easily add more conditions on file/class/function names to avoid printing unwanted stuff.
Perftools might give you what you're looking for. It analyzes the entire process and can give you a graphical view that looks something like this. Rack perftools profiler is a rubygem that uses perftools and makes it easy to integrate with a Rails application, so I would recommend going with that if you want to try it.
Firstly stacktrace IS every method call that was on the stack at the time an error occurred, what other history could you want besides this?
Secondly, to answer your question, no there is no easy way to log all method calls. You could up your log level all the way to debug which should give you more stuff in the logs, but this will only be things that someone has actually chosen to log, unrelated to method calls.
It probably wouldn't be that difficult to patch ruby in such a way that every method call will print some log statements before and after the method execution, but this will once again be similar to what a stack trace would give you anyway and potentially less since you won't get line numbers etc.
If you want more info than the stack trace, logging is the way most people would do it.

"Maybe IRB bug!"

What exactly does this mean -- "Maybe IRB bug!"? What does that tell me about the potential root cause of an exception?
Note that the text "Maybe IRB bug!!" was printed after the stack trace as part of the exception output.
This message means that IRB detected the cause of the stack trace being inside IRB's own code, not in the code you entered to be executed. And depending on what you did before that, it is thus likely that you triggered a bug in IRB.
A stack trace or segfault of a tool itself (as opposed to an error in user-code) is considered a bug almost all of the time. A tool should never die on user data, but always fail gracefully and with meaningful error messages. The one you see here is an attempt for one of those :)

ruby tests - error messages don't include line numbers or file name

How do I get line numbers to be reported with my errors when testing. Here is what I get back on a typical error:
josh#josh-laptop:~/d/test$ ruby unit/line_test.rb -n test_update
Loaded suite unit/line_test
Started
E
Finished in 0.066663 seconds.
1) Error:
test_update(LineTest):
NameError: undefined local variable or method `sdf' for
#<LineTest:0xb6e61304>
1 tests, 0 assertions, 0 failures, 1 errors
It is tough to debug without a line number and filename. From the code
samples I've seen, people generally get back a more verbose error
reports. How do I enable this?
Thanks!
[Edit] From the Rails Guide
$ ruby unit/post_test.rb -n test_should_report_error
Loaded suite -e
Started
E
Finished in 0.082603 seconds.
1) Error:
test_should_report_error(PostTest):
NameError: undefined local variable or method `some_undefined_variable' for #<PostTest:0x249d354>
/test/unit/post_test.rb:6:in `test_should_report_error'
1 tests, 0 assertions, 0 failures, 1 errors
How long are your unit tests? Typically, a test case should only be a couple of lines of code. If not, consider splitting it up. That should really narrow it down, particularly for an undefined variable or method. In any case, if you install ruby-debug, you can step through the test case and see exactly where the problem lies.
I found an answer that I don't like but which gets the job done. I thought I'd post it in case others can't find a better solution
ruby -d unit/line_test.rb -n test_update
-d sets the $DEBUG to true and gives a dump with error, warning, exception details
If this is a Rails app? Then most likely Rails' backtrace cleaner is getting in the way. Most likely because your directory starts with "unit" not "test" like Rails assumes. I ran into a similar issue (a plugin I was developing was outside the Rails directory so the entire backtrace was being filtered).
Check out the default silencer and either add a filter so that it will pass this silencer (filters run before silencers) OR simply remove the silencer with remove_silencers!. Rails provides a file in the initializers directory that will do this but the line is commented out by default.

Resources