Ruby で Test::Unit を使ってみる
プログラムを書いた後、本当にその動作するの?みたいなことを確かめるために、Ruby には Test::Unit というクラスがあります。
今回は、研究室の課題が出たので、それをテストの勉強と一緒にやってしまおうという話です。実はそんなことするつもりなかったんですが、発表が1週間遅れたのでちょっと余計なことをしてみようと。
テストにはテストする対象となるファイルと、どういうテストをするかのテストファイルが必要になります。
今回テスト対象のファイルは、ユニコードのデータが大量に書いてあるファイル(UnicodeData.txt)を、文字見つける・単語数える・たぶん似てる名前を見つけるという3つの分析っぽいことをしてみたものです。
class UnicodeData def analyze(unicode_number) #分析用メソッド unless unicode_number =~ /^[\dA-F]+/ #16進数かどうか puts "#{unicode_number} is not hex number." #16進数の数値を渡さなきゃダメ else open("UnicodeData.txt").each{|line| word = line.chomp.split(/;/) #セミコロンごとに区切る str = [word[0].hex].pack('U') if word[0] == unicode_number #値が等しければ puts "#{unicode_number} is #{str}" return str elsif word[0].hex > unicode_number.hex #値が越えたら puts "#{unicode_number} is not exist." #その値の文字は存在しない return str end } end end def wordcount(want) #文字 want が何度登場するか数えるメソッド count = 0 open("UnicodeData.txt").each{|line| word = line.chomp.split(/;/) #セミコロンごとに区切る word[1].split(/ /).each{|w| #二つ目に文字の名前があるので、それを空白で区切る count += 1 if w == want #文字 want と同じだったら+1していく } } print "#{want} : #{count}\n" #表示 return count end def resemble(word1, word2) list = Hash.new open("UnicodeData.txt").each{|line| word = line.chomp.split(/;/) #セミコロンごとに区切る next if word[10] == nil #中身がないときは無視 str = word[10].split(/ /) #単語ごとで分ける st0, st1 = str[0], str[1] #1つめと2つめの単語を確保 if list.key?([st0, st1]) #前に使われていれば listst0, st1 << str #同じキーで格納 else list.store([st0, st1], [str]) #新しくキーと値を格納 end } p listword1, word2 #表示 return listword1, word2 #テストのため値を返す必要があるみたい end end
ファイルをダウンロードしなきゃいけないのでそのままでは動きませんがご了承を。ファイル名は unicodedata.rb にしてあります。
これに対応して、テストファイル( test.rb )は以下のような感じ。
require 'test/unit' require 'unicodedata' #テストしたいファイルとtest/unitをrequireしておく class UnicodeDataTest < Test::Unit::TestCase def setup #一番初めに呼び出されるメソッド @obj = UnicodeData.new end def teardown #1つテストが終わったら呼び出されるメソッド puts "\ttest finished." end def test_analyze #メソッド名はtest_元ファイルでのメソッド名 とかがいいか str = ["0000", "ABCD", "A456", "4576", "JUE4"] str.each{|word| assert_equal([word.hex].pack('U'), @obj.analyze(word)) } end def test_wordcount str = ["FIVE", "KATAKANA"] str.each{|word| assert_not_equal(0, @obj.wordcount(word)) } end def test_resemble str = ["HALFWIDTH","HANGUL"] assert_not_nil(@obj.resemble(str[0], str[1])) assert_nil(@obj.resemble(str[1], str[0])) end end
assert_* というのは Test::Unit::TestCase にあるメソッドで、色々あるのでリファレンスでも見てください。わざと失敗するようなテストも作ってありますが・・・。
この程度のものではテストする意味もなさそうなんですが、やはりプログラムが大きくなればなるほどテストの重要性が増していくようなので、これからは小さなプログラムでもテストを作って慣れていこうかな。
実行結果は研究室で見せ・・・られたら見せます。