Forum: RSpec rspect weird problem

Posted by Andres M. (andres_m)
on 2011-12-06 07:14
Hello everyone, this is really urgent so ill be quick, here is some ruby
code that i know works:

    require 'csv'

    class Motorcycle
      attr_reader :name, :weight
      @@count = 0

      def self.find (name)
        found = nil
        ObjectSpace.each_object(Motorcycle) { |o|
          found = o if o.name == name
        }
        return found
      end

      def self.create
      File.new('motorcycles.csv').readlines[1..-1].map{ |line|
        Motorcycle.new( *line.split( ',' )  )
        }
      end

      def initialize (name, weight)
      @name = name
      @weight = weight
      self.class.count += 1
      end

      def self.count
      return @@count
      end

      def self.count=( count )
      @@count = count
      end

      def available_colors

      colors=[]
      colorsFile = File.read('colors.csv').split("\n").map { |line|
line.split(',') }
      for i in (0..colorsFile.flatten.length) do
        if (colorsFile.flatten[i].to_s == self.name.to_s)
          colors.push(colorsFile.flatten[i+1])
        end
      end

      return colors
      end

      def contains (name,color)
      if(self.name.to_s == name)
      else
        return color
      end
      end

      def has_abs?
      File.open( 'abs.txt' ) do |io|
      io.each {|line| line.chomp! ; return true if line.include?
self.name.to_s}
      end

      return false
      end

    end

    Motrocicle.create

the code must pass this tests on rspec:

    describe Motorcycle do
      describe "loading the motorcycle list" do
        it "should load 2 motorcycles from the CSV" do
          Motorcycle.count.should == 2
        end
      end

      describe "finding a motorcycle by name" do
        it "should return an instance of the Motorcycle class" do
          Motorcycle.find("1200 RT").should be_a Motorcycle
        end
      end

      describe "#weight" do
        it "should have a weight of 800 pounds for the 1200 RT" do
          Motorcycle.find("1200 RT").weight.should == '800 pounds'
        end

        it "should have a weight of 500 pounds for the 600 GS" do
          Motorcycle.find("600 GS").weight.should == '500 pounds'
        end
      end

      describe "#available colors" do
        it "should find 'red' and 'black' as available colors for the
BMW 1200 RT" do
          Motorcycle.find("1200 RT").available_colors.should == [ 'red',
'black' ]
        end

        it "should find 'green' and 'blue' as available colors for the
BMW 600 GS" do
          Motorcycle.find("600 GS").available_colors.should == [
'green', 'blue' ]
            end
      end

      describe "#has_abs?" do
        it "should be true for a motorcycle that appears in
abs_motorcycles.txt" do
          Motorcycle.find("1200 RT").has_abs?.should be_true
        end

        it "should be false for a motorcycle that does not appear in
abs_motorcycles.txt" do
          Motorcycle.find("600 GS").has_abs?.should be_false
        end
      end
    end

problem is, after the first test (where it counts the amount of
motrocicle instances) every instance is a nil, thats t say, every test
is failed except for the fist one. here is the output log:

    Failures:

      1) Motorcycle finding a motorcycle by name should return an
instance of the Motorcycle class
         Failure/Error: Unable to find matching line from backtrace
           expected nil to be a kind of Motorcycle
         # ./motoapp.rb:76

      2) Motorcycle#weight should have a weight of 800 pounds for the
1200 RT
         Failure/Error: Unable to find matching line from backtrace
         NoMethodError:
           undefined method `weight' for nil:NilClass
         # ./motoapp.rb:82

      3) Motorcycle#weight should have a weight of 500 pounds for the
600 GS
         Failure/Error: Unable to find matching line from backtrace
         NoMethodError:
           undefined method `weight' for nil:NilClass
         # ./motoapp.rb:86

      4) Motorcycle#available colors should find 'red' and 'black' as
available colors for the BMW 1200 RT
         Failure/Error: Unable to find matching line from backtrace
         NoMethodError:
           undefined method `available_colors' for nil:NilClass
         # ./motoapp.rb:92

      5) Motorcycle#available colors should find 'green' and 'blue' as
available colors for the BMW 600 GS
         Failure/Error: Unable to find matching line from backtrace
         NoMethodError:
           undefined method `available_colors' for nil:NilClass
         # ./motoapp.rb:96

      6) Motorcycle#has_abs? should be true for a motorcycle that
appears in abs_motorcycles.txt
         Failure/Error: Unable to find matching line from backtrace
         NoMethodError:
           undefined method `has_abs?' for nil:NilClass
         # ./motoapp.rb:102

      7) Motorcycle#has_abs? should be false for a motorcycle that does
not appear in abs_motorcycles.txt
         Failure/Error: Unable to find matching line from backtrace
         NoMethodError:
           undefined method `has_abs?' for nil:NilClass
         # ./motoapp.rb:106

    Finished in 0.01223 seconds
    8     examples, 7 failures

i have been inclined to think this is some kind of bug or something due
to my result doing the manual test like this:

    puts Motorcycle.count
    puts Motorcycle.find("1200 RT")
    puts Motorcycle.find("1200 RT").weight
    puts Motorcycle.find("600 GS").weight
    puts Motorcycle.find("1200 RT").available_colors
    puts Motorcycle.find("600 GS").available_colors
    puts Motorcycle.find("1200 RT").has_abs?
    puts Motorcycle.find("600 GS").has_abs?

which give me this output:

2
#<Motorcycle:0x7fd8bffcfd88>
800 pounds
500 pounds
red
black
green
blue
true
false


so i'm really pretty much on a dead end, ¿does anyone have a clue as to
what could be happening?.
Posted by Patrick Collins (patrick99e99)
on 2011-12-06 08:11
(Received via mailing list)
>     Motrocicle.create

I don't know if this helps, but I am pretty sure "Motrocicle.create" 
isn't what
you intended to call.

Also, I'd like to point out that:

>       def self.find (name)
>         found = nil
>         ObjectSpace.each_object(Motorcycle) { |o|
>           found = o if o.name == name
>         }
>         return found
>       end
>

Is very inefficient because it's going to keep iterating through all the
objects even after it's found the one it's looking for.

  def self.find(name)
    ObjectSpace.each_object(Motorcycle) do |o|
      return o if o.name == name
    end
  end

Will return found object immediately or nil if nothing is found.

Patrick J. Collins
http://collinatorstudios.com
Posted by Andres M. (andres_m)
on 2011-12-06 08:27
Patrick Collins wrote in post #1035294:
>>     Motrocicle.create
>
> I don't know if this helps, but I am pretty sure "Motrocicle.create"
> isn't what
> you intended to call.
>
> Also, I'd like to point out that:
>
>>       def self.find (name)
>>         found = nil
>>         ObjectSpace.each_object(Motorcycle) { |o|
>>           found = o if o.name == name
>>         }
>>         return found
>>       end
>>
>
> Is very inefficient because it's going to keep iterating through all the
> objects even after it's found the one it's looking for.
>
>   def self.find(name)
>     ObjectSpace.each_object(Motorcycle) do |o|
>       return o if o.name == name
>     end
>   end
>
> Will return found object immediately or nil if nothing is found.
>
> Patrick J. Collins
> http://collinatorstudios.com

ok that was just and error when i copy the code to this post this is the
rspec output with the problem corrected and the "manual script" also
included, and you optimal find method, (by the way thanks for the 
advice, your find method is better,
i dont know how could i just miss it, thanks :D).

q_ro@thor:~/Escritorio/motorcycle_test_app$ rspec motoapp.rb
2
#<Motorcycle:0x7f6e5d4ade68>
800 pounds
500 pounds
red
black
green
blue
true
false
.FFFFFFF

Failures:

  1) Motorcycle finding a motorcycle by name should return an instance
of the Motorcycle class
     Failure/Error: Unable to find matching line from backtrace
       expected 0 to be a kind of Motorcycle
     # ./motoapp.rb:75

  2) Motorcycle#weight should have a weight of 800 pounds for the 1200
RT
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `weight' for 0:Fixnum
     # ./motoapp.rb:81

  3) Motorcycle#weight should have a weight of 500 pounds for the 600 GS
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `weight' for 0:Fixnum
     # ./motoapp.rb:85

  4) Motorcycle#available colors should find 'red' and 'black' as
available colors for the BMW 1200 RT
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `available_colors' for 0:Fixnum
     # ./motoapp.rb:91

  5) Motorcycle#available colors should find 'green' and 'blue' as
available colors for the BMW 600 GS
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `available_colors' for 0:Fixnum
     # ./motoapp.rb:95

  6) Motorcycle#has_abs? should be true for a motorcycle that appears in
abs_motorcycles.txt
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `has_abs?' for 0:Fixnum
     # ./motoapp.rb:101

  7) Motorcycle#has_abs? should be false for a motorcycle that does not
appear in abs_motorcycles.txt
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `has_abs?' for 0:Fixnum
     # ./motoapp.rb:105

Finished in 0.0119 seconds
8 examples, 7 failures


i really don't get it.
Posted by Patrick Collins (patrick99e99)
on 2011-12-06 10:45
(Received via mailing list)
>   1) Motorcycle finding a motorcycle by name should return an instance
> of the Motorcycle class
>      Failure/Error: Unable to find matching line from backtrace
>        expected 0 to be a kind of Motorcycle
>      # ./motoapp.rb:75

I also am noticing that you don't have any sort of setup for your test.. 
In
order for your find method to be able to retrieve anything, I believe 
you are
going to need to call .create prior to it.

describe Motorcycle do
  before :each do
    Motorcycle.create
  end

  describe "finding a motorcycle by name" do
   ...etc
  end
end

Patrick J. Collins
http://collinatorstudios.com
Posted by Andres M. (andres_m)
on 2011-12-06 15:59
no, that didn't work, but i found that i may be due to garbage collector 
taking place before test starts, so the solution was to add a set called 
instances and then in the initialize method put the following code line 
"instances << self", this way my instances had a root, preventing the 
garbage collector from trashing my class instances.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.