java web application testing
TRANSCRIPT
Java Web アプリケーションのテスティングの話
JJUG CCC 2015 Spring tokuhirom
初心者向けっちゃ 初心者向け
コミュニティイベントなので コミュニティからのフィード
バック重視
答えを提供するよりは 議論の元を提供する感じで
自己紹介
自己紹介なんて 不要だと思うかもしれません
が。。
業種の前提が無いと、 聞いても無意味
自社サービスの ウェブアプリケーション
の開発
一昨年まで Perl 書いてたけど去年から Java
Native App 用の API サーバー等が主
Form Webapp
multipart/form-data application/x-www-form-urlencoded
HTML
従来手法
iPhone App Webapp
Android App
AngularJS App
JSON
JSON
近年のアプリ
開発手法の話
Agile
それをAgileと呼ぶならそれはAgileなのだろう
開発の手順
Server
Spec
Client
QA
Iterative
1.2
1.1
2.0
2.1
開発に利用している コンポーネント
Apache Tomcat MySQLJava8
普通だ!
自己紹介終わり。
本編です
質問は随時叫ぶなり手をあげるなりしてください。
原則
手動テスト最高ですね!!
(CENSORED)
ネイティブアプリ等は 機種ごとの差異なども
あるので 最終的には必要
どこまで自動化するか
手動でやるよりも 自動でやったほうが 楽になりそうだな~って ところまでやる。
ここ、テスト書いておかないと後で壊れそうだな
というところを、「契約」として
書いておく
Web Application でのテスト、どのレイヤでやるか。
どこまでスタブにするか
近代的WebApp
Browser Controller Model RDBMS
外部API
どこのレイヤでテストする?
Model のテストを手厚くやろう。
どうやる?
悩みどころ
Q. RDBMSまわりの テスト、どうやるか?
A. RDBMSとのつきあいかたによる
深い付き合い
浅い付き合い
1. RDBMS を絞り尽くしたい派
SQLをゴリゴリ 書きたい
2. JPA にすべてを委ねるよって人
JPAがRDBMSの差異を吸収してくれる。。
はず
RDBMS に依存しない 実装を求める
H2 でテストするぞ!!!
僕の場合
1 です。
JPA は使わないので。。
(CENSORED)
SQL書きたいよ?
一番テストしたいのは RDBMS とのつなぎ込み部分
RT 鍵: WEB+DB システムとは SQL と入出力仕様だ
というわけで、MySQLを利用したテストの仕方をご紹介し
ます。
よ~し、パパ MySQL を maven から 起動しちゃうぞ~
(CENSORED)
local に立ってる MySQL 使ってこ
CREATE DATABASE proj_test_deadbeef;
プロジェクト名 ランダム生成文字列
スキーマのSQLを流し込む!!!
for (SHOW TABLES) { DELETE FROM $_; }
@Before
マスターデータをINSERTする
自動生成したDBへの接続情報は DI かなにかでがんばって
設定しよう!!
DB のテストに関する 知見は以上になります。
休憩
外部APIのテスト
ところで、最近話題の microservices
SOA でもなんでもいいですが……
僕の周りでは10年ぐらい前 疎結合ウェブアプリケーション
と呼んでました。
コンポーネントを 細かい httpd に分けて HTTP で通信してこ↑
メリット: 分業しやすい
変更の影響範囲が明確
弊社でも、 バズワードが出る前から 実践されております。
(CENSORED)
しかし、 テストがやや やりにくい。
どうするか?
クライアントライブラリを DI で置き換える?
速い。
テスト範囲が狭くなって良くない面がある。
結合テストを別途行うならいいけど。。
httpd を起動して モックサーバーを実行する
Embedded Jetty
servlettester-jetty github.com/tokuhirom/
servlettester-jetty
JettyServletTester.runServlet((req, resp) -> { resp.getWriter().print("Hey"); }, (uri) -> { try (CloseableHttpClient client = HttpClientBuilder.create() .build()) { HttpGet request = new HttpGet(uri); try (CloseableHttpResponse resp = client.execute(request)) { String body = EntityUtils.toString(resp.getEntity(), StandardCharsets.UTF_8); assertEquals("Hey", body); } } });
http://localhost:12800/
httpd あげるの無駄なのでは????
無駄だけど、jetty なら起動速いし気にならない。
DB関連のほうが十分に遅いので。。
実際には、もっとシンプルに。。
apimock https://github.com/tokuhirom/apimock
Sinatra風にサーバー側実装を書ける
@Test public void test() { mockApi(mock -> {
mock.get(“/api/member/detail“,c -> { return ImmutableMap.of(“hoge”, “fuga”);
}); }, () -> {
assertEquals(”fuga}”, injector.get(Client.class).getMember(1)
.getHoge() );
} }
HTTPの通信を細かく書けないと、
Regression Test 書きづらい。
外部 API のテストに関する 知見は以上になります。
休憩
コントローラのテスト
コントローラのテスト、どうやるか
API サーバー のテスト
極めて書きやすい。
httpd をあげて Apache HttpClientでアクセスする。
servlettester-jetty
JettyServletTester.runServlet( new MyServlet(), (uri) -> {
// your test code } );
実際のテストコードでは。。。
ControllerTestBase クラス的なので自動的にサーブレット立ち上げる。
@Test public void test() { http.get(“/api/member/“) .isOK() .contentContains(“hogehoge”);
}
JSON API だったらどうすんの?
@Test public void test() { val req = new Req(“hoge”, “fuga”); Res res = mech2.postJSON(“/api/member/register“, req) .isOK() .parseJSON(Res.class); assertThat(res.getName()) .isEqualTo(“hoge”);
}
@Test public void test() { http.post(“/api/member/create“) .param(“name”, “John”) .isOK() .contentContains(“hogehoge”);
}
HTML のフォームとか……?
あんま真面目にテストしてない。。
人力のテストでカバーできるので。。
HTML 変わりまくるので、自動化テストの手間が 見合わない。
コントローラのテストの話は終わり。
ダミーデータの作成
public class TestBase { @Inject protected Creator create;
}
@Test public void test() { Member member = create.member(); Blog blog = create.blog(member); // …
}
fixture.yml 的なの メンテナンスが面倒
Web 屋さん、 Excel 嫌いな人もいるので。。
ダミーデータ作成の話、 終わり。
テストライブラリ どれがいいのか、という話
junit3 vs junit4
junit4 世代なので、素直に junit4 つかってます
assertThat(actual, is(expected));
読む分にはいいけど、書きづらい。。
assertj を使う
assertThat(actual) .isEqualTo(expected)
補完が効きやすい = IDE Friendly
assertThat(list) .hasSize(5)
開発が活発
assertThat(uri) .hasPath(“/“) .hasPort(80);
先週ぐらいに要望だしたら、だれか実装してた。
ところで、、
Google truth ってどうなの?
dagger2 とか、google 発プロダクトで利用されてる
だいたい assertj と一緒
コードが小難しい assertj のほうが好き
まとめ
• assertj 便利。
Continuous Integration
全体の構成
gh:e jenkinsエンジニア
Nexus Enterprise
Deploy System
ServerServer Server Server
Nexus Enterprise へは jenkins からしか上がらない
テスト通らないコードはリリースできない
CI は誰かがお膳立てしてあげればみんな諦めて使う
Findbugs checkstyle
gh:e から p-r 投げたら テストが自動で回る
CI ないと、テストは ぶっ壊れる
CI 回さないと 自分の書いたコードを
誰かが壊す
CI は基本。
僕のやり方まとめ• DB のテストは実際に DB を使う
• 外部 API のテストは実際に API をコールする
• コントローラのテストはサーブレットコンテナを起動する
• CI を常に回す
おしまい
• (CENSORED)
以上。