show full stack track in minitest - ruby

given the following test:
require 'minitest/spec'
require 'minitest/autorun'
describe 'stuff' do
def foo
assert false
end
it "should show stack trace" do
foo
end
end
I am getting an error saying failed assertion on line 6, is it possible to show full stack trace so I know it got called within the it statement?

With default Minitest, you only get the (abbreviated) stack trace when an exception is raised. Try the Minitest::Reporters gem if you want to be able to customize your output easily - including also showing a partial stack trace for failures.

The minitest failure message should show which test has failed - in the case of an exception being raised then a stack trace would be useful.
So, if I add another test calling the foo method then I will also see that test fail, and the same line.
describe 'stuff' do
def foo
assert false
end
it "should show stack trace" do
foo
end
it "will not show stack trace" do
foo
end
end
Then I see;
Finished in 0.001372s, 1457.7259 runs/s, 1457.7259 assertions/s.
1) Failure:
stuff#test_0001_should show stack trace [t.rb:6]:
Failed assertion, no message given.
2) Failure:
stuff#test_0002_will not show stack trace [t.rb:6]:
Failed assertion, no message given.
You would generally use a custom method in a test to verify common functionality;
it 'works like a Widget' do
widget = WidgetMaker.do_something
verify_widget widget
end
private
def verify_widget(widget)
assert_ # etc ...
end

It seems -b is no longer a valid option for rake test. I'm running minitest (5.13.0).
Use -t instead:
rake test -h
...
-t, --trace=[OUT] Turn on invoke/execute tracing, enable full backtrace. OUT can be stderr (default) or stdout.

As #Rafael mentioned in the comments, there's the -b flag.
This flag is added by the rails extension to minitest, so it is a minitest option, but requires rails.
The correct order of the options is this:
rails test -b #...
Check it by calling the help:
> rails test -h
Usage: rails test [options] [files or directories]
You can run a single test by appending a line number to a filename:
rails test test/models/user_test.rb:27
You can run multiple files and directories at the same time:
rails test test/controllers test/integration/login_test.rb
By default test failures and errors are reported inline during a run.
minitest options:
-h, --help Display this help.
--no-plugins Bypass minitest plugin auto-loading (or set $MT_NO_PLUGINS).
-s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake
-v, --verbose Verbose. Show progress processing files.
-n, --name PATTERN Filter run on /regexp/ or string.
--exclude PATTERN Exclude /regexp/ or string from run.
Known extensions: simplecov, minitest_reporter, rails, pride
-w, --warnings Run with Ruby warnings enabled
-e, --environment ENV Run tests in the ENV environment
-b, --backtrace Show the complete backtrace
-d, --defer-output Output test failures and errors after the test run
-f, --fail-fast Abort test run on first failure or error
-c, --[no-]color Enable color in the output
-p, --pride Pride. Show your testing pride!

Related

minitest-reporters does not change minitest output style

I have been trying to use the minitest-reporters gem to alter the output style of Ruby's builtin minitest testing library. However, it does not actually change the output.
It should be noted that I am not using Rails or Rake, but I didn't think that would make a difference. I am simply trying to test a Ruby command-line program that I have written.
Here's a dumb little test case (let's call it dumbtest.rb) that I was trying out:
require 'minitest/autorun'
require 'minitest/reporters'
Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(:color => true), Minitest::Reporters::SpecReporter.new]
describe "MiniTest demo" do
describe "when asked about the number 2" do
it "should be equal to the number 2" do
2.must_equal 2
end
end
end
When I run the test, it just produces the default minitest output (i.e. colorless, no descriptions of passing tests, etc.):
$ ruby -Ilib:test dumbtest.rb
Run options: --seed 48983
# Running:
.
Finished in 0.001356s, 737.6595 runs/s, 737.6595 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
With minitest-reporters enabled, I expect the output to look something more like this (i.e. list both passing and failing tests as opposed to just failing, the word PASS is colored green, the final summary is color-coded, etc.):
There are no runtime errors. It's just not working for me. Any idea why?

Silence a specific guard plugin?

I´m using guard-yard to automatically run YARD. However the output it has is really annoying and makes it hard to read the RSpec output (which is more interresting).
guard 'yard' do
watch(%r{app/.+\.rb})
watch(%r{lib/.+\.rb})
watch(%r{ext/.+\.c})
end
Q. How do I silence the output of this Guard plugin?
The yard tool output can be redirected. AFAIK you can't disable all notifications for guard.
FWIW: This is the way I set up yard in my Guardfile to hide part of the output:
guard :yard, stdout: 'log/yard.log', stderr: 'log/yard_error.log' do
watch(%r{app/.+\.rb})
watch(%r{lib/.+\.rb})
end
Option 1: You may want to only run Yard if the tests pass:
group :stuff, halt_on_fail: true do
guard :rspec, cmd: 'bundle exec rspec' do
# (stuff for guard-rspec template goes here
end
guard :yard do
watch(%r{app/.+\.rb})
watch(%r{lib/.+\.rb})
watch(%r{ext/.+\.c})
end
end
or ...
Option 2: you may prefer to just skip yard when you're focused on RSpec:
guard :rspec, cmd: 'bundle exec rspec' do
# (stuff for guard-rspec template goes here
end
guard :yard do
watch(%r{app/.+\.rb})
watch(%r{lib/.+\.rb})
watch(%r{ext/.+\.c})
end
and limit guard to just running rspec bundle exec guard -g rspec
Option 3: use the scope command to switch between groups/plugins
You can also use the scope command in the Pry interactor to tell Guard what you're interested in running, e.g.
# tells guard to just run rspec
[1] guard(main)> scope rspec
[2] RSpec guard(main)>
# or just yard
[1] guard(main)> scope yard
[2] Yard guard(main)>
# or everything again
[1] guard(main)> scope default
[2] Default guard(main)>
I had the same problem and I used interactor :off ate the beginning of the Guardfile, so your code should look like this:
interactor :off
guard 'yard' do
watch(%r{app/.+\.rb})
watch(%r{lib/.+\.rb})
watch(%r{ext/.+\.c})
end
To run it in the background and not receive any output in the console you should run the command as:
bundle exec guard <options> >/dev/null 2>&1 &

How to get rspec-2 to give the full trace associated with a test failure?

Right now if I run my test suite using rake spec I get an error:
1) SegmentsController GET 'index' should work
Failure/Error: get 'index'
undefined method `locale' for #
# ./spec/controllers/segments_controller_spec.rb:14:
in `block (3 levels) in '
This is normal as I do have an error :)
The problem is that the trace isn't very helpful. I know it broke in segments_controller_spec.rb, line 14, but this is just where I call the test:
### segments_controller_spec.rb:14
get 'index'
I would prefer to have the actual line breaking and the complete trace, not the part in the spec folder.
Running with --trace doesn't help.
You must run rspec with -b option to see full backtraces
Another (easier) alternative is to edit the .rspec file, and add the backtrace option.
It should look somewhat like this:
--colour
--backtrace
That will give you the full backtrace.
Hope this helps.
This will also work:
# rails_helper.rb
RSpec.configure do |config|
config.full_backtrace = true
end
Another approach is to clear all backtrace exclusion patterns in spec_helper.rb. I like this solution most as I'm able to keep all RSpec settings in one place and get rid of .rspec file or explicit --backtrace in .travis.yml.
# spec_helper.rb
RSpec.configure do |config|
config.backtrace_exclusion_patterns = []
end
I don't know how to get the controller error to show up in rspec. Sometimes it shows up but I don't know what conditions cause it to show up. Here is a way to see the error fairly quickly though:
Open another terminal session and run:
tail -f log/test.log
Then go back to the terminal session and run just the spec that had the error:
bin/rspec -b spec/requests/posts/index_spec.rb
Go back to the tail of the log and you should see the error, hopefully without too much other stuff surrounding it (because you ran the failing test by itself).
One more option when all else fails is to just add a rescue block and print out the stack try or add a binding pry statement there and use show-stack.
rescue Exception => e
puts ""
puts e.backtrace
puts ""

Is it possible to run a single test in MiniTest?

I can run all tests in a single file with:
rake test TEST=path/to/test_file.rb
However, if I want to run just one test in that file, how would I do it?
I'm looking for similar functionality to:
rspec path/to/test_file.rb -l 25
The command should be:
% rake test TEST=test/test_foobar.rb TESTOPTS="--name=test_foobar1 -v"
Have you tried:
ruby path/to/test_file.rb --name test_method_name
No gem required:
ruby -Itest test/lib/test.rb --name /some_test/
Source: http://blog.arvidandersson.se/2012/03/28/minimalicous-testing-in-ruby-1-9
This is one of the things that bother me about the string name definition in tests.
When you have:
def test_my_test
end
you always know how your test is named so you can execute it like this:
ruby my_test -n test_my_test
But when you have something like:
it "my test" do
end
you are never sure how this test is really named internally so you can not use the -n option just directly.
To know how this test is named internally you only have an option: execute the whole file to try to figure out looking in the logs.
My workaround is (temporally) add something to the test name very unique like:
it "my test xxx" do
end
and then use the RegEx version of the '-n' parameter like:
ruby my_test.rb -n /xxx/
I'm looking for similar functionality to rspec path/to/file.rb -l 25
With Nick Quaranto's "m" gem, you can say:
m spec/my_spec.rb:25
If you are using MiniTest with Rails 5+ the best way to run all tests in a single file is:
bin/rails test path/to/test_file.rb
And for a single test (e.g. on line 25):
bin/rails test path/to/test_file.rb:25
See http://guides.rubyonrails.org/testing.html#the-rails-test-runner
You can use this to run a single file:
rake test TEST=test/path/to/file.rb
I also used
ruby -I"lib:test" test/path/to/file.rb
for better display.
There are 2 ways to do it:
Run tests 'manually' (see Andrew Grimm's answer).
Hack Rake::TestTask target to use a different tests loader.
Rake::TestTask (from rake 0.8.7) theoretically is able to pass additional options to MiniTest::Unit with a "TESTOPTS=blah-blah" command line option, for example:
% rake test TEST=test/test_foobar.rb TESTOPTS="--name test_foobar1 -v"
In practice, the option --name (a filter for test names) won't work, due to rake internals. To fix that you'll need to write a small monkey patch in your Rakefile:
# overriding the default rake tests loader
class Rake::TestTask
def rake_loader
'test/my-minitest-loader.rb'
end
end
# our usual test terget
Rake::TestTask.new {|i|
i.test_files = FileList['test/test_*.rb']
i.verbose = true
}
This patch requires you to create a file test/my-minitest-loader.rb:
ARGV.each { |f|
break if f =~ /^-/
load f
}
To print all possible options for Minitest, type
% ruby -r minitest/autorun -e '' -- --help
You can pass --name to run a test by its name or a number within its name:
-n, --name PATTERN Filter run on /regexp/ or string.
e.g.:
$ ruby spec/stories/foo_spec.rb --name 3
FAIL (0:00:00.022) test_0003_has foo
Expected: "foo"
Actual: nil
This flag is documented in Minitest’s README.
I am in Rails Version 4.2.11.3 and Ruby Version 2.4.7p357
Below one worked for me.
ruby -Itest <relative_minitest_file_path> --name /<test_name>/
If you are using Turn gem with minitest, just make sure to use Turn.config.pattern option since Turn Minitest runner doesn't respect --name option in ARGs.
I'm looking for similar functionality to:
rspec path/to/test_file.rb -l 25
There is a gem that does exactly that: minitest-line.
gem install minitest-line
ruby test/my_file -l 5
from https://github.com/judofyr/minitest-line#minitest-line
I use ruby /path/to/test -n /distinguishable word/
Edit:
-n is a shorthand for --name. distinguishable word can be any string you put in the test description, I usually use some random word that I know won't be present in other tests' descriptions.
Following will work
def test_abc
end
test "hello world"
end
This can run by
bundle exec ruby -I test path/to/test -n test_abc
bundle exec ruby -I test path/to/test -n test_hello_word
Install gem minitest-focus and use the keyword focus on test/spec like below to run only the specific test.
focus
def test
end
focus
it "test" do
end
This would not need any command line argument to be passed.

How do you run a specific test with test/spec (not a specific file, but a spec within a given file)?

With Test::Unit, I can run:
ruby path/to/test.rb --name=test_name_that_i_want_to_run
Thus far, I have not been able to figure out how to do this with test/spec specifications. I am wondering if the way that specifications are automatically named does not allow me to do something like this.
Take the following spec for example:
require 'rubygems'
require 'spec'
describe 'tests' do
it 'should be true' do
1.should == 1
end
it 'should be false' do
1.should_not == 2
end
end
You can execute a single spec by using the -e flag and providing the portion specified by the it block. e.g. ruby my_spec.rb -e 'should be false'
After contacting the gem maintainer, Christian Neukirchen, I found out how to do this, so I am documenting it here for future reference.
specrb path/to/test.rb --name ".*should behave this way.*"
I needed to use the specrb test runner, an extended version Test::Unit's test runner, rather than just the ruby command.
You can also do this with the ruby command:
ruby path/to/test.rb -n "/should behave this way/"

Resources