10分テスト - 学校図書株式会社 · 238 10分テスト 目 次 4 年 10分テスト 10分テストについて 「10分テスト」は,各単元の次の前後で,主に観察・実験の技能と知識理解を
Nds#24 単体テスト
-
Upload
kazumune-katagiri -
Category
Documents
-
view
1.748 -
download
1
Transcript of Nds#24 単体テスト
今日から始める!単体テストの自動化のススメ
2012/01/29@nemuzuka
第 24 回長岡 IT開発者勉強会
単体テストしやすいモジュール設計の指針をつくってミタ ~カバレッジ 40%めざせ
自己紹介
● id:nemuzuka,@nemuzuka● 昨年の春、地元の長岡に帰ってきました!
● サーバサイドに Javaを使用したWebアプリケーションの開発を主にやっております
● 新潟は Javaやってる人少ない気がします
みなさん、テストしてますか?
「お金」という対価を受け取るレベルのプログラムを提供する以上、
テストしないということは考えられません。
リリ|ス?
テストしないで
え|
までだよね|
自己満プログラム
許されるのは
テストしなくて
テストは1回やればおしまい?システムは生き物。
機能を追加していく過程でそもそもの振る舞いを壊してしまうこともしばしば。
ソフトウェアの場合は関係ないと思ってた箇所に思いもよらず影響を及ぼすこともあります。
開発言語 /DBサーバ /フレームワークのバージョン UPを行う際にデグレってないかの確認を全部手動でやるのはかったるい。だからといって、構築した時のバージョンを維持するってのも・・・ねぇ
やっぱり複数回やることが多いんです
テストはしなきゃいけないのはわかるけど面倒なんだよなー
機械の力を借りましょう。
そりゃ、毎回手動でおこなってたんじゃ効率が悪い。
そこで今日のお題は
テストなんてかったるくてやってられな 限りある時間を有効に使いたいそんなあなたに、うってつけ!
単体テストを自動化しやすいモジュール設計
について考えてミタテストを考える会
テストの自動化というと
xUnitを使えばいいよねあとよろしく
失敗 ENDへのフラグ
ある程度の方針が必要なんです
● テストしやすい設計、アーキテクチャの確立
● 開発者個人にまかせてしまうと、粒度はバラバラ
(あ、これ俺のスキーマでないと動かないっスよ)
● 何やってるテストなのかわからない
(でも、カバレッジ高いから良いでしょ?)
● 作られたは良いけど、結局放置
テストが通らなくなってくると、魔法のパラメータ
「 -Dmaven.test.skip=true」でテストの実行を無かったことに
作ったものの、使い続けられないテストクラスが量産されることに・・・
せっかくつくったのに
モッタイナイ
まずは前提条件対象:MVCモデルを採用したWebアプリ
【思想】・ View/Controller
→ ロジック記述量を少なく (Actionにロジック書く奴はおしおき )・Model
→ もう、嫌って程集約
【自動化の対象範囲】
・ Ui部分 (View)は自動化対象外→ seleniumとか使ってもいいけど、 UI部分って変更多いし、
かけた時間に対してメリットが少ないと思うの・サーブレット (Controller)も自動化対象外
→ いいからModelに全部任せておけって! Mockでリクエストパラメータとか作るの面倒じゃん。
→ でも、 Sessionオブジェクトとか HttpRequestとか J2EE前提なオブジェクトはModelに渡すなよ。 パラメータは POJOだ (簡単にインスタンスを生成できる奴でお願いします )
→ Modelからの結果をそのままレスポンスに設定するくらいの勢いで!
頑張って自動化する箇所はModel
画面に表示する項目の加工すらもModelに持たせるとかして、 View部分にはできるだけ判断文を持たせないようにした方が幸せになれる気がします。(ロジックの分散を避けるのが目的です。 )
システム全体を自動化するには膨大な時間と工数がかかるので、対象を絞りましょう→ バグり易い所 (Model)を重点的にリグレッションテストしやすいように
した方が費用対効果高そう。→ Webブラウザからの打鍵テストを行う時の確認事項も少なくなるはず。→ 本来、Webブラウザの打鍵から始まる一連の処理は結合テストだと思う。
自動テストしやすいメソッド
「このメソッドを呼んだら、結果どうなる」が容易に定義できるもの
もっと言えば、パラメータだけで処理して結果を返すメソッド
DBアクセスの場合は、前提条件のデータを格納しておいて、メソッド呼び出しで SQL発行させて結果確認、というのが基本的な流れだから、まぁとっつきやすい
例えばこんな疑問
● xUnitのサンプルって、単純な処理(足し算とか引き算)ばっかであんまり実務っぽくないんだもん
– 現実のシステムはそんなに単純じゃないよ
– 1回のメソッド呼び出しでいろんなことやるじゃない
でもそれは、メソッドの振る舞いを一連の処理としてみたときの話
粒度を小さくすれば
「結果どうなる」が定義しやすくなるんじゃね?
ファイルのインポート処理アップロードされたファイルを1行ずつ読み込んで、テーブルに格納されていなければ、登録。格納されていれば、更新
public void doImport(InputStream is) { Readerインスタンスを生成 while(1行読み込む) { 読み込んだ情報を元に検索条件作成 DB検索 if(該当レコードあり) { 更新データを作成 DB更新 } else { 登録データを作成 DB登録 } } Readerをクローズ}
このメソッドを呼び出したらどうなるべきか??
テストケースのパターンを増やす時は、 InputStreamのパターンを増やす?
こうしたらどうかな?public void doImport(InputStream is) { Readerインスタンスを生成 while(1行読み込む) { create検索条件 do検索 create登録・更新Entity do永続化 } Readerをクローズ}
検索条件 create検索条件(行データ) { XXXX}
検索結果 do検索(検索条件) { (DBアクセス)}
登録・更新Entity create登録・更新Entity(検索結果) { if(検索結果あり) { 更新用のEntity生成 } else { 登録用のEntity生成 }}
void do永続化(登録・更新Entity) { if(登録) { 登録処理(DBアクセス) } else { 更新処理(DBアクセス) }}
メソッド内の処理を細分化→ メソッドが何をしているのか
わかりやすくする (メソッド間も疎結合 )→ テストパターンを追加する時は
引数のパターンを増やす
※ソースコード中にコメントを書くよりも細分化単位で JavaDocを書いた方がよっぽどいいソースコードになる、と思う
さらに一手間
● 細分化したメソッドのスコープはパッケージプライベート
– privateだとテストクラスから参照できない● わざわざリフレクション使うのもなぁ・・・
● publicでなければ大体良いんじゃね?● テストクラスは同じパッケージに配置
– どのクラスのテストをしているのかわかりやすく
– クラス名も XXXTestとかね。
Mockオブジェクト
● 使わなくても良いように実装を見直してみる
● MockはあくまでもMock– テストクラス以外にもメンテナンスコストがかかる
– Mockを作ることに情熱をかけ始めたら本末転倒
● テスト済みであれば、実クラスを呼び出しても全然アリだと思う
実装設計にもうひと手間
● Modelを責務に分けたレイヤーで細分化
Service
Logic
Dao DB
Model
※トランザクションスクリプトでもいいじゃない
レイヤーの責務● Dao
– DBアクセス● 1テーブルに対する CRUD● 複数テーブルを結合した SELECT文発行
● Logic
– DAOに対するアクセスのとりまとめ● 親子関係のテーブルに対する登録処理
– Web/Batch共通で使えそうな処理● メール送信
● 複数 Serviceで利用される処理● Service
– Controllerとの間を取り持つ delegate– Logicに対するアクセスの取りまとめ
テスト自動化のメリット● リグレッションテスト
● カバレッジレポート
– テストクラスで実行した箇所がわかる
● Jenkins等の CIツールと組み合わせて– 最新のソースコード取得
– ビルド (リリースモジュールの生成 )– テスト
– レポート出力
を自動で行うことができる
・プロジェクトは進んでいるか・「俺、仕事している」感を体感できるハズ
開発者の環境以外でも動作するようにテストクラスを記述することで、環境依存を減らす(テストクラスにおけるフルパス指定禁止、スキーマは CIツールや開発者毎 )
老婆心ながら・・・● カバレッジの目標はがんばりすぎない
– ≠高カバレッジ 高品質
● そもそも仕様を満たしていないかもしれません
– カバレッジ 100%にするのは難しい● 外部リソースアクセス
● 標準 APIの例外– カバレッジでなく、 assertにこだわりましょう– SQLのカバレッジは取れない
● SQLでがんばっている箇所があれば、データパターンを増やしてテストもがんばる!
● バグが発生したら
– 再現するテストケースを書いて、そこから修正
– 抜けてた観点をチーム、組織で共有できれば尚良し
● 単体テストはあくまでもメソッドとしての振る舞い
– 結合テスト、システムテストが不要な訳ではない
最後に
テストのスキルは、言語がかわってもそんなに変わりません。なにより、テストしやすい実装ができるということは、開発者として大きなアドバンテージがあると思います。
「テストしやすい実装=シンプルな実装」を目指せるはずです。システムは生き物なのでシンプルに保てれば保守もしやすくなるでしょう。
テストがいくら完璧でも、使う人に価値が無いと思われれば、そのシステムは意味がありません。テストだけに情熱をかけすぎないように、ほどほどに。
興味が出てきたら
買って読んでね
ご清聴ありがとうございました