Shuta(@did0es)です。ども。

激弱のお魚さんによるド素人視点からテスト駆動開発について語ろうと思います。
※鉞いいよこいよ(震え声)

突然べらべらと話し始めると引かれそうなので、自己紹介を兼ねて最近の進捗報告をしようと思います

Shutaです。ども。

最近はRubyばっかり書いてます(今回もそれ絡みの話です、Ruby星人でごめんね)

先日はのこのことTOKYOに出て、某緑と黒の会社のMeetupでウェイウェイしながらお寿司食う人をしてました。
楽しかった。みんなキラキラしてて眩しかった。

後はProcessingとかp5jsでメディアアートの真似事をしています。GPU積んだいいパソコン欲しいのでほしいものリスト公開しておきます

何もない人畜無害です、よろしく。

以下本文でございます

 

僕は夏休みにRails(†黒魔術†)でAPIサーバーをこしらえて、
もう今では老人扱いのApacheで簡単なWebサーバーをよっこらせしてWebアプリケーションを作りました。

当時僕は右も左もわからないプランクトンだったのでとりあえず勧められるがままにRailsでサーバー設計してたのですが、

Rails「ルーティング辺りがダメです」

僕「くわしく」

Rails「はい、ルーティング辺りがダメです」

僕「… 直しました」

Rails「コントローラー辺りがダメです」

僕「( #^ ω ^ )はい、直しました ボタンポチー」

Rails「ルーティング辺りがダメです」

僕「( #^ ω ^ )」

僕「(」゚O゚)」ああああああaaaahhhhhhhhhhhaahh!!!!!くぁwせdrftgyふ(ry」

みたいな茶番をたびたび繰り広げていました

ちょっとRailsはエラー画面が白地に赤で軽くホラーな感じなのと、賢いIDEとか使わないとエラーとか仕様の修正中に、一体どこを直しているのかわからなくなってにゃ~んって感じになります。

そもそも自分で開発ということで、動いたらええねん精神でやってたので、コントローラーの行数とか油断してるとあっという間にえらいことになってました、反省。

それを防ぐために、
「はいっ!!1つのコントローラーファイルには10以内!!リファクタリングは正義!!!冗長さはサヨウナラ!!!」みたく縮小化していくべきなのですが

  • コーディング規約とか組んだことねぇ…しかもぼっちで開発ですし…
  • リファクタリングムズカシイ
    (追記 : Rubyの魔法使い目指して日々修業中だよ☆わたしも立派な魔女になれるかなぁ…)

という諸々から、とりあえずテストコードを走らせるテスト駆動開発をおべんつよして、もうちょい親切なエラーを見ながら修正とかリファクタリングもしてきたいと思い

テスト駆動、はじめました。(冷やし中華始める感じ)

テスト駆動にはテスティングフレームワークを使用します
Rubyにはなんか有名なテスティングフレームワークが3つぐらいあります
Minitest とtest-unitとRspecです。ざっくりこの3つについて紹介していきます。
まずは

Minitest : 今回はこれを使った感じをつらつらと書いていくので後程詳しく話します。使った理由は簡単だからです(Rubyの標準のgemに入っているので別途インスコしなくていいので手軽、書きやすいのもお魚さんには優しい)

test-unit : これはなんか古いフレームワークです。標準のgemに入っています
うーーん、ちょっとかじった感じMinitestに近しい感じです
- じゃあMinitestでいっか(鉞が飛ぶ音)

Rspec : なーんかdescribe関数とかでネストにしてexampleで帰ってきてほしい結果書いて、たまにメタプロも出てきて…みたいなちょっと前2つとは違う味がするやつです。
標準のgemに入っていない!!!!メッッ!!!!
(また追々触れていきたいと思います)

ということでMinitestについて

の前に ~ 何故テスト駆動開発すべきなのか ~ みたいなことについて某エンジニア向けポエム投稿サイトをあさってたらいい感じの記事見つけたのでそこから引用してきます

テストコードはアプリケーションの命綱、安全ネット、防弾チョッキ

「このコード、テストなしでリリースするのはちょっと不安だな」と思ったら、それがテストを書くトリガー

  • リリースするときに「ちゃんとうまく動きますように」と祈ってる自分がいたら、テストが不足している証拠

将来の自分が楽をするために書く

  • コマンド一発でこれまで書いてきたコードの動作確認ができる! 速いし、楽ちん!!
  • 毎回リリース前に全部手作業と目視でテストするつもり?無理だよね!

将来、自分のコードをメンテするかもしれない他のメンバーのために書く

  • ドキュメントを書く代わりに、コードを書いた人の意図や頭の中にある仕様を明示的なテストコードとして残しておく

将来、Railsやライブラリ(gem)をアップデートするときのために書く

  • 「テストが全部パスすればきっと大丈夫」と思えるようにする

不具合を修正するときに書く

テストコード上で不具合を再現させて、失敗するテストコードがパスするようにアプリ側のコードを修正する

テストコードがあれば不具合の修正と再発防止を一度に実現できる(同じ不具合を再発させてしまうのはプロとして恥ずかしい

【初心者向け】テストコードの方針を考える
(何をテストすべきか?どんなテストを書くべきか)
https://qiita.com/jnchito/items/2a5d3e15761fd413657a

はいプロ って感じでお魚さんの僕にはまだ早い感じがしますが、とにかく開発の現場では本番環境でのやらかしをなくすためにテスト駆動する感じです
その副産物みたいな感じで僕の望むわかりやすいエラーメッセージを得られます。

あとはカバレッジを100%(とにかく全体のテストを書いてパスさせる)は、あまり意識しなくていいようで、
自分の不安なところでテストを書くのがいい感じっぽいです(いっぱい書くとコードの実行が遅くなっちゃう…)
とりあえず今回は手動でテストを駆動させていきます

ここからMinitestについてです
前述のとおり、Rubyに元から入っているテスティングフレームワークです。
色々話すよりもコード出した方が早いのでコード出すね

(これはRGBと16進数カラーコードの変換を行う簡単なプログラムです)
lib/rgb.rb
def_to_hex(r, g, b)
    [r, g, b].inject('#') do |hex, n|
        hex + n.to_s(16).rjust(2, '0')
    end
end

test/rgb_test.rb
require 'minitest/autorun'
require './lib/rgb.rb'

class RgbTest < Minitest::Test
    def test_to_hex
        assert_equal '#000000', to_hex(0, 0, 0)
        assert_equal '#ffffff', to_hex(255, 255, 255)
    end
end

(実行結果)
Run options: --seed 40922

#Running

.

Finished in 0.002091s,  478.2401 runs/s, 956.4802 assertions/s
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips 

はい。以上です

とはいかないのでちょっと色々書きます

Minitestのテストの書き方としては
requireでMinitestのTestメソッドを読み込みます。
これでとりあえずMinitestが使える感じになります

Minitestでテストを作成するとき、テストしたいメソッドはtest_から始まるようにします。Minitestはこれを血眼で探して実行しに行きます

今回はとりあえず実行結果のテストをしたいのでassert_equalメソッドで検証してます
第一引数は欲しい結果を入れて、第二引数に実行するメソッド入れます

あとはRubyの書き方なので適当にさーっと

次に実行結果です
Run options: --seed なんか数字はテストの実行順序をシャッフルするオプションらしいです、デフォルトでついてます。よくわからないけどまぁ、気にしない気にしない

ちゃんとテストコードが実行されると.が表示されます
ミスるとFが表示されます(下みたいな感じ)

F
Failure
RgbTest#test to hex [test/rgb_test.rb:7]:
Expected: "#fffffe"
Actual: "#ffffff"
(テストコードの欲しい実行結果のところを#ffffffから#fffffeに変えた)

エラーわかりやすいし、コンソールにもちろん出力なのでRailsみたいな気合の入った、紅白の縁起がいい配色のエラーを読まなくていいので精神衛生的に(?)良いです。

Finished in 0.002091s,  478.2401 runs/s, 956.4802 assertions/s
は実行にかかった時間です。

1 runs, 2 assertions, 0 failures, 0 errors, 0 skips 
右から 実行したメソッド数、検証した件数、やらかし数(実行失敗)、やらかし数(エラー・例外)、skipメソッドでスキップされた件数

こんな感じで色々とテストを書くと情報が得られます
特にコンパイラに基本的にぶち込まない言語は、テストコード書くだけでちょっとした安心感に包まれそうです。

ということで、
みなさんテスト駆動開発(しなさい)
(Rubyも書いてくれるとおじさんとっても嬉しいです、一緒にメタプログラミングするお仲間募集中です 😉 )

参考文献:プロを目指す人のためのRuby入門(頂き物)

Twitterでフォローしよう

おすすめの記事