Rubyを用いたじゃんけんプログラムとそのテスト（test-unit）

# はじめに
Rubyでじゃんけんのプログラムを製作しました。
その際、勝ち負けの判定が正しいかをtest-unitを用いて確認しました。

# 目次
１．じゃんけんメソッドを書く
２．テストコードを書く
３．じゃんけんプログラムを書く
４．プログラムを実行
５．テストを実行

# １．じゃんけんメソッドを書く
初めにじゃんけんのメソッドをクラスにまとめます。
ここでは、標準入出力などは行わずただ戻り値を返すだけです。
このメソッドは部品としてテストコードとじゃんけんプログラムのコードに使用します。

```ruby:janken_judge.rb
class Janken
  def self.judge(my_hand, enemy_hand)
    hands = {"g" => "グー", "c" => "チョキ", "p" => "パー"}        
    if my_hand == enemy_hand
      "あなたは#{hands[my_hand]}、私は#{hands[enemy_hand]}、引き分けです。"        
    elsif (my_hand == "g" && enemy_hand == "c") || (my_hand == "c" && enemy_hand == "p") || (my_hand == "p" && enemy_hand == "g")
      "あなたは#{hands[my_hand]}、私は#{hands[enemy_hand]}、あなたの勝ちです。"        
    else
      "あなたは#{hands[my_hand]}、私は#{hands[enemy_hand]}、あなたの負けです。"        
    end
  end
end
```

# ２．テストコードを書く
test-unitを用いて全てのパターンで判定が正しいか確認するテストコードを書いていきます。

```ruby:test_janken.rb
# 'test/unit'とテストするメソッド部品をrequire 
require 'test/unit'
require_relative 'janken_judge.rb'

# Test::Unit::TestCaseを継承したclassを作成。名前がtest_で始まるメソッドを作成。
class TestJanken < Test::Unit::TestCase
  def test_janken
# テストを書く。assert_equal 期待される値A, テスト対象B、A = Bであればテスト通過。今回は全ての手の組み合わせと、勝ち負けの結果を記入。
    assert_equal 'あなたはグー、私はグー、引き分けです。', Janken.judge("g", "g")
    assert_equal 'あなたはチョキ、私はチョキ、引き分けです。', Janken.judge("c", "c")
    assert_equal 'あなたはパー、私はパー、引き分けです。', Janken.judge("p", "p")
    assert_equal 'あなたはグー、私はチョキ、あなたの勝ちです。', Janken.judge("g", "c")
    assert_equal 'あなたはチョキ、私はパー、あなたの勝ちです。', Janken.judge("c", "p")
    assert_equal 'あなたはパー、私はグー、あなたの勝ちです。', Janken.judge("p", "g")
    assert_equal 'あなたはグー、私はパー、あなたの負けです。', Janken.judge("g", "p")
    assert_equal 'あなたはチョキ、私はグー、あなたの負けです。', Janken.judge("c", "g")
    assert_equal 'あなたはパー、私はチョキ、あなたの負けです。', Janken.judge("p", "c")
  end
end
```

１．まずは'test/unit'と先に書いた'janken_jedge.rb'をrequireします。

２．Test::Unit::TestCaseを継承したclassを作成します。
名前がtest_で始まるメソッドを作成します。ここでは、test_jankenとしました。

３．作成したtest_jankenメソッドにテストを書いていきます。
assert_equalを用いて、期待される値とテスト対象の値が一致するかで判定しています。
今回は全ての手の組み合わせと、勝ち負けの結果で判定を行いました。

# ３．じゃんけんプログラムを書く
最後に実際に実行するメインロジックであるじゃんけんプログラムを書いていきます。
このプログラムを実行すると、標準入力の待ち状態になって、ユーザーは g,c,pのいずれかを入力します。コンピュータはランダムにグー、チョキ、パーを出し、勝ち負けを判定して、 以下のように出力されます。
例） あなたはチョキ、私はパー、あなたの勝ちです。

```ruby:janken.rb
# 先に作成したメソッド部品をrequire
require_relative 'janken_judge.rb'

# ユーザーはg,c,pいずれかの手を入力
my_hand = gets.chomp
# コンピュータはランダムな手を出す。
enemy_hand = ["g","c","p"].sample

# じゃんけんの判定が出力される。
puts Janken.judge(my_hand, enemy_hand)
```

# ４．プログラムを実行
それでは実行してみます。

```bash
% ruby janken.rb 
g
あなたはグー、私はパー、あなたの負けです。
```

# ５．テストを実行
上の結果より、じゃんけんプログラムは正しく動いているように思えます。全パターンで正しく判定できているのかを確認するためにテストを実行してみましょう。

```bash
% ruby test_janken.rb 
Loaded suite test_janken
Started
.
Finished in 0.001524 seconds.
--------------------------------------------------------------------------------
1 tests, 9 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
--------------------------------------------------------------------------------
```

9 assertions, 0 failures, 100% passedと出ましたので、全パターンでテストを通過したことが確認できました。

それでは間違ったコードを書いていた場合も試してみます。janken_judge.rbのelseの後の行の、「あなたの負けです。」を「あなたの勝ちです。」に変えてから、テストを実行してみます。

```bash
 % ruby test_janken.rb
Loaded suite test_janken
Started
F
================================================================================
     12:     assert_equal 'あなたはグー、私はチョキ、あなたの勝ちです。', Janken.judge("g", "c")
     13:     assert_equal 'あなたはチョキ、私はパー、あなたの勝ちです。', Janken.judge("c", "p")
     14:     assert_equal 'あなたはパー、私はグー、あなたの勝ちです。', Janken.judge("p", "g")
  => 15:     assert_equal 'あなたはグー、私はパー、あなたの負けです。', Janken.judge("g", "p")
     16:     assert_equal 'あなたはチョキ、私はグー、あなたの負けです。', Janken.judge("c", "g")
     17:     assert_equal 'あなたはパー、私はチョキ、あなたの負けです。', Janken.judge("p", "c")
     18:   end
test_janken.rb:15:in `test_janken'
<"あなたはグー、私はパー、あなたの負けです。"> expected but was
<"あなたはグー、私はパー、あなたの勝ちです。">

diff:
? あなたはグー、私はパー、あなたの負けです。
?                         勝ち      
Failure: test_janken(TestJanken)
================================================================================

Finished in 0.01695 seconds.
--------------------------------------------------------------------------------
1 tests, 7 assertions, 1 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
0% passed
--------------------------------------------------------------------------------
```

「"負け"と出てほしいのに"勝ち"になってしまってますよ」と教えてくれました。
しっかりとテストが動いてくれていることが分かりました。