Can rspec output the value that made a test fail? - ruby-on-rails

I have statements like:
#obj[:attribute].eql?("TestValue").should be_true
And it would be nice if instead of just telling me that the test failed, it told me that it failed because #obj[:attribute] was nil or was 1234 or whatever it was. Is there any way to do this?

When doing something like
#obj.attribute.should eql(5)
and it throws an error, you'll usually see
expected 5
got 10
Is there a specific reason why you are doing eql??

Sure, rspec does output the difference between expected and actual values. You just need to change your matcher to provide more relevant information to you. Right now your expectation is that the expression #obj[:attribute].eql?("TestValue") will be true and rspec will inform you that it was false instead. If you rewrite your expectation as
#obj[:attribute].should eql("TestValue")
You should see the sort of output you are looking for.

Related

RSpec expectation on stub fails

Here's the call I would like to test expectations for:
UserMailer.invoice_paid(user, invoice).deliver_later
Rails 5 ActionMailer behaviour in :test mode seems to return nil on every method of an ApplicationMailer class. This should be fine since I can just stub it like so:
invoice_paid_dbl = double(ActionMailer::MessageDelivery)
allow(UserMailer).to receive(:invoice_paid).and_return(invoice_paid_dbl)
This expectation fails:
expect(UserMailer).to receive(:invoice_paid).once
While this one passes:
expect(invoice_paid_dbl).to receive(:deliver_later).once
Shouldn't that be impossible? I thought maybe the method chain was confusing RSpec, but splitting up the line into this has no effect:
mail = UserMailer.invoice_paid(user, invoice)
mail.deliver_later
Adding .with(any_args) to the stub and expectation also has no effect (since that's the default anyways). The failure is expected: 1 time with any arguments, received: 0 times with any arguments.
Not getting how you have stubbed methods, but think that following will work for you
You are trying to stub chain of methods so need to use stub_chain instead of stub
UserMailer.stub_chain(:invoice_paid, :deliver_later).and_return(:invoice_paid_dbl)
I hope this will work and solve you problem. For more details please check docs
I'll leave the question up in case it helps others, but this was actually the result of a silly mistake. I had expect(UserMailer).to receive(:invoice_paid) earlier in the it block, and it was passing. It was the second expectation of that type which was failing. Oops.

RSpec error: 'but it does not respond to `include?`'

I am running the following rspec test
expect(City.first.city_openings('2014-05-01', '2014-05-05')).to include(#listing2,#listing3)
I am getting this result
This is confusing to me because it seems that my result does in fact include the right values. But rspec says that my result "does not respond to include?" Any ideas on how to fix this? I don't see much about it anywhere.
Your method city_openings return true and not a array.
TrueClass is not iterable with include? method.
See the documentation here
https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/include-matcher
https://relishapp.com/rspec/rspec-expectations/v/3-7/docs/built-in-matchers/match-matcher

RSpec 2 'something.should be`

I came across some horrible looking RSpec 2 test:
something.should be
Nope, I didn't accidentally forget to cut+paste the rest of the line,
that's it!
So what's the exact semantic of that? should_not be_nil ?
Please chime in why this is horrible style.
IMHO it's sloppy, not precise, and does not clearly communicate what's required. (it triggers my gag reflex ;)
You're correct - according to the docs object.should.be equals object.should_not be_nil
Documentation, 4th one down in that first list.
From the docs: "We recommend you use the expect syntax unless you have a specific reason you prefer the should syntax. We have no plans to ever completely remove the should syntax but starting
in RSpec 3, a deprecation warning will be issued if you do not explicitly enable it, with the plan to disable it by default in RSpec 4 (and potentially move it into an external gem)."
I believe the equivalent in newer syntax would be:
expect(something).to be
or more commonly:
expect(something).not_to be_false

capybara error message, test still passes

When I run integrations tests with Capybara/webkit I get this error message:
undefined|36|TypeError: Result of expression 'node' [undefined] is not an object.
However it doesn't cause the test to fail and it doesn't always occur. When it does occur it seems to occur at the same point in the test (right before the final assertion)
test:
it "does something with things" do
#....
within('#dialog_box') do
click_button 'Save'
end
puts 'after within'
page.should have_content(thing_attrs[:name])
puts 'after assertion'
end
Final output:
after within
undefined|36|TypeError: Result of expression 'node' [undefined] is not an object.
after assertion
does something with things [pass]
How can I narrow down what is causing this? It makes test output ugly :)
I had a very similar problem, the error I was getting was:
undefined|0|TypeError: 'undefined' is not an object
In the end in order to figure out where it was coming from, I removed js files from application.js one by one until the error disappeared. Once I had narrowed it down, I figured out that there was, in fact, an undefined variable, which wasn't causing any issues and hence all tests were passing.
There might be a better way to do this, not really sure, but this approach worked for me. Best of luck.

rails 3 test case error.on(:field) Vs. errors[:field]

I am working on the Rails 3 Test cases . While writing case i got Deprecation error like
DEPRECATION WARNING: Errors#on have been deprecated, use Errors#[] instead.
Also note that the behaviour of Errors#[] has changed. Errors#[] now always returns an Array. An empty Array is returned when there are no errors on the specified attribute. (called from on at /usr/local/lib/ruby/gems/1.9.1/gems/activemodel-3.0.0.rc/lib/active_model/deprecated_error_methods.rb:7)
For that i used errors[:field] instead of errors.on(:field)
Now Deprecation error is gone , but cases are not working as earlier it was working . It is not testing any validation for the model
Sol
Replace:
errors.on(:field)
with:
errors.include?(:field)
After searching for examples of how to do this without finding anything I ended up doing:
errors[:field].present? / errors[:field].blank?
Don't know if this is the preferred way but it seems to do the job.
I am using something like this at the moment:
#hamburger.errors[:ingredients].count.should == 1
#hamburger.errors[:ingredients].should include "Tomatoes are missing dude!"
Hope it helps someone, right now it is the cleanest solution for me.
I'm converting my old specs to something like this to remove the deprecation warnings:
model.should have(1).error_on(:field)
model.should have(:no).errors_on(:field)

Resources