Slide 1

Slide 1 text

JSTDD Intro for EVERY JavaScripters 〜 4周⽬のTDDを始めよう 〜

Slide 2

Slide 2 text

kanazawa.js v1.7 @wtnabe ⾦沢歌劇座 2012-03-31

Slide 3

Slide 3 text

Self-Introduction

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Webの開発とシステム管理全般 Ruby, JavaScript, PHP kanazawa.js Certified Ruby Programmer Gold

Slide 6

Slide 6 text

JavaScriptの専⾨家 TDDの専⾨家

Slide 7

Slide 7 text

つまり皆さんと同じです

Slide 8

Slide 8 text

ちょっと違うこと 以下は少なめ F5押して ⽬を凝らす

Slide 9

Slide 9 text

今⽇はそのためのお話 何を知り 何を準備し ⽇々どうしていくか

Slide 10

Slide 10 text

私とTDD 課題 2002年 XP, テストファーストを知る 2003年 リファクタリングしたい テストないじゃん 設計上⼿になりたい クソコードを紡ぐ不安

Slide 11

Slide 11 text

私とTDD テスト 2005年 Ruby, PHP でユニットテスト開始 2006年 JavaScriptでユニットテスト開始 WSH + JScript + jsUnit

Slide 12

Slide 12 text

私とTDD インターフェイス 2007年 『アジャイルプラクティス』 「変更に強いコードとうまい設計を⽬ 指す覚え書き」 - あーありがち 2008年 『インターフェイス指向設計』 『RESTful Webサービス』

Slide 13

Slide 13 text

私とTDD ⾃動化 2009年 『Release It !』 Rake, Capistrano プロセス監視

Slide 14

Slide 14 text

私とTDD ⽂化 2010年 3⽉ TDDBC北陸 9⽉ 『レガシーコード改善ガイド』 12⽉ kanazawa.js v0.0.1 2011年 Rails 3 で TDD

Slide 15

Slide 15 text

私とTDD 2012年3⽉ kanazawa.js v1.7 ← イマココ

Slide 16

Slide 16 text

まとめると

Slide 17

Slide 17 text

設計は難しい http://www.flickr.com/photos/mrbill/3267227227/

Slide 18

Slide 18 text

⽬の前にはスパゲッティ http://www.flickr.com/photos/katiejean97/6966583763/

Slide 19

Slide 19 text

不安

Slide 20

Slide 20 text

http://www.flickr.com/photos/cauchipics/4444456369/ TDDを始めて

Slide 21

Slide 21 text

とってもハッピー ※ 不適切な画像は削除されました

Slide 22

Slide 22 text

以上、⾃⼰紹介おわり

Slide 23

Slide 23 text

本⽇のお品書き TDDってなに? テスティングフレームワークと関連知識 やってみよう JavaScript TDDの課題 TDDの始め⽅(スピリチュアル注意)

Slide 24

Slide 24 text

本⽇のターゲット とりあえずJavaScript書いて動かせる⼈ TDD始めたい⼈

Slide 25

Slide 25 text

覚えてほしいこと Red / Green / Refactoring Firebugだけではつらい ⾃動テストで安⼼を⼿に⼊れよう

Slide 26

Slide 26 text

What is TDDってなに?

Slide 27

Slide 27 text

だいぶ乱暴な説明

Slide 28

Slide 28 text

テスト駆動開発 Test-Driven Development テスト - テストコードの実⾏によって 駆動 - 頑張りやすくする 開発 - 開発⼿法

Slide 29

Slide 29 text

テストコード? プログラムをテストするプログラム

Slide 30

Slide 30 text

プログラムをテストするプログラム?

Slide 31

Slide 31 text

こんな感じ function isOdd( num ) { return num % 2; } function testIsOdd() { console.log(true === isOdd( 3 )); console.log(false === isOdd( 2 )); } testIsOdd();

Slide 32

Slide 32 text

実⾏結果 $ node /path/to/test_code.js true true

Slide 33

Slide 33 text

あとでもうちょっと詳しく

Slide 34

Slide 34 text

詳しい⼈向けの諸注意 TDDのテストは開発者が⾃らのために⾏ うテストです TDDはあくまでDevelopmentであっ てTestではありません

Slide 35

Slide 35 text

どうしてプログラムで テストするの?

Slide 36

Slide 36 text

Firebugじゃダメなの?

Slide 37

Slide 37 text

Firebugじゃダメなの? 「確認」のくり返し 正確さ? 変更 → 全部やり直し ⾒ていないところは?

Slide 38

Slide 38 text

Firebugはダメじゃない Firebugだけでやるのは⼤変

Slide 39

Slide 39 text

コンピュータは 疲れを知らず 同じことを正確に 延々くり返せる

Slide 40

Slide 40 text

だからテストコード

Slide 41

Slide 41 text

では次に

Slide 42

Slide 42 text

得られるメリット 現場で困っていそうなこと

Slide 43

Slide 43 text

困っていませんか? console.log(), var_dump(), p, ... 間違ってそのままcommit/deploy

Slide 44

Slide 44 text

困っていませんか? デザイン vs Viewのコード システム vs DOMのロード

Slide 45

Slide 45 text

困っていませんか? ライブラリのバージョンアップ 機能追加 気づかないところが壊れてた

Slide 46

Slide 46 text

困っていませんか? 以前作ったコード 仕様書 vs 実際の動作 何が正しいのか?

Slide 47

Slide 47 text

TDDでこうした課題に⽴ち 向かいやすくなります

Slide 48

Slide 48 text

その理由は? 開発の進め⽅が違います

Slide 49

Slide 49 text

これまでの開発⼿法(1) コードを書き倒す 祈る (-⼈"- ; ウゴケ! 実⾏ orz

Slide 50

Slide 50 text

これまでの開発⼿法(2) 実装が済んでからまとめてテスト テストは基本的に⼿動

Slide 51

Slide 51 text

これまでの開発⼿法の問題 デバッグは祈りと⽬⼒ ⽬⼒頼み テスト開始が遅い 遅い → バグや仕様漏れの発⾒も遅い 遅い テストは疲れる 疲れる

Slide 52

Slide 52 text

後半しんどすぎる

Slide 53

Slide 53 text

TDDによる開発の流れ プログラムをテストする⼩さなコード 実⾏ → 失敗 成功するまでプログラムを直す 以上を⼩さく素早くくり返す

Slide 54

Slide 54 text

TDDで問題を解決 ⼿動テストのくり返しで疲れる → ⾃動化 ⾃動化 テストを始めるのが遅い → テストファースト テストファースト 「待ち時間」 → インターフェイスを決めて並⾏作業 インターフェイスを決めて並⾏作業

Slide 55

Slide 55 text

もう⼀度コードを⾒てみる

Slide 56

Slide 56 text

プログラムをテストするプログラム function isOdd( num ) { return num % 2; } function testIsOdd() { console.log(true === isOdd( 3 )); console.log(false === isOdd( 2 )); } testIsOdd();

Slide 57

Slide 57 text

こんなコード公開する? プロダクトコードとテストコード混在 JavaScriptの容量増加 テストに⽤意するデータ丸⾒え

Slide 58

Slide 58 text

無理でしょ

Slide 59

Slide 59 text

そこでフレームワークですよ!

Slide 60

Slide 60 text

Testing Frameworks and knowledge around there テスティングフレームワークと関連知識

Slide 61

Slide 61 text

フレームワークってなに? テストの記述 テストの実⾏

Slide 62

Slide 62 text

頻出ワード 実⾏環境 ブラウザなど組み込み / node.jsなど 種類 ユニット / インテグレーション スタイル xUnit / BDD

Slide 63

Slide 63 text

今回は 実⾏環境 ブラウザ ブラウザなど組み込み / node.jsなど 種類 ユニット ユニット / インテグレーション スタイル xUnit / BDD

Slide 64

Slide 64 text

今回は ブラウザ ユニットテスト

Slide 65

Slide 65 text

ユニットテスト 主にメソッドやクラス単位で⾏うテスト

Slide 66

Slide 66 text

メソッド function method() { ... }

Slide 67

Slide 67 text

クラス function klass() { ... }

Slide 68

Slide 68 text

おんなじだ!

Slide 69

Slide 69 text

JavaScriptでは functionに対するテストと 思っていいです

Slide 70

Slide 70 text

なぜユニットテスト? JavaScriptだけで話が完結する すぐにでも始められる ← 重要 cf. JavaScriptのテスト事情-ダイジェスト版- 2011年10⽉13⽇

Slide 71

Slide 71 text

どんなものがあるの? Jasmine ( 44% ) QUnit ( 41% ) via http://dailyjs.com/files/DailyJSSurvey2011.pdf ※ 複数回答なので合計は100%以上

Slide 72

Slide 72 text

今回はQUnit

Slide 73

Slide 73 text

QUnitの理由 準備が少ない  記述が少ない つまりコードをスライドに載せやすい ※ 実務ではまた別な理由があると思います。

Slide 74

Slide 74 text

というわけで ブラウザで QUnitを使って ユニットテスト

Slide 75

Slide 75 text

Try it ! やってみよう

Slide 76

Slide 76 text

最速QUnit解説

Slide 77

Slide 77 text

HTMLを⽤意 qunit.jsとqunit.cssを読み込む

Slide 78

Slide 78 text

QUnit example

    test markup, will

    Slide 79

    Slide 79 text

    プロダクトコードとテストコードも⾜す ...

    Slide 80

    Slide 80 text

    ファイルの状態 . ├── index.html ├── product.js <- プロダクトコード ├── qunit.css ├── qunit.js └── test_product.js <- テストコード

    Slide 81

    Slide 81 text

    テストの書き⽅ test('テストの名前', function() { ... });

    Slide 82

    Slide 82 text

    今⽇使うAssertion ok( 確認したいコード ); equal( 確認したいコード, 期待する値 );

    Slide 83

    Slide 83 text

    これだけ

    Slide 84

    Slide 84 text

    組み合わせるとこう test('isOdd', function() { ok( isOdd(3) ); });

    Slide 85

    Slide 85 text

    さて

    Slide 86

    Slide 86 text

    サンプルを⽤意しました a) 奇数判定 b) ⽇付の整形

    Slide 87

    Slide 87 text

    a) 奇数判定 確認したいこと TDDの教科書的な流れ

    Slide 88

    Slide 88 text

    a) 奇数判定 設計 奇数を与えたら true が返ってくる 偶数を与えたら false が返ってくる

    Slide 89

    Slide 89 text

    TDDの教科書的な流れ Fail it - まず失敗 - Red Fake it - 仮実装 - Green 三⾓測量 & Refactoring

    Slide 90

    Slide 90 text

    No content

    Slide 91

    Slide 91 text

    by @t_wada 何かに似てる

    Slide 92

    Slide 92 text

    Diagram by Karn G. Bulsuk

    Slide 93

    Slide 93 text

    ⼩さく進める 間違った⽅向に進んでないことを確認 するためにわざと間違える すぐにチェック(テスト)して フィードバックを次のサイクルに

    Slide 94

    Slide 94 text

    Fail it 1 プロダクトコードのないテスト test('isOdd', function() { ok( isOdd(3) ); });

    Slide 95

    Slide 95 text

    No content

    Slide 96

    Slide 96 text

    No content

    Slide 97

    Slide 97 text

    Fake it 1 内容のないプロダクトコード function isOdd( num ) { return true; } test('isOdd', function() { ok( isOdd(3) ); });

    Slide 98

    Slide 98 text

    No content

    Slide 99

    Slide 99 text

    Fail it 2 通らないテストパターン function isOdd( num ) { return true; } test('isOdd', function() { ok( isOdd(3) ); ok( !isOdd(2) ); // new ! });

    Slide 100

    Slide 100 text

    No content

    Slide 101

    Slide 101 text

    Fake it 2 Fail 回避 function isOdd( num ) { if ( num == 3 ) { return true; } else if ( num == 2 ) { return false; } } test('isOdd', function() { ok( isOdd(3) ); ok( !isOdd(2) ); // new ! });

    Slide 102

    Slide 102 text

    No content

    Slide 103

    Slide 103 text

    Refactoring 異なる⽅向からの2つ以上のテスト これらを元にゴールをより正確に計る これが三⾓測量 三⾓測量できたらリファクタリング

    Slide 104

    Slide 104 text

    つまり今がチャンス! function isOdd( num ) { return num % 2; // Refactoring } test('isOdd', function() { ok( isOdd(3) ); ok( !isOdd(2) ); });

    Slide 105

    Slide 105 text

    もう⼀度おさらい Fail it - まず失敗 - Red Fake it - 仮実装 - Green 三⾓測量 & Refactoring

    Slide 106

    Slide 106 text

    テストコードは設計を表す test('isOdd', function() { ok( isOdd(3) ); ok( !isOdd(2) ); });

    Slide 107

    Slide 107 text

    サンプル a) 奇数判定 b) ⽇付の整形 ⽇付の整形

    Slide 108

    Slide 108 text

    b) ⽇付の整形 確認したいこと 変化するものはひとまず固定してテスト 設計のbreak downが⼤事 設計 Date → 「YYYY/MM/DD」な⽂字列

    Slide 109

    Slide 109 text

    Fail it test('formatDate', function() { equal('2012/02/14', formatDate(new Date('Tue Feb 14 2012 1 });

    Slide 110

    Slide 110 text

    ちょっと確認したいことが function formatDate( date ) { return [date.getFullYear(), date.getMonth() + 1, date.getDate()].join('/'); }

    Slide 111

    Slide 111 text

    Failed Expected: "2012/2/14" Result: "2012/02/14" Diff: "2012/2/14" "2012/02/14" // あ

    Slide 112

    Slide 112 text

    Dateのメソッドは 桁数が合わない場合も

    Slide 113

    Slide 113 text

    設計やり直し メソッドを分割する Date -> YYYY/MM/DD 数字の桁数を2桁に正規化する 2 -> 02 sprintfやstrftimeがあれば…。

    Slide 114

    Slide 114 text

    さらに設計 数字の2桁への正規化? 2 -> 02 12 -> 12 110 -> ? 2012 -> ?

    Slide 115

    Slide 115 text

    さらに設計 今回は⽇付の処理に特化 ⽉、⽇に3桁以上の数字はあり得ない 整数以外もあり得ない

    Slide 116

    Slide 116 text

    Fail it test('padZero', function() { equal('02', padZero(2)); });

    Slide 117

    Slide 117 text

    端折って本実装 function padZero( num ) { return '0' + num; }

    Slide 118

    Slide 118 text

    Fail it 2 test('padZero', function() { equal('02', padZero(2)); equal('12', padZero(12)); // new });

    Slide 119

    Slide 119 text

    頑張る function padZero( num ) { var str = num.toString(); if ( str.length < 2 ) { return ('0' + str); } else { return str; } }

    Slide 120

    Slide 120 text

    Refactoring function padZero( num ) { var str = '0' + num; return str.substr(str.length - 2, 2); }

    Slide 121

    Slide 121 text

    完成テストコード test('formatDate', function() { equal('2012/02/14', formatDate(new Date('Tue Feb 14 2012 1 }); test('padZero', function() { equal('02', padZero(2)); equal('12', padZero(12)); });

    Slide 122

    Slide 122 text

    完成プロダクトコード function formatDate( date ) { return [date.getFullYear(), padZero(date.getMonth() + 1), padZero(date.getDate())].join('/'); } function padZero( num ) { var str = '0' + num; return str.substr(str.length - 2, 2); }

    Slide 123

    Slide 123 text

    ⽇付の整形のまとめ 「今」はテストしにくいので固定 設計重要 / 場合分け重要 TDDそのものとは異なる経験も⼤事

    Slide 124

    Slide 124 text

    Promblems of JavaScript TDD JavaScript TDDの課題

    Slide 125

    Slide 125 text

    できないこと ⾒た⽬の雰囲気 効果の雰囲気 ※ レイアウトはすごく頑張れば可能

    Slide 126

    Slide 126 text

    ⼯夫すればできること 処理が複雑 頑張って分ける 頑張って分ける

    Slide 127

    Slide 127 text

    ⼯夫すればできること まとめて読み込むと動かない 名前空間を分ける どうしてもダメな部分はHTMLに直接 適切な分割には経験が必要です。

    Slide 128

    Slide 128 text

    名前空間 var Namespace = { ... } HTML ...

    Slide 129

    Slide 129 text

    ⼯夫すればできること DOM操作ばかりで結局⽬視 要素の有無や数を数えることは可能 ※ 不安がなければテスト不要

    Slide 130

    Slide 130 text

    ⼯夫すればできること 無名関数ばかり できるだけ名前を付けよう 即時実⾏無名関数だらけ できるだけ避ける。中⾝は⼩さく。

    Slide 131

    Slide 131 text

    無名関数 func1( function() { ... }); 名前付き func1( function() { func2(); }) function func2() { }

    Slide 132

    Slide 132 text

    (function() { ... })(); 中⾝をちゃんと外に (function() { func1(); })(); function func1() { }

    Slide 133

    Slide 133 text

    諦めも肝⼼ 根本的に不可能なテストや現時点で無理 なテストはある 別な⽅法を考えよう

    Slide 134

    Slide 134 text

    How to Start TDDの始め⽅

    Slide 135

    Slide 135 text

    できることからやる TDDは⼩さなくり返し その導⼊が最初から完璧だなんて不⾃然 まずは現状の「困った」を⼀つでも解決

    Slide 136

    Slide 136 text

    できる⼈を探そう 分かってそうな⼈、頑張ったら分かりそ うな⼈に⽚っ端から声を掛けよう

    Slide 137

    Slide 137 text

    うまくいかないかも お前は最初から⼀⼈で⾃転⾞に乗れたのか?

    Slide 138

    Slide 138 text

    はじめよう

    Slide 139

    Slide 139 text

    例え失敗しても 今動いているコードは なくならない

    Slide 140

    Slide 140 text

    今やり直せよ。未来を。 詠み⼈知らず

    Slide 141

    Slide 141 text

    もう⼀つ

    Slide 142

    Slide 142 text

    TDDがすべてではない 我々の⽬的は何か? より良いプロダクトで顧客、ユーザーに より⾼い価値を届けること

    Slide 143

    Slide 143 text

    そのためにやれることを やるだけ

    Slide 144

    Slide 144 text

    TDDは⼤事な⼿段の⼀つ

    Slide 145

    Slide 145 text

    最後にもう⼀度

    Slide 146

    Slide 146 text

    覚えてほしいこと Red / Green / Refactoring Firebugだけではつらい ⾃動テストで安⼼を⼿に⼊れよう

    Slide 147

    Slide 147 text

    Any Questions ? Thanks to developers of testing frameworks, TDD evangelists and prcatitioners and panelists And You