How to pass multiple arguments in Ruby? - ruby

I am new to Ruby and couldn't get any help from answers here, because code level seems pretty advance here:
How do I pass multiple arguments to a ruby method as an array?
Ruby method with maximum number of parameters
http://www.tutorialspoint.com/ruby/ruby_methods.htm
I have created a step_definitions like this:
Then(/^I should see "([^"]*)" as the name for line item (.*)$/) do |puppy_name, line_item|
#cart.name_for_line_item line_item
end
where method name_for_line_itemtakes only one argument i.e. line_item
but in above step_definition I have to verify the puppy_name I am passing.
So I tried:
#cart.name_for_line_item.should include puppy_name line_item but this is red line of error under the method and
if I try
#cart.name_for_line_item line_item .should include puppy_name it give compile time error:
RSpec::Expectations::ExpectationNotMetError
Source: Cucumber and Cheese by Jeff Morgan

You should use parenthesis :
(#cart.name_for_line_item(line_item).should).include? puppy_name
Latest version of rspec allow another syntax :
expect(#cart.name_for_line_item(line_item)).to include(puppy_name)
Link to rspec documentation : https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers

Related

IntelliJ Ruby warning "Cannot resolve properly, was not processed"

I have many lines in my specs that result in this IntelliJ warning:
"Cannot resolve properly, was not processed"
The vast majority of the lines have this format:
expect(result[:err]).to include('(Check the file permissions.)')
If I move the literal string to a separate variable, the warning goes away:
msg = '(Check the file permissions.)'
expect(result[:err]).to include(msg)
Is there a way to make this error go away (other than moving all my string literals to variables)?
My guess is that the RubyMine parser thinks that include is the Ruby keyword to include a module and so it emits a warning telling it cannot find the corresponding module.
The only way I found to fix this warning is to use the inclusion alias proposed by the rspec include matcher :
expect(result[:err]).to inclusion('(Check the file permissions.)')
This fixes the warning and the expectation works the same, but sadly the english sentence is bad.
There is also 3 other aliases available, but they don't give better english syntax:
alias_matcher :a_collection_including, :include
alias_matcher :a_string_including, :include
alias_matcher :a_hash_including, :include
alias_matcher :including, :include
These alias definitions can be found here
Maybe by chance this answer could lead someone to a better solution.
If you're willing to switch from using the word include to something like contain, you could simply create a custom matcher:
RSpec::Matchers.define :contain do |expected|
match do |actual|
expect(actual).to include(expected)
end
end
You could either add that code directly in your rails_helper.rb file, or better yet in a separate file. For instance, create spec/support/custom_matchers.rb and place the code there. You'll need to make sure that file gets included when running rspec. To do that, you could uncomment the following line which appears in the default spec/rails_helper.rb file:
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
With that in place, your spec file would read:
expect(result[:err]).to contain('(Check the file permissions.)')
It can be fixed by adding this to rails_helper.rb or support/rubymine_stubs.rb:
# Rubymine IDE underlines `include` matchers with warning "Cannot resolve properly, was not processed"
# To fix this issue let's make an alias `contain` and use it instead
RSpec::Matchers.alias_matcher :contain, :include
module RubymineStubs
# create stub for `contain` so Rubymine won't underline it
def contain(*_args) end
end

Check if a method is an alias to another method in rspec

Article#to_archive is an alias for Article#archived!:
class Article
alias to_archive archived!
end
I need to ensure this, so I wrote this test:
describe '#to_archive' do
it 'is an alias to #archived!' do
expect(subject.method(:to_archive)).to eq(subject.method(:archived!))
end
end
However, I receive an error
Failure/Error: expect(subject.method(:to_archive)).to eq(subject.method(:archived!))
expected: #<Method: Article(#<Module:0x00000005a7c240>)#archived!>
got: #<Method: Article(#<Module:0x00000005a7c240>)#to_archive(archived!)>
It used to work in ruby < 2.3 IIRC. I tried alias_method, but it didn't help.
The definition of Method#== is not clear and/or useful, so you shouldn't rely on it.
To check that it is an alias, you can do this:
expect(subject.method(:to_archive).original_name).to eq(:archived!)

Access `expected` line from metadata

I want output line, which was failed during rspec comparasion inside example, but I don't know how to do it best.
For example I have test like this:
require 'rspec'
describe 'My behaviour' do
it 'should do something' do
test_string = 'test'
expect(test_string).to eq('failed_test')
end
after :each do |example|
puts example.metadata[:expect_line]
end
end
And I want to outputed line in after :each be
"expect(test_string).to eq('failed_test')"
I know, I have acces to example.metadata[:location] which return something like "./spec/test_spec.rb:4" and I can parse it and extract line, but is there already something like I need hided in whole example structure?
Update:
I just understand. that example.metadata[:location] return not failed line, but actually line in whitch it started, so it have no use for me :(
So question still exist - how to get failed line?
This information isn't hidden anywhere in the example structure that I'm aware of. RSpec's default output shows the line that failed:
Failures:
1) My Description should fail
Failure/Error: expect(1).to eq(2)
expected: 2
got: 1
If we look at how rspec itself gets this in rspec/core/formatters/exception_presenter.rb and rspec/core/formatters/snippet_extractor.rb, it appears that they go through the backtrace of the example exception to find the spec file and extract the line (similar to what you mentioned). If there was an easier way to pull that out of the example, I would think RSpec itself would use that :)

Trouble with "to" method in RSpec (undefined method)

Completely new to rspec here, as will become evident.
The following rspec file fails:
require_relative( 'spec_helper')
describe GenotypingScenario do
it 'should add genes' do
scen = GenotypingScenario.new
gene = Gene.new( "Pcsk9", 989 )
scen.addGene( gene )
expect( gene.id).to eq( 989 )
ct = scen.genes.count
expect (ct).to equal(1)
expect (5).to eq(5)
end
end
Specifically, the last two expect() lines fail, with errors like this:
NoMethodError: undefined method `to' for 1:Fixnum
Yet the first expect line works fine. And gene.id is definitely a FixNum.
Ruby 2.1.2, rspec 3.0.0, RubyMine on Mac OS 10.9.4.
Any thoughts?
The spacing in your last two expect lines are tripping up the Ruby interpreter.
expect (5).to equal(1)
Is evaluated by Ruby as:
expect(5.to(equal(1)))
When what you really mean is:
expect(5).to(equal(1))
It's the return value from calling expect() that has a method to; RSpec isn't extending the Ruby built-in types. So you should change your last two expectations to read as follows:
expect(ct).to equal(1)
expect(5).to eq(5)
I was following a Rails API tutorial with TDD, when I found a line in the tests that expected a json response not to be empty.
This is how I wrote it:
expect(json).not_to_be_empty
And I got that unfriendly NoMethodError: undefined method 'not_to_be_empty'
I came to the accepted answer on this thread and it opened my eyes.
I then changed the line to:
expect(json).not_to be_empty
I know you could still be looking for the difference, well, welcome to RSpec! I removed the underscore in between not_to and be empty to make two words. It worked like ... good code.

What exception is raised when using + on symbols in Ruby?

Doing the Ruby Koans, in the file about_symbols at line 88, I'm not sure of the answer.
This is the code:
def test_symbols_cannot_be_concatenated
# Exceptions will be pondered further farther down the path
assert_raise(what should i put?) do
:cats + :dogs
end
The point of the Ruby Koans is to learn by reading and trying things out.
Open up a terminal and start irb. Then try using the + operator on two symbols. Check the error you get and substitute it as appropriate in the Koans file.
Assuming that your prompt ends in $, that will look something like this:
$ irb
irb(main):001:0> :cats + :dogs
The answer you need will be clear pretty quickly in the error that irb spits out.
To go through step by step in case your completely new to Ruby you could try:
Open up a terminal
Type irb at your prompt to get to the interactive ruby prompt
This is where you can quickly try out different Ruby things
Type the command in question :cats + :dogs
Review the output which will look like
NoMethodError: undefined method `+' for :cats:Symbol
from (irb):1
The name of the exception thrown which is what you are looking for is the first thing e.g. NoMethodError

Resources