For some reason, RSpec is not recognizing assertions in one of my spec files - but runs the print statement around it.
To start the spec test, on the terminal:
rspec spec/lib/slots_scheduler_spec.rb
Part of the spec file that asserts... (is part of a loop)
print "#{slots_result[0].date} #{slot.date}\n"
slots_result[0].date.should == slot.date
And what I see on the console...
....
2012-11-18 2012-11-11
2012-11-25 2012-11-11
No examples found.
Finished in 0.00005 seconds
0 examples, 0 failures
If something is wrong, I expect some other message than '0 examples, 0 failures'. Why are my tests ignored like this?
You Haven't Defined an Example Group
Your code, as posted above, has no example groups. Example groups require a describe or context block, and a specify or it block for each test in order to work.
Your print statements work because they are valid Ruby. However, the RSpec DSL requires more from you before it will result in an actual test being performed.
Related
Say I have a user_spec.rb for my User model, and I want to run that test inside the rails console.
My first thought is to execute the usual shell command:
exec("./spec/user_spec.rb")
But is there a simpler way to run the spec? I'm trying to automate some of the tests (and reinvent the wheel a little, yes), so being able to trigger an rspec test inside of another Ruby class seems ideal.
Edit:
output = `./spec/user_spec.rb`
This will provide the rspec output and $?.success? will then provide a pass fail value. Is this the best solution here? Or is there a way to call an RSpec class itself?
As pointed out by Anthony in his comment, you can use RSpec::Core::Runner to basically invoke the command line behavior from code or an interactive console. However, if you use something like Rails, consider that your environment is likely going to be set to development (or even production, if this is where you'll execute the code). So make sure that whatever you do doesn't have any unwanted side-effects.
Another thing to consider is that RSpec globally stores its configuration including all example groups that were registerd with it before. That's why you'll need to reset RSpec between subsequent runs. This can be done via RSpec.reset.
So putting it all together, you'll get:
require 'rspec/core'
RSpec::Core::Runner.run(['spec/path/to_spec_1.rb', 'spec/path/to_spec_2.rb'])
RSpec.reset
The call to RSpec::Core::Runner.run will output to standard out and return the exit code as a result (0 meaning no errors, a non-zero exit code means a test failed).
..
Finished in 0.01791 seconds (files took 17.25 seconds to load)
2 example, 0 failures
=> 0
You can pass other IO objects to RSpec::Core::Runner.run to specify where it should output to. And you can also pass other command line parameters to the first array of RSpec::Core::Runner.run, e.g. '--format=json' to output the results in JSON format.
So if you, for example, want to capture the output in JSON format to then further do something with it, you could do the following:
require 'rspec/core'
error_stream = StringIO.new
output_stream = StringIO.new
RSpec::Core::Runner.run(
[
'spec/path/to_spec_1.rb',
'spec/path/to_spec_2.rb',
'--format=json'
],
error_stream,
output_stream
)
RSpec.reset
errors =
if error_stream.string
JSON.parse(error_stream.string)
end
results =
if output_stream.string
JSON.parse(output_stream.string)
end
Run bundle exec rspec to run all tests or bundle exec rspec ./spec/user_spec.rb to run the specific test
When running minutest tests, is it possible to peek at the information about the errors that has happened?
For example, this test suite takes ten minutes to complete. But I would like some more info about the letter E appearing in the tests result.
I don't want to wait ten minutes.
*** Running FRONTEND component engine specs
Run options: --seed 29704
# Running:
......................................................................................................................................................................................E...........
That's E for "error", so one of your tests is failing. Normally you get output that explains more. Once you identify which test is failing you can run that test in a more focused capacity, like:
ruby test/unit/broken_test.rb --name=test_that_is_broken
Where that is the path to your test script and the name of the testing method that's failing.
You may need to make your tests self-contained, able to be run this way, by using:
require_relative '../test_helper'
Or whatever the helper stub is that kicks off the testing framework. Some skeleton files contain things like require 'test_helper' which won't be found in your current $LOAD_PATH.
it 'should be an array and not be empty' do
pending
expect(a.class).to be(Array)
expect(a.empty?).to be(false)
expect(a.first.class).to be(ExampleClass)
end
When I run rspec:
Failures:
1) should be an array and not be empty FIXED
Expected pending 'No reason given' to fail. No Error was raised.
# ./spec/example_spec.rb:19
Any ideas why this is being listed as a failure?
As of Rspec 3.x, pending specs are actually run, and if they pass, it's considered a failure (because if it passes, then Rspec thinks it shouldn't be pending).
You can use skip instead of pending to make sure your spec doesn't actually run.
More info: https://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#changes-to-pending-semantics-and-introduction-of-skip
Here's your clue:
should be an array and not be empty FIXED
Things that pass will cause a pending test to fail. Check the docs for examples [1], [2].
RSpec 2
RSpec 3
I'm trying to get this:
http://www.amazon.com/Dream-Cheeky-902-Electronic-Reference/dp/B004D18MCK
working on a mac using this:
https://github.com/derrick/dream_cheeky
After running rake, it says "4 examples, 0 failures, 2 pending". How do I execute the actual ruby example that I want? (I'm a Ruby noob)
Thanks!
4 examples, 0 failures, 2 pending is a message from RSpec saying there are two unit tests that are pending.
A pending test is generally a test that the author hasn't fully implemented yet. You can think of it like a function that you stubbed out to finish later. For example:
def add_two_numbers(n1, n2)
# TODO write some code that adds n1 and n2
end
As the comments mention, a pending test won't stop you from using the library successful.
Here is an example of pending:
https://www.relishapp.com/rspec/rspec-core/v/2-0/docs/pending/pending-examples
When I run my model specs and controller specs separately, it's fine. When I run them together, I get a stack overflow, literally :)
$ bundle exec rspec --fail-fast spec/models
........
Finished in 0.44274 seconds
8 examples, 0 failures
$ bundle exec rspec --fail-fast spec/controllers
..
Finished in 0.99339 seconds
2 examples, 0 failures
$ bundle exec rspec --fail-fast spec
F
Failures:
1) HerpController derp derp example
Failure/Error: Unable to find matching line from backtrace
SystemStackError:
stack level too deep
# /Users/jared/.rvm/gems/ruby-1.9.2-p290/gems/actionpack-3.2.1/lib/abstract_controller/layouts.rb:359
Finished in 0.02241 seconds
1 example, 1 failure
How do I even begin to debug this? Thanks.
Removing half of my specs at a time turned up the problem. I suppose this is an example of bisect debugging. Thanks to Frederick Cheung, whose comment suggested this approach.
For posterity, this was the problem.
include Rails.application.routes.url_helpers
describe "Attendee#next_page" do
end
Apparently, includes go inside the describe
describe "Attendee#next_page" do
include Rails.application.routes.url_helpers
end
I have a lot to learn about rspec. :)
You can either put a debugger statement in your code and debug that way, or just start using puts "got here" in the places of your code that you know are being run. I would suggest using something meaningful instead of "got here" too :-)
I'd start either with puts or raise statements at key points in your code so you can start to narrow down which line is causing the problem. Once you start getting close, you can comment out one line at a time to figure out which line the problem disappears with - as soon as you've got it down to one line, you can figure out what that line is doing that Ruby doesn't like.
In general terms of where to start, "Stack level too deep" is usually an infinite loop or infinite recursion problem - I'd imagine that there's something going on where a model is invoking a controller that's invoking the model, or vice-versa. No way to know for sure until you start commenting out lines, but any place where you've got function calls is going to belong on your suspect short list. Good luck!
Possibly you can get "Unable to find matching line from backtrace" error in case you are checking some var which wasn't initialised actually
In this example pay attention to var observation which is not initialised in the wrong snippet
wrong snippet
describe "GET index" do
it "assigns all observations as #observations" do
get :index, {}, valid_session
assigns(:observations).should eq([observation])
end
end
fixed example (line 3)
describe "GET index" do
it "assigns all observations as #observations" do
observation = Observation.create! valid_attributes
get :index, {}, valid_session
assigns(:observations).should eq([observation])
end
end
Sometimes we rely on using let as initializer, but forget to add it e.g.
let(:observation) {FactoryGirl.create(:observation)}