Rubyのtest/unitの使い方と、ジャンケンのコードをテストしてみた。

#まず初めに
課題で「ジャンケンのプログラムをtest/unitを使ってテストしろ。」と出され、テストコード自体初めて聞いたので、自分用のメモとして記載します。
動作環境は以下の通り。

mac
Ruby 2.6.5
test/unit 3.3.6

#達成したいこと
ジャンケンのプログラムを、「test/unit」を使用して、テストする。

#test/unitとは
そもそも、テストコードとは、書いたプログラムのロジックが、想定通りの動きをしているか、確認するためのプログラムです。

test/unitはRuby用のテストフレームワークで、元々は標準搭載されていたらしいです。
tesu/unit自体のインストールは[こちら](https://test-unit.github.io/ja/index.html)を参照してください。

#test/unitの基本的な使い方
前提として、ver.によって多少異なるので、ご了承ください。
基本的な構文は以下の通り。

~~~ruby
require 'test/unit'

class [クラス名] < Test::Unit::TestCase

end
~~~
まずはこのフレームワークを使用するために`'test/unit'`を`require`します。
つぎに、`Test::Unit::TestCase`を継承したclassを作成します。
Rubyでは`Test::Unit::TestCase`を継承することでそのクラスはテスト実行ファイルになります。

~~~ruby
require 'test/unit'

class [クラス名] < Test::Unit::TestCase

  def test_[メソッド名]
    foo = "hoge"
    assert_equal("hoge", foo)
  end

end
~~~

テストの処理は上記の通りです。
メソッドを作成し、そちらにテストしたいプログラムを書きます。メソッド名は`test_`から始めるのがルールです。このメソッド内では、以下の書式でチェックメソッドを書きます。（チェックメソッドは、他にもあります）

~~~ruby
assert_equal(想定の値, 変数やメソッド等)
~~~

`assert_equal`では、変数の値やメソッドの返り値が想定のものと一致することを確認します。

こちらで簡単なチュートリアルは終わりですが、もっとデフォルトで使用できるメソッドなどあるので、リファレンスを参照してみてください。

#解決方法
それでは、達成条件の解決方法を以下に記載します。
まずですが、ジャンケンのプログラムを先に書いてしまいます。
（あまり、スマートなプログラムではないですが、ご容赦ください）
標準入力でgかcかpを入力したら、ジャンケンの結果が出力される仕組みです。

~~~ruby
player = gets.chomp

if player == "g"
  player = "グー"
elsif player == "c"
  player = "チョキ"
elsif player == "p"
  player = "パー"
end

com = rand(3)
if com == 0
  com = "グー"
elsif com  == 1
  com =  "チョキ"
else
  com = "パー"
end

if player == com
  res = "引き分け"
elsif (player == "グー" && com == "チョキ") || (player == "チョキ" && com == "パー") || (player == "パー" && com == "グー")
  res = "あなたの勝ち"
else
  res = "あなたの負け"
end

puts "あなたは#{player}、私は#{com}、#{res}です。"

~~~

今回の場合は、`player`と`com`の２つの変数の値が決まったときに正しい結果が表示されるかをテストするので、テストするのは以下の部分です。

~~~ruby
if player == com
  res = "引き分け"
elsif (player == "グー" && com == "チョキ") || (player == "チョキ" && com == "パー") || (player == "パー" && com == "グー")
  res = "あなたの勝ち"
else
  res = "あなたの負け"
end

puts "あなたは#{player}、私は#{com}、#{res}です。"
~~~

今回は、上記の勝敗を判定する処理をクラスにまとめます。

~~~ruby
class Janken
  def self.judge(player,com)
    if player == com
      res = "引き分け"
    elsif (player == "グー" && com == "チョキ") || (player == "チョキ" && com == "パー") || (player == "パー" && com == "グー")
      res = "あなたの勝ち"
    else
      res = "あなたの負け"
    end
    return "あなたは#{player}、私は#{com}、#{res}です。"
  end
end
~~~

ジャンケンの勝敗の処理をクラスにまとめました。
そうしたら、テスト処理の方を書きます。

~~~ruby
require 'test/unit'

class Test_Janken < Test::Unit::TestCase
  def test_janken
    assert_equal('あなたはグー、私はグー、引き分けです。', Janken.judge("グー","グー"))
    assert_equal('あなたはチョキ、私はチョキ、引き分けです。', Janken.judge("チョキ","チョキ"))
    assert_equal('あなたはパー、私はパー、引き分けです。', Janken.judge("パー","パー"))
    assert_equal('あなたはグー、私はチョキ、あなたの勝ちです。', Janken.judge("グー","チョキ"))
    assert_equal('あなたはチョキ、私はパー、あなたの勝ちです。', Janken.judge("チョキ","パー"))
    assert_equal('あなたはパー、私はグー、あなたの勝ちです。', Janken.judge("パー","グー"))
    assert_equal('あなたはグー、私はパー、あなたの負けです。', Janken.judge("グー","パー"))
    assert_equal('あなたはチョキ、私はグー、あなたの負けです。', Janken.judge("チョキ","グー"))
    assert_equal('あなたはパー、私はチョキ、あなたの負けです。', Janken.judge("パー","チョキ"))
  end
end
~~~

ジャンケンの勝敗のパターンの全９通りを`assert_equal`で検証するという感じです。
これをジャンケンの処理を合体させます。
以下のコードが最終的なものになります。

~~~ruby
require 'test/unit'

class Janken
  def self.judge(player,com)
    if player == com
      res = "引き分け"
    elsif (player == "グー" && com == "チョキ") || (player == "チョキ" && com == "パー") || (player == "パー" && com == "グー")
      res = "あなたの勝ち"
    else
      res = "あなたの負け"
    end

    return "あなたは#{player}、私は#{com}、#{res}です。"
    
  end
end

class Test_Janken < Test::Unit::TestCase
  def test_janken
    assert_equal('あなたはグー、私はグー、引き分けです。' ,Janken.judge("グー","グー"))
    assert_equal('あなたはチョキ、私はチョキ、引き分けです。' ,Janken.judge("チョキ","チョキ"))
    assert_equal('あなたはパー、私はパー、引き分けです。' ,Janken.judge("パー","パー"))
    assert_equal('あなたはグー、私はチョキ、あなたの勝ちです。' ,Janken.judge("グー","チョキ"))
    assert_equal('あなたはチョキ、私はパー、あなたの勝ちです。' ,Janken.judge("チョキ","パー"))
    assert_equal('あなたはパー、私はグー、あなたの勝ちです。' ,Janken.judge("パー","グー"))
    assert_equal('あなたはグー、私はパー、あなたの負けです。' ,Janken.judge("グー","パー"))
    assert_equal('あなたはチョキ、私はグー、あなたの負けです。' ,Janken.judge("チョキ","グー"))
    assert_equal('あなたはパー、私はチョキ、あなたの負けです。' ,Janken.judge("パー","チョキ"))
  end
end

~~~

結果は、、

~~~
Loaded suite test
Started
.
Finished in 0.000811 seconds.
--------------------------------------------------------------------------------
1 tests, 9 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
--------------------------------------------------------------------------------
1233.05 tests/s, 11097.41 assertions/s
~~~

問題なく、テストできました。

#リファレンス

[test/unitライブラリ - doc.ruby-lang.org](https://docs.ruby-lang.org/ja/2.0.0/library/test=2funit.html)

[rubyのデフォルトのUnit testの使い方 - 脳汁portal](http://portaltan.hatenablog.com/entry/2015/10/28/111757)

[Test::Unitでテストを書く -Qiita](https://qiita.com/repeatedly/items/727b08599d87af7fa671)