チャート式ruby-IV(assert_equal)



# お題:assert\_equal

[チャート式Ruby](https://qiita.com/daddygongon/items/6f38d9a04e127a7952a7)の4回目，テスト駆動開発の根本となるassert\_equalです．assert equalとはequalかどうかを確かめる(assert)関数です．どんなのでもいいんですが，自分で作ると好きにできますんで，その様子を見てもらいましょう．


# 解法:red,green

まずは1==1です．

    > ruby assert_equal.rb
    ruby: No such file or directory -- assert_equal.rb (LoadError)

もちろんないんで，それをemacsします．

```ruby
p 1==1
```

として見ましょう．

    > ruby assert_equal.rb
    true

と返ってきてますか？

これをmethodにします．英語の感覚だと，

    assert equal expected and result

とでもなるでしょうか．なんで，

    assert_equal(expected, result)

という感じです．まずはred

```ruby
p assert_equal(1, 1)
```

として見ましょう．

    > ruby assert_equal.rb
    assert_equal.rb:1:in `<main>': undefined method `assert_equal' for main:Object (NoMethodError)

関数がないと怒られますよね．それなら，

```ruby
def assert_equal(expected, result)
  return expected == result
end

p assert_equal(1, 1)
```

なら動くし，ちゃんとtrueが返ってますよね．


# 解説:colorize-出色の継承-

これだけだと，殺風景なんで，red, green, refactoringという標語にしたがって動作するように変えます．肝は，colorizeです．

```ruby
require 'colorize'

def assert_equal(expected, result)
  if expected == result
    puts 'true'.green
  else
    puts 'false'.red
  end
end

assert_equal(1, 1)
```

どうです．greenでしょ？

ならtestにredも付け加えて置きましょう．

    assert_equal(1, 2)

redでしょ？

colorizeというgem libraryがないと怒られたなら

    > gem install colorize

でinstallしてください．関学のproxyで引っかかっている人は，

    > gem install colorize -r -p http://proxy.ksc.kwansei.ac.jp:8080

してください．

gemというのはrubyのlibraryを管理するシステムです．色々出せますんで，試してみてください．

```ruby
> irb
irb(main):001:0> require 'colorize'
=> true
irb(main):002:0> String.colors
=> [:black, :light_black, :red, :light_red, :green, :light_green, :yellow, :light_yellow, :blue, :light_blue, :magenta, :light_magenta, :cyan, :light_cyan, :white, :light_white, :default]
```

colorizeは，ruby標準のString classに色を表示するmethodを上載せ(override)します．こんなのがすぐに使えて色々あるのがrubyです．いや，object思考です．


# 改良:richer output

もう少し出力をrichにしましょう．

-   引数でとってきた，expected, resultの値をそのまま出力
-   どうなったかを記述
    -   **true:** print "succeeded in assert\_equal.\n".green
    -   **false:** print "failed in assert\_equal.\n".red

どうです．できました？

```ruby
require 'colorize'

def assert_equal(expected, result)
  if expected == result
    puts 'true'.green
  else
    puts 'false'.red
  end
end

assert_equal(1, 1)
assert_equal(1, 2)
```


# 拡張:assert\_not\_equal

    assert_not_equal(1, 2)

を考えましょう．まずはtestです．上のんを入れて実行して見ましょう．

    > ruby assert_equal.rb
    expected :: 1
    result   :: 1
    succeeded in assert_equal.
    expected :: 1
    result   :: 2
    failed in assert_equal.
    assert_equal.rb:15:in `<main>': undefined method `assert_not_equal' for main:Object (NoMethodError)
    Did you mean?  assert_equal

なんかが返ってくるでしょうか．関数がないと怒られます．まずはcopy & pasteします．関数名だけassert\_equalからassert\_not\_equalに直しましょう．

    expected :: 1
    result   :: 2
    failed in assert_equal.

となります．このままだと，振る舞いがおかしいですよね．修正します．

    expected :: 1
    result   :: 2
    succeeded in assert_not_equal.

となればOKです．

```ruby
require 'colorize'

def assert_equal(expected, result)
  if expected == result
    puts 'true'.green
  else
    puts 'false'.red
  end
end

assert_equal(1, 1)
assert_equal(1, 2)
```


# 整理:重複箇所の整理

重複している箇所は整理して，別立ての関数にしてください．

```ruby
require 'colorize'

def assert_equal(expected, result)
  if expected == result
    puts 'true'.green
  else
    puts 'false'.red
  end
end

assert_equal(1, 1)
assert_equal(1, 2)
```


# 補足:重複実行の予防

このcodeは今後繰り返し使っています．そのためには，requireで呼び出す必要があります．同じdirectoryに写(copy)して使うようにします．

例えば，

```ruby
require './assert_equal'

assert_equal(2, 1*2)
assert_not_equal('bob', 'bob2')
```

というように使います．

しかし，今のままだとassert\_equal.rbに書いたテストがそのまま実行されてしまいます．そこで，そういうのを回避してくれるidiom(熟語)があります．

```ruby
if $PROGRAM_NAME == __FILE__
  assert_equal(1, 1)
  assert_equal(1, 2)
  assert_not_equal(1, 2)
  assert_not_equal(1, 1)
end
```

です．意味は，codeが書いてあるファイル名(FILE)が，動いているファイル名($PROGRAM\_NAME)と一致したら中身を実行です．これはidiomなんで&#x2026;覚えてください．あ，ここに書いてあるということをね．

```ruby:code/assert_equal_final.rb
require 'colorize'
def puts_vals(expected, result)
  puts "expected :: #{expected}"
  puts "result   :: #{result}"
end
def assert_not_equal(expected, result)
  puts_vals(expected, result)
  print expected != result ?
  "succeeded in #{__method__}.\n".green :
    "failed in #{__method__}.\n".red
end
def assert_equal(expected, result)
  puts_vals(expected, result)
  print  case expected == result
         when true  ; "succeeded in #{__method__}.\n".green
         when false ; "failed in #{__method__}.\n".red
         end
end

if $PROGRAM_NAME == __FILE__
  assert_equal(1, 1)
  assert_equal(1, 2)
  assert_not_equal(1, 2)
  assert_not_equal(1, 1)
end
```



------
 - **source** ~/git_hub/ruby_docs/chart_style_ruby/c4_assert_equal.org