Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JSTDD Intro for EVERY JavaScripters @kanazawa.js v1.7 (2012-03-31)

088b1b43ff5dd64aa0f000da9e9da777?s=47 wtnabe
March 31, 2012

JSTDD Intro for EVERY JavaScripters @kanazawa.js v1.7 (2012-03-31)

デザイナもエンジニアも参加する kanazawa.js のために JavaScript を題材にして TDD を紹介します。

088b1b43ff5dd64aa0f000da9e9da777?s=128

wtnabe

March 31, 2012
Tweet

More Decks by wtnabe

Other Decks in Programming

Transcript

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

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

  3. Self-Introduction

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

  6. JavaScriptの専⾨家 TDDの専⾨家

  7. つまり皆さんと同じです

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

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

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

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

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

    『RESTful Webサービス』
  13. 私とTDD ⾃動化 2009年 『Release It !』 Rake, Capistrano プロセス監視

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

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

  16. まとめると

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

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

  19. 不安

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

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

  22. 以上、⾃⼰紹介おわり

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

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

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

  26. What is TDDってなに?

  27. だいぶ乱暴な説明

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

    - 開発⼿法
  29. テストコード? プログラムをテストするプログラム

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

  31. こんな感じ function isOdd( num ) { return num % 2;

    } function testIsOdd() { console.log(true === isOdd( 3 )); console.log(false === isOdd( 2 )); } testIsOdd();
  32. 実⾏結果 $ node /path/to/test_code.js true true

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

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

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

  36. Firebugじゃダメなの?

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

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

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

  40. だからテストコード

  41. では次に

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

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

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

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

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

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

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

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

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

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

  52. 後半しんどすぎる

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

  54. TDDで問題を解決 ⼿動テストのくり返しで疲れる → ⾃動化 ⾃動化 テストを始めるのが遅い → テストファースト テストファースト 「待ち時間」

    → インターフェイスを決めて並⾏作業 インターフェイスを決めて並⾏作業
  55. もう⼀度コードを⾒てみる

  56. プログラムをテストするプログラム function isOdd( num ) { return num % 2;

    } function testIsOdd() { console.log(true === isOdd( 3 )); console.log(false === isOdd( 2 )); } testIsOdd();
  57. こんなコード公開する? プロダクトコードとテストコード混在 JavaScriptの容量増加 テストに⽤意するデータ丸⾒え

  58. 無理でしょ

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

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

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

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

    xUnit / BDD
  63. 今回は 実⾏環境 ブラウザ ブラウザなど組み込み / node.jsなど 種類 ユニット ユニット /

    インテグレーション スタイル xUnit / BDD
  64. 今回は ブラウザ ユニットテスト

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

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

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

  68. おんなじだ!

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

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

  71. どんなものがあるの? Jasmine ( 44% ) QUnit ( 41% ) via

    http://dailyjs.com/files/DailyJSSurvey2011.pdf ※ 複数回答なので合計は100%以上
  72. 今回はQUnit

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

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

  75. Try it ! やってみよう

  76. 最速QUnit解説

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

  78. <!doctype html> <html> <head> <link href="./qunit.css" rel="stylesheet" <script src="./qunit.js" type="text/javasc

    </head> <body> <h1 id="qunit-header">QUnit example</h1> <h2 id="qunit-banner"></h2> <div id="qunit-testrunner-toolbar"></div> <h2 id="qunit-userAgent"></h2> <ol id="qunit-tests"></ol> <div id="qunit-fixture">test markup, will </body> </html>
  79. プロダクトコードとテストコードも⾜す ... <head> <link href="./qunit.css" rel="stylesheet" ty <script src="./qunit.js" type="text/javascri

    <script src="./product.js" type="text/javasc <script src="./test_product.js" type="text/j </head>
  80. ファイルの状態 . ├── index.html ├── product.js <- プロダクトコード ├── qunit.css

    ├── qunit.js └── test_product.js <- テストコード
  81. テストの書き⽅ test('テストの名前', function() { ... });

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

  83. これだけ

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

  85. さて

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

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

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

  89. TDDの教科書的な流れ Fail it - まず失敗 - Red Fake it -

    仮実装 - Green 三⾓測量 & Refactoring
  90. None
  91. by @t_wada 何かに似てる

  92. Diagram by Karn G. Bulsuk

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

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

    });
  95. None
  96. None
  97. Fake it 1 内容のないプロダクトコード function isOdd( num ) { return

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

    true; } test('isOdd', function() { ok( isOdd(3) ); ok( !isOdd(2) ); // new ! });
  100. None
  101. 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 ! });
  102. None
  103. Refactoring 異なる⽅向からの2つ以上のテスト これらを元にゴールをより正確に計る これが三⾓測量 三⾓測量できたらリファクタリング

  104. つまり今がチャンス! function isOdd( num ) { return num % 2;

    // Refactoring } test('isOdd', function() { ok( isOdd(3) ); ok( !isOdd(2) ); });
  105. もう⼀度おさらい Fail it - まず失敗 - Red Fake it -

    仮実装 - Green 三⾓測量 & Refactoring
  106. テストコードは設計を表す test('isOdd', function() { ok( isOdd(3) ); ok( !isOdd(2) );

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

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

  109. Fail it test('formatDate', function() { equal('2012/02/14', formatDate(new Date('Tue Feb 14

    2012 1 });
  110. ちょっと確認したいことが function formatDate( date ) { return [date.getFullYear(), date.getMonth() +

    1, date.getDate()].join('/'); }
  111. Failed Expected: "2012/2/14" Result: "2012/02/14" Diff: "2012/2/14" "2012/02/14" // あ

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

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

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

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

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

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

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

    // new });
  119. 頑張る function padZero( num ) { var str = num.toString();

    if ( str.length < 2 ) { return ('0' + str); } else { return str; } }
  120. Refactoring function padZero( num ) { var str = '0'

    + num; return str.substr(str.length - 2, 2); }
  121. 完成テストコード 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)); });
  122. 完成プロダクトコード 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); }
  123. ⽇付の整形のまとめ 「今」はテストしにくいので固定 設計重要 / 場合分け重要 TDDそのものとは異なる経験も⼤事

  124. Promblems of JavaScript TDD JavaScript TDDの課題

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

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

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

  128. 名前空間 var Namespace = { ... } HTML <script type="text/javascript">

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

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

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

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

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

  134. How to Start TDDの始め⽅

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

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

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

  138. はじめよう

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

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

  141. もう⼀つ

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

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

  144. TDDは⼤事な⼿段の⼀つ

  145. 最後にもう⼀度

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

  147. Any Questions ? Thanks to developers of testing frameworks, TDD

    evangelists and prcatitioners and panelists And You