単 体 テ ス ト id:ykhr-kokko
自己紹介 こうみえて 28 歳なりたてほやほや 嫁さんの次に Java が好き(と言わされてる) エロい(と言わされてる) どーでもいいプラグインを公開
単体テストって かたーいお話に見えますが   ・・・そうです、固いです。 ですが、なんだかこむずかしい話をだらだら話しても面白くはいので、軽いノリでいきます そもそも単体テスト好きな人っているの?
はじめに テーマ 「単体テスト」 Unit Test 今日の目標 単体テストがやりたくてやりたくてしかたなくなる! というのはムリなので、 単体テストについて、日ごろ自分が思っていることをだらだらと話してみます。 基本的にグチじゃないけど、色の薄い部分はグチです。
昨日の夜の気持ち ただ今、前日(当日)の 25 時です、まだ資料できてねーよぉぃ、前日がお客さん飲みで、 23 時すぎに解散して家に着いてとりあえず資料作ってるけど全然はかどらねー、そりゃそうだわ、どー考えても飲みすぎてるし、しかもですよ、飲みに行った店って高田屋ですよ高田屋、そう、あの高田屋なんですよ、ガルーンのスケジュールを何度見直しても今日の懇親会高田屋じゃん、なにが悲しくて 2 連チャンで高田屋行かないといけねーんだよ、ってグチってもさ、自分が高田屋を予約したからしゃーないんだよねw だってそこしか思いつかなかったんだもん でもお酒大好きだしエンジニア同士の飲みは楽しいし見知らぬ方々がいるからさらに楽しそーだし某おっきい人のプレッシャーもあるしまぁいいよね、ってかそもそもエンジニアサミットという素晴らしいイベントを企画してくださった原さんにすげー感謝ですよ、なかなか自分ひとりの力じゃこんなことできないし、いろんな人の話を聞くだけで面白そーだし、こんな会に自分が発表者として貢献できるなんて今からwktkっすよ、だから夜眠れなかった影響で発表がgdgdだとか、誰かの発表中にワンセグでこっそり競馬中継見たりしてても文句言わないでね★ 注:グチのサンプルです
しつもーん 単体テスト、やってますか? ちなみに今の私のプロジェクトは・・・ 某かなりおっきいプロジェクト 詳細は企業秘密 で、単体テストは (小声で)やってません (一応)やってることにはなってる んじゃ、どーしてるかと言うと 結合試験で単体テストレベルのテストやりまくり 項目多すぎだろwww終わんねーよwww
というわけで本題 突然ですが、Javaの問題です。 ※ Java らー以外のみなさん、ごめんなさい
問題1 Integer.MIN_VALUE  は  -2^31  です。 さて、 Long.MIN_VALUE  は ??  そして、 Double.MIN_VALUE は ???
問題1 Integer.MIN_VALUE  は  -2^31  です。 さて、 Long.MIN_VALUE  は ??    -> -2^63 そして、 Double.MIN_VALUE は ??? -> 2^-1074  ・・・正の数
問題2 次のオブジェクトを TreeSet にいくつか入れるとどうなるでしょう? public class Entry implements Comparable<Entry> {   private String hoge;   @Override   public int compareTo(Entry o) {   return 0;   } }
問題2 次のオブジェクトを TreeSet にいくつか入れるとどうなるでしょう? ->何個いれても、 1 個にしかなりません   理由は(ry public class Entry implements Comparable<Entry> {   private String hoge;   @Override   public int compareTo(Entry o) {   return 0;   } }
問題2(旧) 次のメソッドは何を表示するでしょう? さて、これは成功するでしょうか。 File file = new File(“../..”); System.out.println(file.getAbsolutePath()); File file = new File(“C:/hoge/foo/bar.txt”); FileOutputStream fos = new FileOutputStream(file);
問題2(旧) 次のメソッドは何を表示するでしょう? さて、これは成功するでしょうか。 File file = new File(“../..”); System.out.println(file.getAbsolutePath()); File file = new File(“C:/hoge/foo/bar.txt”); FileOutputStream fos = new FileOutputStream(file); C:/xxx/...  ...xxx/../.. -> ホントのパスにしたい場合、 FILE#getCanonicalPath() を使う ※ただしこいつは throws IOException C:/hoge/foo/ がないと、 IOException (指定されたパスが見つかりません。)となります。
なにを言いたいかと言うと・・・ こういう問題から発生するバグは、たいてい単体テストレベルで摘み取れるバグです。 単体レベルのバグが結合テスト以降に残ると・・・ バグがみつけにくい 手戻りが大きい(単体テストからやり直し) -> あきらかにコスト増ですよね?
なので 単体テストはやりましょう! 別に、きちんと試験項目を作成してテストコード書いてやれとまでは言わない いや、言えない。だって、自分がやってないんだもん。特に OSS なんかだと・・・ ふつーのプロジェクトだと、きっちりやるべきだけどね。 求められてる品質が OSS とは違うから。 最低限、動かしましょう つーかさ、動かしながら作ったほうが断然いいよね 世の中、まったく動かさずに作る人もいるんですよ 大企業なんかだと、単体試験としてバグを出したいがため(≒品質評価報告書でこんだけバグを出したから大丈夫!って言いたいがため)に、動かしながら作るのを否定してくるんですよ
と、そんな当たり前の話はおいといて
それじゃ 単体テストでもやろうか! でも、どーやって?? とりあえず JUnit ? テストケースの作成単位は? どこまで連結してやるの? 自動実行の仕組みは?
よく聞くこと 「単体テスト、どーやったらいいか わかりません!」
よく聞くこと 「単体テスト、どーやったらいいか わかりません!」 「試験項目の挙げ方、わがんね!」 じゃね???
試験項目があればテストはできる 試験項目が挙げられれば、テストコードだって簡単に作れるはずです。 だって、ぼくたちは 3 度のメシよりコーディングが好きなんですから  (*) (*)  でも、嫁さんのほうがもっと好きです ( 言わされてます )
問題3 んじゃ、試験項目を挙げてみよう! public boolean isOdd(int i) { return (i % 2) == 1; }
ほーら、挙げられるじゃんww 次は趣向を変えて。
問題4 とこれで、これだとどうよ? /** *  このメソッドは、引数の整数が奇数なら true 、 *  偶数なら false を返します。 */ public boolean isOdd(int i) {  ・・・
自分的な答え 2 3 -1 -2 0 Integer.MIN_VALUE Integer.MAX_VALUE
テスト項目を挙げる際の罠 案外、コードを先に見てしまうと、テスト項目が挙がらなかったりする。 コードが正しい、という前提になってしまうことが多い 一度コードを見てしまうと、広い視野で見ることは難しい(自分は) これだと、本当に仕様を満たしているのかどうか、疑問じゃないですか? 実は、さっきの問題にはバグがあったり。 Java Puzzlers からちょっとパクらせてもらいました。
ブラックボックステスト コードを見ずに、仕様(≒ Javadoc レベルの情報)から項目を挙げる よく言われる手法 同値分割 境界値分析
ホワイトボックステスト コードを見ながら試験項目を挙げる よく言われるカバレッジというやつ ステートメントカバレッジ ブランチカバレッジ コンディションカバレッジ etc... 詳細は略 (めんどい)
その他 経験ベースからくる項目も重要です。 たとえば、先ほどの問題で言えば・・・ 0 Integer.MIN_VALUE Integer.MAX_VALUE といった項目も考えられます。経験的にバグりやすそうな値を挙げるわけです。
実プロジェクトで使うには・・・ みなさんがわかっていても、チームのメンバーが同レベルの試験項目が挙げられるわけじゃないです。 Y 「なんちゃら技法を使って項目を挙げてください」 B 「お前は何を言っているんだゴルァ」 Y 「ひーっ、ごめんなさいごめんなさいごめんなさい」
そこで 試験項目抽出技法から、試験観点一覧といったものにブレイクダウンしておくとやりやすい ループの回数は0, 1, 複数, 最大をやる 境界となる前後の値をテストする テストで実行行すべてを通るように 分岐はどっちのパターンもやる 試験項目のレビューをすることも必要 項目がきちんとあげられているか 逆に無駄な試験項目がないか 結合ではけっこうやられてるんだけど・・・。
さて、 ブラックボックステスト、重要です ホワイトボックステストも重要です 経験ベースからくる項目も重要です んじゃ、どうすりゃいいの?
そこで・・・ 自分的推奨方法 ブラックボックステストでテスト実施 仕様を満たしているかどうかの観点でテスト ここに、経験ベースの観点も。 カバレッジを測定 ホワイトボックステストでテスト実施 ブラックボックスでカバレッジを満たせなかった部分について項目を追加 満たせない部分は、不必要なコードかどうかを判断することも必要
さいごにテストケースについて せっかく作成したテストケースを捨てるプロジェクトがあります
┏ どうぐ━━━┓   ┃ ykhr  ┃   ┃┏━すてる ━━ ━━━━━━━┓   ┃┃  E ゴールデンフィンガー ┃   ┃┃  E えっちなまんが  ┃   ┗┃  E すきんへっど   ┃    ┃  E すけすけめがね   ┃    ┃  嫁  Ver 3.25  ┏━━━━━━━━━ ━━ ━━┓    ┃  ガンダム  ┃テストケースをすてますか?┃    ┃->  テストケース ┃-> はい          ┃    ┗━━━━━━━━━┃  いいえ          ┃               ┗━━━━━━━━━━━ ━━ ┛   ┏━━━━━━━━━━━━━━━━━━━━━━┓   ┃ それをすてるなんて、とんでもない!!     ┃   ┃                       ┃   ┃                        ┃   ┃                  ▼  ┃   ┗━━━━━━━━━━━━━━━━━━━━━━┛
テストケースすてんな>< テストケースは、回帰試験で使ってこそ価値のあるものです。 回帰試験をやらないなら、コスト的に見てテストケース作ってまでやる価値はあまりないです。 テストケースがあると、テストケースの保守もする必要があるので、一見コスト増に見えますが、そんなことはありません(妄想)。 このへんは次回にきっと誰かが・・・
テストケースを捨てないために 逆に、テストケースはいつでもどこでも実行できるように作成すべき。 DB がからむと、かなりタイヘンだけど テストケースの可読性も重要 読めないテストケースは、あっても意味ナシ プロジェクト毎に、テスト用の親クラスを作るといった仕組みも必要 そのプロジェクトを動作させる前提条件を実装するとか テストケース用ライブラリを簡単に使えるようにするものとか
まとめ テストはスキル やればできるようになる 試験項目さえ挙がれば、テストコードはかける 試験項目抽出の手法はいくつかある 全部を知る必要はないけど、ある程度は知っておくべき。 テストケースも資産です 俺は Java より嫁さんが好き(言わさ(ry
おまけ テストの資格:「 JSTQB 」 テスト技術者認定資格 Japan Software Testing Qualifications Board http://www.jstqb.jp/ 合格すると、名詞に貼るシールがもらるので、これ目当てに受験しよう! まだ一枚も使ったことないけどw

Unit Test