Wednesday, 20 July 2011

A little diversion.

Over my lunch hours this week I decided to do a little bit of hacking. I decided to write a sentence matcher it is part of my toying with writing an Eliza clone. For now it is a fairly abstract piece of code that does not match anything yet.

The idea is to a have a sentence and then test to see if it matches a rule. My rule might be [0, "and",0] which means any number of words followed by an and followed by any number of words. The task is not that exciting in itself and is partially about increasing my coding experience with CoffeeScript. 

What was interesting was when I wrote a sub rule matcher and them wrote out about 10 little test sequences to test out the code. I just dumped them at the bottom of the file and was console.log-ing them to my terminal to visually check everything was working as expected. I am sure that is how many people code when working with prototype stuff. Then I though gosh I am having trouble remembering if the stuff outputted to the terminal is correct, I need a test harness. 

Well I could have hit the internet and downloaded one. Instead I decided to write my own, very minimal one. What surprised me was in the space of 37 minutes I had a minimal test harness set up and running tests and, err, yes I did time it. After a total of 1hr I had my tests refactored to use it, support for test suites, counting of passed and failed tests. 

Go CoffeeScript for productivity.

Of course it is all sitting at the bottom of one file along with my actual tests... Anyway I can now resume working on my matcher code :)

Just in case you want to see it and yes the code is very much hacked out with no regard to style in fact I have barely look over it other than to code it up. Also please don't use it there are plenty of test harnesses out there we don't need to increment that count. That all said here it is along with a little test suite so you can see the layout of the tests. Oh and it is not very well tested :)

test = (name, testfn) ->
  ok = true
  try
    testfn()
  catch err
    console.log "Fail - "+name
    console.log err
    ok = false
  ok

equal = (message, val, expected) ->
  ok = true
  if isArray val
    if val.length != expected.length then ok  = false
    else
      idx = 0
      while idx < val.length and ok
        if val[idx] != expected[idx++] then ok =false
  else
    ok = val == expected
  throw message + " (got #{val} expected #{expected})" if not ok
isfalse= (message, val) ->
  throw message + " (got #{val} expected false)" if !!val

runTestSuite = (suite, reportResults = true) ->
  console.log "Running " + suite.name + " tests."
  testsRun = 0
  pass = 0
  fail = 0

  for k,v of suite
    if k[0..3] == "test"
      ok = test k, v
      if ok then ++ pass
      else ++fail
  if reportResults
    console.log "passed:#{pass} failed:#{fail}"
    if fail > 0 then console.log "FAIL"
    else console.log "PASS"
  [pass, fail]

runAll = (suites) ->
  pass = 0
  fail = 0
  for suite in suites
    [p,f] = runTestSuite(suite, false)
    pass +=p
    fail += f
  if fail == 0 then console.log "PASS #{pass} tests"
  else console.log "FAIL #{fail} test failed of #{pass+fail} tests"


tokeniserTests = {
  name:"tokeniser"
  testSimpleCase: () ->
    result = tokeniser "one two three"
    equal( "", result, [ 'one', 'two', 'three'])
  
  testConvertedToLowercase: () ->
    result = tokeniser "onE Two thrEe"
    equal( "", result, [ 'one', 'two', 'three'])

  testOnlyLooksAtFirstSentence: () ->
    result = tokeniser "onE Two thrEe. and more"
    equal( "", result, [ 'one', 'two', 'three'])
}

No comments:

Post a Comment