This month’s blogging has been a little slow because it is taking a while for me to get my head around TDD. I have no complaints though because this has been another steep learning curve requiring a significant amount of external research.
Continuing on from the last post, I have been working through writing the code for a given test with two assertions. In this post I’m working through the second assertion - which took a while.
To recap the test was:
test_lexicon.rb
require 'ex48/lexicon.rb'
require "test/unit"
class TestLexicon < Test::Unit::TestCase
def test_directions()
assert_equal(Lexicon.scan("north"), [['direction', 'north']])
result = Lexicon.scan("north south east")
assert_equal(result, [['direction', 'north'],
['direction', 'south'],
['direction', 'east']])
end
end
The corresponding code that I wrote was:
lexicon.rb
class Lexicon
@@hash = {
'direction' => ['south', 'north', 'east']
}
def self.scan(sentence)
words = sentence.split(' ')
result = [] # this array should contain arrays of [key word]
words.each do |word|
element = [] # push this array of [key,word] to the result array
@@hash.each do |key, value|
if value.include?(word)
element = [key, word]
result.push(element)
end
end
end
return result
end
end
The error I kept receiving was:
Started
F
===========================================================================================================================
/Users/wickinot/Code/learnrubythehardway/ex48/tests/test_lexicon.rb:11:in `test_directions'
8: assert_equal(Lexicon.scan("north"), [['direction', 'north']])
9: result = Lexicon.scan("north south east")
10:
=> 11: assert_equal(result, [['direction', 'north'],
12: ['direction', 'south'],['direction', 'east']])
13: end
14: end
<[["direction", "north"]]> expected but was
<[["direction", "north"], ["direction", "south"], ["direction", "east"]]>
diff:
? [["direction", "north"], ["direction", "south"], ["direction", "east"]]
Failure: test_directions(TestLexicon)
===========================================================================================================================
Finished in 0.008249 seconds.
---------------------------------------------------------------------------------------------------------------------------
1 tests, 1 assertions, 1 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
0% passed
---------------------------------------------------------------------------------------------------------------------------
121.23 tests/s, 121.23 assertions/s
rake aborted!
The reason for the error was that the code was not pushing the element array to the result array. This is because I missed that I never specified the element array.
To figure out the solution I did do a lot of research on the internet and also came across another excellent resource - a book called Eloquent Ruby by Russ Olsen. Though these resources did not give me the answer to the solution, they did make me research and understand hashes and arrays and iteration on a deeper level. For example, the hash code is a lot less repetitive.
For the last two weeks I have been working on test driven development (or TDD). It has been a challenging experience working my way through exercise 48 - building a Lexicon.
So far I’ve only written code for the first ‘asser_equal’ in the test provided in the book. Here are the learnings so far:
- Understand the overall problem first, tackle the code later.
- Break the problem down by writing comments in your own words - method known as writing “pseudo code”.
- Hashes aren’t as scary as they seem and I learnt a lot more than what’s in the book by researching into the problem. I took a good look at the ruby docs on hashes found here and here and also arrays.
- You can have blocks inside of blocks, this I didn’t know and just thought I’d try - and it worked!
- Make sure you write a return statement at the end of the block - otherwise the test keeps failing.
Tackling the first two points took me the longest. Once I had that figured out, the coding part became much easier. This is only step one of the problem so far - more to come!
The test was:
test_lexicon.rb
require 'ex48/lexicon.rb'
require "test/unit"
class TestLexicon < Test::Unit::TestCase
def test_directions()
assert_equal(Lexicon.scan("north"), [['direction', 'north']])
result = Lexicon.scan("north south east")
#assert_equal(result, [['direction', 'north'],
['direction', 'south'],
['direction', 'east']])
end
end
The corresponding code that I wrote was:
lexicon.rb
#split sentence/user input into words
#take each of the words and #if word matches the value in the direction hash,
#wrong : return it as an array of array with (word, [[direction, word]]) pairing.
#right: return an array of [value, word]
#right: push this array to the empty mega array of arrays.
#make sure to return result
class Lexicon
@@hash = {
'north' => 'direction',
'south' => 'direction',
'east' => 'direction'
}
def self.scan(sentence)
words = sentence.split
result = []
words.each do |word|
@@hash.each do |key, value|
if key.include?(word)
element = [value, word]
result.push(element)
end
return result
end
end
end
end