Contenu connexe
Similaire à Nds#24 単体テスト (20)
Plus de Kazumune Katagiri
Plus de Kazumune Katagiri (9)
Nds#24 単体テスト
- 1. 第 24 回 長岡 IT 開発者勉強会
今日から始める!
単体テストの自動化のススメ
単体テストしやすいモジュール設計の指針をつくってミタ
~カバレッジ 40% めざせ
2012/01/29
@nemuzuka
- 2. 自己紹介
● id:nemuzuka,@nemuzuka
● 昨年の春、地元の長岡に帰ってきました!
● サーバサイドに Java を使用した Web アプリ
ケーションの開発を主にやっております
● 新潟は Java やってる人少ない気がします
- 11. ある程度の方針が必要なんです
● テストしやすい設計、アーキテクチャの確立
●
開発者個人にまかせてしまうと、粒度はバラバラ
(あ、これ俺のスキーマでないと動かないっスよ)
●
何やってるテストなのかわからない
(でも、カバレッジ高いから良いでしょ?)
● 作られたは良いけど、結局放置
テストが通らなくなってくると、魔法のパラメータ
「 -Dmaven.test.skip=true 」
でテストの実行を無かったことに
作ったものの、使い続けられないテストクラスが量産され
ることに・・・
- 13. まずは前提条件
対象: MVC モデルを採用した Web アプリ
【思想】
・ View/Controller
→ロジック記述量を少なく (Action にロジック書く奴はおしおき )
・ Model
→もう、嫌って程集約
【自動化の対象範囲】
・ Ui 部分 (View) は自動化対象外
→ selenium とか使ってもいいけど、 UI 部分って変更多いし、
かけた時間に対してメリットが少ないと思うの
・サーブレット (Controller) も自動化対象外
→いいから Model に全部任せておけって!
Mock でリクエストパラメータとか作るの面倒じゃん。
→でも、 Session オブジェクトとか HttpRequest とか
J2EE 前提なオブジェクトは Model に渡すなよ。
パラメータは POJO だ ( 簡単にインスタンスを生成できる奴でお願いします )
→ Model からの結果をそのままレスポンスに設定するくらいの勢いで!
- 14. 頑張って自動化する箇所は Model
画面に表示する項目の加工すらも Model に持たせるとかして、 View 部分にはできるだ
け判断文を持たせないようにした方が幸せになれる気がします。
( ロジックの分散を避けるのが目的です。 )
システム全体を自動化するには膨大な時間と工数がかかるので、対象を絞りましょう
→バグり易い所 (Model) を重点的にリグレッションテストしやすいように
した方が費用対効果高そう。
→ Web ブラウザからの打鍵テストを行う時の確認事項も少なくなるはず。
→本来、 Web ブラウザの打鍵から始まる一連の処理は結合テストだと思う。
- 16. 例えばこんな疑問
● xUnit のサンプルって、単純な処理(足し算と
か引き算)ばっかであんまり実務っぽくない
んだもん
– 現実のシステムはそんなに単純じゃないよ
– 1 回のメソッド呼び出しでいろんなことやる
じゃない
でもそれは、メソッドの振る舞いを
一連の処理としてみたときの話
- 19. こうしたらどうかな?
public void doImport(InputStream is) { 検索条件 create検索条件(行データ) {
Readerインスタンスを生成 XXXX
while(1行読み込む) { }
create検索条件
do検索 検索結果 do検索(検索条件) {
create登録・更新Entity (DBアクセス)
do永続化 }
}
Readerをクローズ 登録・更新Entity create登録・更新Entity(検索結果) {
} if(検索結果あり) {
更新用のEntity生成
} else {
登録用のEntity生成
}
}
メソッド内の処理を細分化
void do永続化(登録・更新Entity) {
→メソッドが何をしているのか if(登録) {
わかりやすくする ( メソッド間も疎結合 ) 登録処理(DBアクセス)
→テストパターンを追加する時は } else {
引数のパターンを増やす 更新処理(DBアクセス)
}
}
※ ソースコード中にコメントを書くよりも細
分化単位で JavaDoc を書いた方がよっぽどい
いソースコードになる、と思う
- 20. さらに一手間
● 細分化したメソッドのスコープはパッケージ
プライベート
– private だとテストクラスから参照できない
● わざわざリフレクション使うのもなぁ・・・
● public でなければ大体良いんじゃね?
● テストクラスは同じパッケージに配置
– どのクラスのテストをしているのかわかりや
すく
– クラス名も XXXTest とかね。
- 21. Mock オブジェクト
● 使わなくても良いように実装を見直してみる
● Mock はあくまでも Mock
– テストクラス以外にもメンテナンスコストが
かかる
– Mock を作ることに情熱をかけ始めたら本末転
倒
● テスト済みであれば、実クラスを呼び出して
も全然アリだと思う
- 22. 実装設計にもうひと手間
● Model を責務に分けたレイヤーで細分化
Model
Service
Logic
Dao DB
※ トランザクションスクリプトでもいいじゃない
- 23. レイヤーの責務
● Dao
– DB アクセス
● 1 テーブルに対する CRUD
● 複数テーブルを結合した SELECT 文発行
● Logic
– DAO に対するアクセスのとりまとめ
● 親子関係のテーブルに対する登録処理
– Web/Batch 共通で使えそうな処理
● メール送信
● 複数 Service で利用される処理
● Service
– Controller との間を取り持つ delegate
– Logic に対するアクセスの取りまとめ
- 24. テスト自動化のメリット
● リグレッションテスト
● カバレッジレポート
– テストクラスで実行した箇所がわかる
● Jenkins 等の CI ツールと組み合わせて
– 最新のソースコード取得
– ビルド ( リリースモジュールの生成 )
– テスト
・プロジェクトは進んでいる
– レポート出力 ・「俺、仕事している」感
を体感できるハズ
を自動で行うことができる
開発者の環境以外でも動作するようにテストクラスを記述することで、環境依存
を減らす
( テストクラスにおけるフルパス指定禁止、スキーマは CI ツールや開発者毎 )
- 25. 老婆心ながら・・・
● カバレッジの目標はがんばりすぎない
– 高カバレッジ≠高品質
● そもそも仕様を満たしていないかもしれません
– カバレッジ 100% にするのは難しい
● 外部リソースアクセス
● 標準 API の例外
– カバレッジでなく、 assert にこだわりましょう
– SQL のカバレッジは取れない
● SQL でがんばっている箇所があれば、データパターンを増やし
てテストもがんばる!
● バグが発生したら
– 再現するテストケースを書いて、そこから修正
– 抜けてた観点をチーム、組織で共有できれば尚良し
● 単体テストはあくまでもメソッドとしての振る舞い
– 結合テスト、システムテストが不要な訳ではない