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

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.

Related

Ruby chomp!.strip! in one line

I'm trying to scrape a table from a website.
status = recPage.css("#MainContent_GridView1").css("tr")[line].css("td")[2].text.chomp.strip
And I got this error for some of the rows.
undefined method `strip' for nil:NilClass (NoMethodError)
or
undefined method `chomp' for nil:NilClass (NoMethodError)
So I thought I could use chomp!.strip! to skip the nil values. But apparently it won't allow me to put those 2 into one line.
Is there a way to modify this?
How about:
status = recPage.css("#MainContent_GridView1").css("tr")[line].css("td")[2].text.chomp.strip rescue ""
It will set status to "";
You're getting these errors because there're nodes with .text=nil, also chomp! and strip! are meant to modify string in-place, not to ignore errors, and they return nil.
Best way is to check the presence of text (not oneliner, thought):
txt = recPage.css("#MainContent_GridView1").css("tr")[line].css("td")[2].text
txt = txt.chomp.strip if txt
In ruby 2.3+ you can use:
recPage.css("#MainContent_GridView1").css("tr")[line].css("td")[2].text&.chomp.&strip
rescue ""-method could lead to errors in the future (if there are some other errors in this line)
If you really want to do it destructively, you can do:
...text&.tap(&:chomp!)&.tap(&:strip!)

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!)

How to pass multiple arguments in 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

Ruby methods at bottom of script?

I'm using ruby 1.8.7. I could have sworn that I've written my functions at the bottom of my script before and it worked fine.
Do I have to put them at the top? It seems to be the only way they work now. Not a big deal. I just prefer to have them at the bottom so I figured I'd ask.
You can do initializing code in one or more BEGIN-blocks (inherited from Perl, which inherited them from awk).
can_i_do_this? #=>yes
BEGIN {
def can_i_do_this?
puts "yes"
end
}
And for completeness, there are also END-blocks:
END {
can_i_do_this? #=> yes
}
def can_i_do_this?
puts "yes"
end
a
def a
puts "Hello world!"
end
Running this script in Ruby will give you:
script.rb:1:in `<main>': undefined local variable or method `a' for main:Object (NameError)
So no, you can't have them at the bottom. As Ruby is an interpreted language, any code is parsed and processed at runtime ONLY. Therefore, you can only run code (call methods, use variables...) that have already been defined prior to the actual reference.

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