ブログ

読んで思い出す。忘れるために書く

「単語の類似性を算出する」出題を解く

teratail.com

気になったので書いてみる(Ruby, RSpec)

もとの質問で話題としている言語は Java であり、穴埋め問題であり、ぜんぜん関係ないのでこちらに書き残す

今回の RSpec によるテストでは One-liner syntax を利用して、 expect を書く

テストコード

質問本文によると:

 1つ目の文字列: yama

 2つ目の文字列: hamada

より,

 同じ位置の文字数(x)は3,

 長い文字列の文字数(y)は6,

よって,類似性は,(3÷6)×100 より 50%

となる。

らしいので、それっぽくなるようにテストコードを書く

describe 'WordSimilarity' do
  context 'calculate similarity between "yama" and "hamada"' do
    subject { WordSimilarity.new(*%w(yama hamada)).similarity }

    it { is_expected.to eq 50.0 }
  end
end

実装

最低限のコード

テストコードの判定が正しく動き、テスト対象のコードも実際にテストされていることを確かめる

(コマンドとして利用する際の引数の数についての言及もあるが、ここでは書かない)

class WordSimilarity
  def initialize(a, b)
  end

  def similarity
    50.0
  end
end

引数に対応したコード

class WordSimilarity
  def initialize(a, b)
    # 'yama'.chars.zip('hamada'.chars)
    # => [["y", "h"], ["a", "a"], ["m", "m"], ["a", "a"]]
    @similarity_count =
      a.chars
       .zip(b.chars)
       .count { |x, y| x.eql?(y) }
       .to_f
    @word_length = [a, b].max_by(&:length).length
  end

  def similarity
    (@similarity_count / @word_length) * 100
  end
end

まとめ

1つだけのテストコードをパスするコードが書けた

この他にもテストコードには、例外的な場合とか、「この時はエラーとするけど、この時はそうしない」といった境界をハッキリさせるためのテスト、あるいは「ここほんとに動いてるんだろか」と不安になるような部分をテストするコードを追加していきたい

Link