Top Banner
1 JJUG-CCC 2016 Spring #ccc_e4
93

テストゼロからイチに進むための戦略と戦術

Apr 16, 2017

Download

Technology

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: テストゼロからイチに進むための戦略と戦術

1

JJUG-CCC 2016 Spring #ccc_e4

Page 2: テストゼロからイチに進むための戦略と戦術

2ストップウォッチ スタート確認

プロローグ

Page 3: テストゼロからイチに進むための戦略と戦術

3

● 渡辺 祐● (株)ビズリーチ

● ビズリーチ

エンジニアブログ

○ http://tech.dcube.io ● Twitter: @nabedge● https://github.com/nabedge● http://www.slideshare.net/nabedge● http://mixer2.org● http://nabedge.mixer2.org

Page 4: テストゼロからイチに進むための戦略と戦術

4

同僚の島本さんによるセッションもどうぞ

「ビッグデータじゃなくても使える Spark☆Streaming」

AB-6 17:00~17:50

Page 5: テストゼロからイチに進むための戦略と戦術

今日の話には前フリがありまして

5http://www.slideshare.net/sogdice/java8jjug-ccc-2015-fall

Page 6: テストゼロからイチに進むための戦略と戦術

6

Page 7: テストゼロからイチに進むための戦略と戦術

7

Page 8: テストゼロからイチに進むための戦略と戦術

8

全力で地雷原を駆け抜けたら、

海が広がっていた。

ただしテストコードは無い。

繰り返す。テストは無かった。

Page 9: テストゼロからイチに進むための戦略と戦術

9

綺麗な海をテストで守ってくれる人を We are HIRING !

http://www.bizreach.co.jp/recruit/

Page 10: テストゼロからイチに進むための戦略と戦術

テストゼロからイチに進むための戦略と戦術

10

JJUG-CCC 2016 Spring #ccc_e4

Page 11: テストゼロからイチに進むための戦略と戦術

タイトルはあのお方より拝借

11

Page 12: テストゼロからイチに進むための戦略と戦術

▸ 今日話さないこと

▹ TDD, テストファースト

▹ C0, C1, C2▹ カバレッジ50%超えたらその後どうする?

▹ 例外処理のテストとか

▸ 話すこと

▹ 何を準備すべきか、そのコツ

▹ なにから始めるか

▹ その障害はなにか

12

Page 13: テストゼロからイチに進むための戦略と戦術

13

Page 14: テストゼロからイチに進むための戦略と戦術

本に書いてあることを妄信しない。

現実は現実。

ケースバイケースでいいとこ取り。

14

Page 15: テストゼロからイチに進むための戦略と戦術

業界によっても話は違う

▸ 受託開発 (SIer)▸ 業務パッケージ開発▸ 組み込み系▸ Webサービス

15

Page 16: テストゼロからイチに進むための戦略と戦術

一手ずつ指すしかない

16Yet Another 式年遷宮 ...

Page 17: テストゼロからイチに進むための戦略と戦術

一手目

なんらかの道標を

継続的に見られる状態にする

17

Page 18: テストゼロからイチに進むための戦略と戦術

18

1. 自分たちがいまどこにいて

2. あとどのくらいがんばれば

3. あのあたりに行けるかもね。

4. これをチーム全員が

見れるようにする

Page 19: テストゼロからイチに進むための戦略と戦術

19

SonarQube 一択

Page 20: テストゼロからイチに進むための戦略と戦術

20

mvn clean jacoco-prepare-agent test sonar:sonar

Page 21: テストゼロからイチに進むための戦略と戦術

21

これでメトリクスの推移を見れる!!

Page 22: テストゼロからイチに進むための戦略と戦術

22

実は、ここまでたどり着くのはそう簡単ではない。

Page 23: テストゼロからイチに進むための戦略と戦術

23

Jenkins上でテストがまともに動くようにするためには

テストクラス 本体クラス

初期データ投入済みのキレイなデータ層(orモック)

外部APIサービス(orそのモック)

Page 24: テストゼロからイチに進むための戦略と戦術

24

少し話が飛ぶ(...かのように見えます)

Page 25: テストゼロからイチに進むための戦略と戦術

25

ローカル開発環境の構築作業

1. git clone2. vagrant up でOracleVBoxに仮想OSを起動し、

RDB, 検索エンジン等をインストール

3. DBFluteのreplace-schemaでテーブル構築&初期データINSERT

4. バッチスクリプトで検索エンジンにデータ投入

5. Mavenプロジェクトとして

IDE(Eclipse/IntelliJ)にインポート

6. ServerStarter.javaを起動

Page 26: テストゼロからイチに進むための戦略と戦術

26

Jenkins上でのmvn test

1. git clone2. vagrant up で別EC2インスタンスを起動し

RDB, 検索エンジン等をインストール

3. DBFluteのreplace-schemaでテーブル構築&初期データINSERT

4. バッチスクリプトで検索エンジンにデータ投入

5. mvn jacoco-prepare-agent test sonar:sonar6. vagrant destroy (インスタンスは使い捨て)

Page 27: テストゼロからイチに進むための戦略と戦術

27

ポイント

1. ローカル開発環境のデータ層を、

仮想OSもろともvagrant upの一撃で作れるようにしてある。a. 初期データ投入も自動スクリプトあり。

2. ならばそれをテスト自動実行の

環境(Jenkins)にも使えばいい。a. 環境差分は仮想OSのIPアドレスくらい

Page 28: テストゼロからイチに進むための戦略と戦術

28

実際、さらに話が飛びますが

Page 29: テストゼロからイチに進むための戦略と戦術

29

テスト「だけ」が開発じゃない

1. 機能の追加、変更、廃止

2. バグの対応

3. インフラ、フレームワークの

メンテ

4. セキュリティ的な対応

5. 新人育成、新メンバーの

立ち上がりサポート

全体をテストで支える

Page 30: テストゼロからイチに進むための戦略と戦術

30

テストの自動化以外のシチュエーションでも使える手法やツールをチョイスすることで、一石二鳥を狙うべき。

Page 31: テストゼロからイチに進むための戦略と戦術

31

将来構想(の一部)

▸ ローカル開発環境

▸ 結合テスト環境

▸ 社内β環境

▸ 本番環境

すべてDockerコンテナ化

インフラ用ansibleをローカル環境でも使えたら!?

Page 32: テストゼロからイチに進むための戦略と戦術

32

詳しくは「12−factor App」「開発 本番 一致」

でググる。

Page 33: テストゼロからイチに進むための戦略と戦術

33

話をテストに戻します。

Page 34: テストゼロからイチに進むための戦略と戦術

34

テストのカバレッジってなんぞ?

緑=テストが通過している

赤=テストが通過してない

黄色=テストが一部だけ通過

このクラスに対するカバレッジは67%

➗ コード全体テストが通過した箇所

Page 35: テストゼロからイチに進むための戦略と戦術

35

本体コード 116 KStepテストコード 91,577 KStep本体に対して 787倍のテスト

もちろんカバレッジ100%

Page 36: テストゼロからイチに進むための戦略と戦術

36

オライリー本「実践JUnit」より

▸ 14.4.1 望ましいカバレッジの値

▹ 「EclEmmaの開発者も含むほとんどの人々は、

70%以下のカバレッジは不十分だと...」▸ 14.4.3 カバレッジの意義

▹ カバレッジの値は単体ではほとんど意味がありま

せん。重要なのは、値の増減の傾向です。カバ

レッジの値を落とすことなく、徐々に上昇させてゆ

くことを目指しましょう。

Page 37: テストゼロからイチに進むための戦略と戦術

37

ちょっと休憩

1. 水を飲む2. 時間を確認(15~20分くらい?)

Page 38: テストゼロからイチに進むための戦略と戦術

二手目

便利プラグインやライブラリは

積極的に導入する

38

Page 39: テストゼロからイチに進むための戦略と戦術

39

hamcrestのmatcherも悪くはないんだけど

assertThat("hoge", is("hoge"));

assertThat("hoge", is(not("HOGE")));

assertThat("not null", is(notNullValue()));

Page 40: テストゼロからイチに進むための戦略と戦術

40

AssertJが便利!

import static org.assertj.core.api.Assertions.*;

assertThat("hoge").isEqualTo("hoge");

assertThat("hoge").startsWith("h").endswith("e")

assertThat("not null").isNotNull();

Page 41: テストゼロからイチに進むための戦略と戦術

41

IDEをメンテしよう

▸ EclEmma

▹ 手元のeclipseでカバレッジを見る

▸ Quick JUnit

▹ テストクラスとテスト対象クラスを行き来する

▹ ただしEclipse-luna/marsでは一部メニューが

動かない!

▸ IntelliJ IDEAなら上の機能はだいたいデフォルト搭載。

Page 42: テストゼロからイチに進むための戦略と戦術

三手目

ゴミ掃除で分母を減らす

42

Page 43: テストゼロからイチに進むための戦略と戦術

43

レガシーコード改善ガイド16.4 「使用していないコードを削除する」

▸ 邪魔以外の何者でもない。

▸ 古いコードが見たければ

VCSから掘り起こせ。

Page 44: テストゼロからイチに進むための戦略と戦術

44

Page 45: テストゼロからイチに進むための戦略と戦術

45

▸ さすがに1.7万行消したら

カバレッジ少し上昇。

▹ 後日加筆の補足:不要に残ったコメントアウトではない(その悪習は

初めから無い)。うっかりコミットしてしまっていた不要な logファイルで

もない。本当に丸ごと未使用のビジネスロジッククラス等だった。

Page 46: テストゼロからイチに進むための戦略と戦術

四手目

ありもののテストデータの

存在を前提としてテストを書く

46

Page 47: テストゼロからイチに進むための戦略と戦術

47

理想: レガシーコード改善ガイド2.1 「単体テストとは」

次にあてはまるものは単体テストではない。

1. データベースとやり取りする

2. (以降 割愛)

上記に該当するテストが悪いというわけではない。 … … (以下、テストが遅くなりがちだからダメという

話)

Page 48: テストゼロからイチに進むための戦略と戦術

48

開発現場の現実

▸ これでは ↓ お話にならない

▹ 「手順書通りにソースをIDEにインポートしてアプリを起動したら、データ

がほとんど入ってないせいで、画面がま

ともに動きません!」

▸ すべての機能を正確に動かせる

初期データを一撃でINSERTする仕組み

は(自動テスト云々に関わらず)必須

Page 49: テストゼロからイチに進むための戦略と戦術

49

▸ DBFluteのreplace-schema機能を使う

1. テーブルを全DROP2. CREATE TABLE …3. *.xlsに用意したデータをINSERT

(日時情報は相対指定可能)

▸ 他のツールでも代替可能

▸ sql-maven-plugin▸ dbunit-maven-plugin▸ Gradle, 自作bashスクリプト

Page 50: テストゼロからイチに進むための戦略と戦術

50

正しいテストデータが常に存在する前提でテストを書いてもよいことにする

@Test

public void test_foo() throws Exception {

User user = userService.find(5L);

Result result = fooService.doBar(user);

assertThat(result)........

会員番号5番のuserはこのテストに必要なデータを全て持っている

Page 51: テストゼロからイチに進むための戦略と戦術

51

ただし基本は勉強したうえで用法用量を守って。

@Test

public void test_foo() throws Exception {

User user = new User();

user.setHoge = ...//テストに必要な値をその都度書く

Result result = fooService.doBar(user);

assertThat(result)........

Page 52: テストゼロからイチに進むための戦略と戦術

五手目

ところで、メールのテスト

どうする?

52

Page 53: テストゼロからイチに進むための戦略と戦術

53

そこそこ面倒

▸ ローカルマシンにpostfixとdovecotを入れる

▸ 共有マシンにpostfixとdovecotを入れる

▸ 開発環境では、SMTPではなく *.eml形式でファイルに出力する

自作モッククラスに差し替える

▸ GreenMail, mock-javamail, subethaSMTP...などのライブラリを使う

Page 54: テストゼロからイチに進むための戦略と戦術

54

● インストール

○ $ gem install mailcatcher● 起動

○ $ mailcatcher● 1025番でSMTP待ち受け

● 1080番でブラウザでメール閲覧

● portは起動引数で書き換え可

Page 55: テストゼロからイチに進むための戦略と戦術

55

メールの情報をjsonで返すAPI

▸ /messages … メッセージ一覧を取得

▸ /messages/:id.json

▸ /messages/:id.html

▸ /messages/:id.plain

▸ /messages/:id.source

Page 56: テストゼロからイチに進むための戦略と戦術

56

mailcatcherをvagrantで自動構築動作チェックと自動テストの両方で使う

▸ vagrant upで”gem install mailcatcher”

▸ アプリケーションの設定値を差し替え

▹ SMTPサーバのIPアドレスとport番号だけ

▸ 開発過程での目視での動作確認用途に使う。

▸ テストコードではmailcatcherのAPIで

取得したjsonをアサートする。

Page 57: テストゼロからイチに進むための戦略と戦術

六手目

Selenium

- E2Eテストでカバレッジも測る

57

Page 58: テストゼロからイチに進むための戦略と戦術

58

Seleniumご存知ですよね

@Test

public void test_トップページ() throws Exception {

WebDriver drv = new FireFoxDriver();

WebElement element = drv.get(“http://localhost:8080/”);

assertThat(element.findById(“title”).getText())

.contains(“Hello World”)}

Page 59: テストゼロからイチに進むための戦略と戦術

59

不安定だし、メンテコスト大きめ

なので、用量用法を守って。

… とは言うものの

Page 60: テストゼロからイチに進むための戦略と戦術

60

絶対防衛ラインの存在

▸ ECサイト

▹ カートに入れる->入力,決済->注文完了メール

▸ ホテル予約サイト

▹ 予約ボタン -> 入力,決済 -> 予約完了メール

▸ 転職サイト

▹ 応募ボタン -> 入力 -> 応募がありましたメール

Page 61: テストゼロからイチに進むための戦略と戦術

61

1. 是非もなく継続的にやりたい結合テストを

Seleniumで書く。

2. 通常のユニットテストと同じ運用で

継続的に実行できるようにする。

3. とにかく必ずやるというのなら、

ついでにカバレッジも取れるようにする。

Page 62: テストゼロからイチに進むための戦略と戦術

62

前提:アプリは組込Tomcatで起動

public class APStarter {

public static start() {

Tomcat tomcat = new Tomcat();

tomcat.start();

...

public static void main(String args[] argv) {

start();

Page 63: テストゼロからイチに進むための戦略と戦術

63

@BeforeClass メソッド

APStarter.start(); // 起動

@Test メソッド

// WebDriverでアプリの画面にアクセス

@AfterClass メソッド

APStarter.close(); // 停止

Page 64: テストゼロからイチに進むための戦略と戦術

JVM

64

テストクラス

テスト対象

Seleniumでもカバレッジ測定

JaCoCo-Agent

Jenkins用マシンのOS

Vagrant仮想OS

1. vagrant up2. 初期データ投入3. Xvfb起動4. mvn

prepare-agent test sonar:sonarHTTP start()

Page 65: テストゼロからイチに進むための戦略と戦術

JVM

65

テストクラス

テスト対象

普通のユニットテストのカバレッジ測定

JaCoCo-Agent

Jenkins用マシンのOS

Vagrant仮想OS

1. vagrant up2. 初期データ投入3. -4. mvn

prepare-agent test sonar:sonar

Page 66: テストゼロからイチに進むための戦略と戦術

66

もしも多種類ブラウザでやるとしたら?

JVMテストクラス

テスト対象JaCoCo-Agent

Jenkins用マシンのOS

Vagrant仮想OS

JVMテストクラス

テスト対象JaCoCo-Agent

Jenkins用マシンのOS

Vagrant仮想OS

JVMテストクラス

テスト対象JaCoCo-Agent

Jenkins用マシンのOS

Vagrant仮想OS

JVMテストクラス

テスト対象JaCoCo-Agent

Jenkins用マシンのOS

Vagrant仮想OS

Page 67: テストゼロからイチに進むための戦略と戦術

67

ちょっと休憩

1. 水を飲む2. 時間を確認(35分くらい?)

Page 68: テストゼロからイチに進むための戦略と戦術

68

七手目Jenkins上でのテストの定期ジョブ実行を止めたくなる自分自身との戦い

Page 69: テストゼロからイチに進むための戦略と戦術

69

事件発生

▸ Jenkinsがチャットルームに

「テストが失敗しました...」をつぶやく

▸ あれっ?と思ってローカル環境で

テストを実行すると全て成功する

Page 70: テストゼロからイチに進むための戦略と戦術

70

ログを追うにも

● 実際には200MByte前後。

● log4j.properties / logback.xml を

長い間 整理していないツケ

Page 71: テストゼロからイチに進むための戦略と戦術

71

▸ 手元では再現しない。

▹ AWS(EC2)でしか発生しない。

▸ たまにしか発生しない。

▸ Jenkinsがオオカミ少年化するのが

嫌だからチャットへの投稿botを停止。

▸ 忙しくてしばらく停止しっぱなし

▸ 本当にバグってテストが失敗してても

誰も気づいてない。

Page 72: テストゼロからイチに進むための戦略と戦術

72

巨大ログをよくよく目grepすると

==> default: Existing lock /var/run/yum.pid: another copy is running as pid 3744.==> default: Another app is currently holding the yum lock; waiting for it to exit...==> default: The other application is: yum

● テストではなくvagrant の段階 !● yum install hogehoge でコケている。● 他のyumが動いている??

Page 73: テストゼロからイチに進むための戦略と戦術

73

vagrant up

AMI起動 (vagrant-aws-plugin)

yum update ... 他のOS起動シーケンス

sshデーモン開始

vagrant provision

yum install hogehoge

yum lock

微妙に時間がかかることがある

テスト実行ジョブスタート

Page 74: テストゼロからイチに進むための戦略と戦術

74

▸ テスト用EC2インスタンスを使い捨て

しているからこそ発生する事象。

▸ つまらない原因でCIサーバでのテストが

事実上止まってしまうことはありうる。

▸ わずらわしさに負けたらそこで

試合終了。

Page 75: テストゼロからイチに進むための戦略と戦術

75

八手目

教育、啓蒙

Page 76: テストゼロからイチに進むための戦略と戦術

76

▸ 幸いなことに

▹ 否定的な感覚のメンバーは皆無

▹ テスト書かないと気持ち悪いという者も。

▸ いずれにせよスキルにバラつきはある。

▹ テストを書き慣れることが必要

Page 77: テストゼロからイチに進むための戦略と戦術

77

テストを書くタイミングだけは守ろう

1. バグ対応のときは必ずテストを書く

2. クラスの中の一部のメソッドを

修正または追加した場合は、

そのメソッドに対するテストだけでも書く。

3. そのために private -> protected に変更するのはOK

※他にもいろいろあるけど上記はその一例です

Page 78: テストゼロからイチに進むための戦略と戦術

78

九手目

金の弾丸

Page 79: テストゼロからイチに進むための戦略と戦術

79

富豪テストを支える基本環境

Mac Book Pro3GHz Core i716GB memory250GB SSD

Jet BrainsAll Products Pack

Page 80: テストゼロからイチに進むための戦略と戦術

80

まとめ

● 時間を確認

Page 81: テストゼロからイチに進むための戦略と戦術

81

1. テストが無いコードはレガシーコードだ!

2. テストを書こう。

3. しかし現実の開発現場は、

それがすべてではない。

Page 82: テストゼロからイチに進むための戦略と戦術

82

1. 自分の手元の開発環境で、アプリの実行に必

要なミドルウェア群を

一撃でインストールする仕組み

(not 手順書)

2. すべての機能を正確に動かせる

初期データを一撃でINSERTする仕組み

テスト書くのとは無関係に必須

Page 83: テストゼロからイチに進むための戦略と戦術

83

ならばそれらの自動化ツールをテストの実行にも活かして手間を省く

1. vagrant/dockerでデータ層を作る

2. DBFluteのreplace-schemaでテストデータ投入

3. あるいは

a. sql-maven-pluginb. dbunit-maven-pluginc. gradle関連でももちろんOK

Page 84: テストゼロからイチに進むための戦略と戦術

84

IDE(のplugin)依存は避ける

1. それJenkins上で動かせるの?

2. QuickJUnitがEclipse luna以降では...

3. WTP, Sysdeo, RunJettyRunよりも

組み込みtomcatでアプリコード化

Page 85: テストゼロからイチに進むための戦略と戦術

85

道標はあるほうがいい

▸ なにを、どこまでがんばれば、

どうなりそうか?

▹ ステップ数

▹ テストカバレッジ

▹ テストの成功、失敗、スキップ

▹ 重複ステップ数

▸ 上記すべての過去の値との比較

Page 86: テストゼロからイチに進むための戦略と戦術

86

便利ライブラリは積極的に導入

▸ Javaライブラリ

▹ AssertJ▹ “J”Mockito

▸ Javaライブラリ以外の方法もある

▹ mailcatcher

Page 87: テストゼロからイチに進むための戦略と戦術

87

言語やフレームワークは最新ですか?

▸ If文の分岐網羅を気にするよりも

Java8 の Stream API で書き直して

見通しを良くする方が建設的。

▸ Spring-testフレームワーク便利!

▹ ただしspring4.2以上

Page 88: テストゼロからイチに進むための戦略と戦術

88

ゴミ掃除をしよう

▸ もう使われていないコードのテストを

がんばって書く悪夢

▸ Log4j.properties, pom.xml を

メンテする。

▹ 不要なログ、無駄な依存関係は

トラブルシューティングの邪魔

Page 89: テストゼロからイチに進むための戦略と戦術

89

Seleniumは用法用量を守って

▸ 絶対防衛ラインで使う

▸ やり方次第でカバレッジも採れる

▸ テスト実行環境の自動構築を徹底すれば、

富豪テスティングなやり方も可能。

▹ スポットインスタンス安っ!

Page 90: テストゼロからイチに進むための戦略と戦術

90

▸ テストの原則は

▹ 繰り返し可能である

▹ 独立している

▸ これを↑実行環境レベルの自動化で

実現する方法「も」ある

▸ ただし実行スピードが犠牲に

なりやすい。考えて使いわける。

基本は基本で知っておこう

Page 91: テストゼロからイチに進むための戦略と戦術

91

▸ 気をつけていても、思わぬ落とし穴で

テストが不安定になって

心が折れそうになることがある。

負けないこと。

Page 92: テストゼロからイチに進むための戦略と戦術

92

テストの旅は続く

エンジニア募集!

https://www.bizreach.co.jp/recruit/

Page 93: テストゼロからイチに進むための戦略と戦術

テストゼロからイチに進むための戦略と戦術

93

To be continued...