user2710150
user2710150

Reputation: 1

rspec test not passing

I'm working through the learn ruby tutorials and I'm trying pass the last example where it tests the printable method. I tested the method by calling the method directly within my ruby program and it spits out exactly whats needed. What is preventing my code from properly passing? Any help is greatly appreciated.

Here's the rspec file:

require 'dictionary'

describe Dictionary do
  before do
    @d = Dictionary.new
  end

  it 'is empty when created' do
    @d.entries.should == {}
  end

  it 'can add whole entries with keyword and definition' do
    @d.add('fish' => 'aquatic animal')
    @d.entries.should == {'fish' => 'aquatic animal'}
    @d.keywords.should == ['fish']
  end

  it 'add keywords (without definition)' do
    @d.add('fish')
    @d.entries.should == {'fish' => nil}
    @d.keywords.should == ['fish']
  end

  it 'can check whether a given keyword exists' do
    @d.include?('fish').should be_false
  end

  it "doesn't cheat when checking whether a given keyword exists" do
    @d.include?('fish').should be_false # if the method is empty, this test passes with nil returned
    @d.add('fish')
    @d.include?('fish').should be_true # confirms that it actually checks
    @d.include?('bird').should be_false # confirms not always returning true after add
  end

  it "doesn't include a prefix that wasn't added as a word in and of itself" do
    @d.add('fish')
    @d.include?('fi').should be_false
  end

  it "doesn't find a word in empty dictionary" do
    @d.find('fi').should be_empty # {}
  end

  it 'finds nothing if the prefix matches nothing' do
    @d.add('fiend')
    @d.add('great')
    @d.find('nothing').should be_empty
  end

  it "finds an entry" do
    @d.add('fish' => 'aquatic animal')
    @d.find('fish').should == {'fish' => 'aquatic animal'}
  end

  it 'finds multiple matches from a prefix and returns the entire entry (keyword + definition)' do
    @d.add('fish' => 'aquatic animal')
    @d.add('fiend' => 'wicked person')
    @d.add('great' => 'remarkable')
    @d.find('fi').should == {'fish' => 'aquatic animal', 'fiend' => 'wicked person'}
  end

  it 'lists keywords alphabetically' do
    @d.add('zebra' => 'African land animal with stripes')
    @d.add('fish' => 'aquatic animal')
    @d.add('apple' => 'fruit')
    @d.keywords.should == %w(apple fish zebra)
  end

  it 'can produce printable output like so: [keyword] "definition"' do
    @d.add('zebra' => 'African land animal with stripes')
    @d.add('fish' => 'aquatic animal')
    @d.add('apple' => 'fruit')
    @d.printable.should == %Q{[apple] "fruit"\n[fish] "aquatic animal"\n[zebra] "African land animal with stripes"}
  end
end

and here's what I've created so far for the printable function:

class Dictionary
def initialize(opts = {})
    @opts = opts
end

def entries
    @opts
end

def add(opts)
    opts.is_a?(String) ? @opts.merge!(opts => nil) : @opts.merge!(opts)
end

def keywords
    @opts.keys.sort
end

def include?(key)
    @opts.has_key?(key)
end

def find(key)
    @opts.select { |word,defin| word.scan(key).join == key }
end

def printable
    opts_sorted = @opts.sort_by { |word,defin| word}
    opts_sorted.each do |word,defin|
        print "[#{word}] \"#{defin}\"\n"
    end
end
end

and here's the error:

  1) Dictionary can produce printable output like so: [keyword] "definition"
     Failure/Error: @d.printable.should == %Q{[apple] "fruit"\n[fish] "aquatic animal
"\n[zebra] "African land animal with stripes"}
       expected: "[apple] \"fruit\"\n[fish] \"aquatic animal\"\n[zebra] \"African lan
d animal with stripes\""
            got: [["apple", "fruit"], ["fish", "aquatic animal"], ["zebra", "African
land animal with stripes"]] (using ==)
       Diff:
       @@ -1,4 +1,4 @@
       -[apple] "fruit"
       -[fish] "aquatic animal"
       -[zebra] "African land animal with stripes"
       +["apple", "fruit"]
       +["fish", "aquatic animal"]
       +["zebra", "African land animal with stripes"]
     # ./11_dictionary/dictionary_spec.rb:81:in `block (2 levels) in <top (required)>
'

Upvotes: 0

Views: 1069

Answers (2)

user7452246
user7452246

Reputation:

Lucky for you I did this whole thing just now! Below is the answer code with comments for the explanation! I hope this still helps even after 4 years!

class Dictionary                                                  # Create the class
  attr_accessor :entries                                          # Attribute Accessor; this is our setter and getter

  def initialize(entries = {})                                    # Create constructor; if there is no value passed the default value is {}
    @entries = {}                                                 # Declare instance variable with empty hash

    if entries.is_a? Hash                                         # is_a? is a method where it sees if its a class; Hash is the class we compare it to
      entries.each {|key, value| @entries[key] = value}           # if there is a value that's passed we copy the hash to our instance variable
    end                                                           # End conditional 
  end                                                             # End constructor

  def keywords                                                    # Main purpose of this method is to return what's inside our keys
    keywords = []                                                 # Create empty keyword variable
    @entries.each_key {|key| keywords.push(key.to_s)}             # each_key method only takes the keys in our hash and pushes them into the keywords array
    keywords.sort                                                 # We sort the keywords variable 
  end                                                             # End method 

  def add(entry)                                                  # add method adds in an entry either a hash or a string
    if entry.is_a? Hash                                           # If the argument belongs to the class Hash; or if its a hash
      entry.each {|key, value| @entries[key] = value}             # Then we copy the key and values to our instance variable
    elsif entry.is_a? String                                      # If the arguemnt belongs to the class String; or if its a String
      @entries[entry] = nil                                       # We create a key for that string and set the value to nil 
    end                                                           # End conditional 
  end                                                             # End method 

  def include?(entry)                                             # include? method this checks if the argument is in our entries and returns a boolean value
    @entries.has_key?(entry)                                      # has_key? checks the instance variable if it has the key 
  end                                                             # End method 

  def find(entry)                                                 # find method finds if certain letters are in our keys
    @entries.select {|key| /#{entry}/.match(key)}                 # select gets the keys that match a certain keyword in our entries
    # if @entries.has_key?(entry)                                 # First attepmt to solve the test case
    #   @entries.select {|key,value| key == entry}
    # else
    #   puts {}
    # end
  end                                                             # End method 

  def printable                                                   # printable method just prints out our entries like a dictionary
    printable = []                                                # Create an empty array 
    @entries.sort.each do |key,value|                             # Sort and iterate to each key-value pair 
      printable.push("[#{key}] \"#{value}\"")                     # push the key-value pair formatted accordingly to the test case
    end                                                           # End hash iteration

    printable.join("\n")                                          # join with newlines to get desired result
  end                                                             # End method 
end                                                               # End class

Upvotes: 1

Steve
Steve

Reputation: 15736

I think the problem is that your printable method is not returning what you want it to return.

The return value of printable is the value of the method's last statement (opts_sorted.each ...). You are using print to output the expected string but this does not change the return value of the method (which is what you are testing).

If you want to return the string you are printing instead try this:

def printable
  opts_sorted = @opts.sort_by { |word, defin| word}
  opts_sorted.map{ |word, defin| "[#{word}] \"#{defin}\"\n" }.join
end

map will transform the key-value pairs in the hash into an array of strings formatted the way you want them and then join will append them into a single string.

Upvotes: 0

Related Questions