JavaScriptテストの疑問、お答えします
自己紹介
- @kyo_ago
- ChatWorkの中の人です
- 普段はLT中心
- ApplicationCacheとかSSEとかCSSを何とかしたい人
(自覚は無いです)
今日話すこと
今日話すこと
- 疑問に対する答え
- テストを書く目的
- 始める前に
- 実践編
- 振り返り
会場に質問
「テストしてますか?」
「Yes!」 or 「No...」
実際「No」は多分ほぼない
手動テストも含めれば基本的に何らかのテストは行う
Q「テストってほんとうに必要?」
Q「テストってほんとうに必要?」
A「Yes。ただし、自動テストが必要かは場合による」
テストとは自動テストだけではない
手動テストも十分テストとして考えて良い
テスト自動化の功罪
テスト自動化の功罪
- 手動テストに価値がある
- 必要以上に手動テストが貶められていないか
- 自動化は理想だけど、常に良いわけではない
- 費用対効果の検討は必要
常に自動化が良いとは限らない
常に自動化が良いとは限らない
ただ、手動テストはあまり語ることもないのでここからは自動テストに関して話します
Q「あんまり意味がある気がしないんだけど。。。」
Q「あんまり意味がある気がしないんだけど。。。」
A「割にあわないならやらない方がいい。ただし、改善は必要」
テストを特別視しない
開発手法やフレームワークのように費用対効果の検討を
ただし、仕事でやるなら予測が必要
使ったことない手法の費用対効果を予測するのは困難
(道を知っていないと歩き出すことはできない)
最初は捨てる前提で簡単な部分から
自動テストは個人でも簡単に実践できる
費用、効果は開発者の技術力、経験によって違う
改善していけばコストは低くなる
ただし、テスト技術はテストをしないと身につかない
Q「どこまでやればいいの?」
Q「どこまでやればいいの?」
A「できるところまで」
この問題は線引が難しい
(ケースバイケースな要素が多い)
テストはまだまだ個人のスキルに大きく依存する
(チーム全体のスキルもある)
ただ、この質問はそもそもテストの経験がない場合が多い
(すでにやってる場合どこまで出来るか見えてるから)
見極めができないならできるところまでとしか言えない
Q「UIのテストはやらないって言うけど、JavaScriptだとほとんどUIだよね?」
Q「UIのテストはやらないって言うけど、JavaScriptだとほとんどUIだよね?」
A「不安にフォーカスしよう。UIが不安ならやるべき」
テストとは不安に対向するための手法である
「UIはやらない」は「UIのテストはコストが高いから費用対効果に見合わない可能性が高い」という意味
実際今手動でUIのテストを行っていて、その費用対効果が高いなら改善すべき
最近はUI(CSS、HTML)のテストもコストが低くなりつつある
(自動でキャプチャ取って一覧でみれるだけでも違うのでは?)
Q「で、今手元にあるコードをどうしたら良いの?」
Q「で、今手元にあるコードをどうしたら良いの?」
A「まずはE2Eテストフレームワークを導入してみては」
テストを考慮していないコードに対してユニットテストを書くのは難易度が高い
(ユニットテストの矛盾)
E2Eテストは比較的ターゲットコードの品質に依存しない
(E2Eテストの法則)
また、テストの文化が根付いていない環境でテストをする困難もある
(テストが難しい部分の修正にテストがいる問題)
Q「なんでJavaScriptのテストってこんなに面倒なの?」
Q「なんでJavaScriptのテストってこんなに面倒なの?」
A「そもそもテストは大変」
サーバサイドも昔は大変だった
技術革新で楽になった部分もあるけど、UIがなくなってAPIベースになった部分も大きい
UIのテストは基本大変
(さらにUIはリッチ化している)
ここまでで何か質問は?
ここからは演説になります
テストの目的
テストの目的
- なぜテストするのか目的を明確にしよう
- 目的が明確で無いと迷ってしまう
- 目的以外は無視しよう
- 目的を達成すべきことだけをやろう
基本、目的がなければやってはいけない
ただ、難しく考える必要はない
とりあえずこのへんから考えて見ては?
おすすめの目的
- 自分の不安の解消
- 他人の不安の解消
- 手動テストの自動化
- 勉強、趣味、見栄
- 複数環境検証
おすすめの目的
- デグレーションの回避
- ドキュメント代わり
- 知識の共有
- 設計
それぞれ解説します
自分の不安の解消
自分の不安の解消
- 非常に健全な理由
- 安心できるまでやろう
- 一般的なテスト技術が使える
- 自己満足にならないように注意
他人の不安の解消
他人の不安の解消
- 普段繰り返していることの省力化を目指そう
- 技術ではなく信頼感
(「全く違う方法で検証」では意味が無いことも)
- 簡単に非常に大きな成果が得られることも
- 便利屋にならないように注意
- 自動操作系ツールでの「自動ログイン」や「連続投稿」など
手動テストの自動化
手動テストの自動化
- 今やっている手動テストを自動化する
- 一クリック省略できないか
- テスト自体ではなくテスト準備の自動化でもいい
- 「画面操作は手動」や、「確認は毎回目視」という手も
- 自動テストのベースにもしやすい
- 効果を周囲に説明しやすい
勉強、趣味、見栄
勉強、趣味、見栄
- これも非常に健全な理由
- 最初はこれから始めることをおすすめする
- 「テストしてますか?」に手をあげられる
- 「テストのためのプロダクト」を作ってみては?
- テンプレートエンジンとか
複数環境検証
複数環境検証
- 「エンジニアがAndroidで確認しない問題」
(旧「エンジニアがIEで確認しない問題」)
- 複数ブラウザ、複数言語での動作確認
- さらっと流すだけでも安心感高い
- SauceLab、BrowserStackなどのサービスも使える
デグレーションの回避
デグレーションの回避
- バグが出た時だけテストを書く
- 難易度は高い
- 周囲の理解は得やすい
- テストの文化の呼び水として
- 場当たり的になる危険性も
ドキュメント代わり
ドキュメント代わり
- 主なAPIだけ
- 場合によっては実行できなくてもいい
- 細かく書きすぎると意味が無い
- 他のテストとは分離を
知識の共有
知識の共有
- チームに対する情報共有
- 先にテストだけPR出す手も
- ペアプロ的にやる方法も
設計
設計
- TDD的な意味
- 最初は目指さない方がいい
- なれるまでは気にしないようにしよう
目的に注力したテスト
目的に注力したテスト
- テストの目的は豊富
- 目的にあった内容を目指そう
- みんな「テスト」の認識が違いすぎる
- やればやるほど良いというものではない
- 目的を間違えると手法が正しくても意味が無い
- 「なぜ、何のために」テストをするのか
「一般的じゃない」?
「きれいじゃない」?
目的を達成できれば勝ち
テストを書く文化
テストを書く文化
- 技術的な問題より文化的な問題のほうが対応が難しい
- すでに文化があるなら導入は難しくない
- 最初は不安の可視化から
- その不安を解消するための対応をしよう
テストを書く文化
- テスト以外にも方法はある
- 不安の可視化を待つ方法も
- 不安がわからないなら周りに聞こう
- 「過去によく問題が発生した箇所はどこですか?」
テスト、事始め
テスト、事始め
- 「じゃあ最初はユニットテストから」はおすすめしない
- ユニットテストは自動化しやすいけど難易度は高い
- 最初はAssertから始めよう
テスト、事始め
- よっぽど速度が気にならない限り放置でいい
(出力が気になるならconsole.assertを殺そう)
- assertでよく止まる箇所は複雑な可能性が高い
- 「よくassertが止まるから」はテストを導入する理由として説明しやすい
- assertの「理由」はそのままテストに流用できる
- 切り出してテストしよう
「やっぱりどこからやるか分からない。。。」
「やっぱりどこからやるか分からない。。。」
- テストを書く技術を伝えることは難しくない
(他の開発技術と同じ)
- しかし、どこが不安かを認識する技術を伝えることは非常に難しい
- 一般的な不安点はそもそも切りだされてテストされてる
- 残るのはどこが不安かわからない毎回変わるビジネスロジック
「やっぱりだめだった。。。」
「やっぱりだめだった。。。」
- 無理だと思ったら引き返そう
(引き返すのは簡単)
- 社内ハッカソンや勉強時間に業務コードに捨てる前提のテストを書いてみては?
- テストを実行する基盤だけ置いとこう
- 「最初は手動実行」、「実コードは欲しくなった時に書く」
- 少しづつやっていこう
「テスト書けたけどなんか違う。。。」
「テスト書けたけどなんか違う。。。」
- テストを書けば改善するわけではない
- テストの費用対効果が悪いこともある
- 足を引っ張っていると思ったら切り捨てよう
- 「部分的に残せないか」、「基盤だけ残せないか」は検討してみよう
そもそもの話
そもそもの話
- メインプログラムでテストを書かなくていい環境はある意味正しい
- 複雑なところはフレームワークが隠蔽してくれてるということ
- フレームワークに乗っかっているとテストの必要性を実感しにくい
- しかし、逆に不安点がコード内に遍在してどこをテストすべきかわからなくなる
- 不安点をを集中させてそこをテストでカバーする
ここから実践編
ツールに関して
ツールに関して
- ユニットテストはMochaかJasmineが主流
- 個人的にはMocha派だが、Jasmineは各種ツールのベースになっていることも多い
(QUnitも最近大きな改修が入ったけど)
- SinonJSは未だに置き換えるものが出ない
(そして未だにちょいちょい更新入ってる)
- 最近だとPromiseのテストパターンが話題
- 非同期テストパターンの発達でfakeTimer系を使わなくなった
ツールに関して
- PowerAssertの一般化
(各種変換をかける場合は複雑になることも)
- E2EテストはProtractorが強いが、testiumにも期待
(Protractorは周辺ツールが揃ってるがtestiumは同期で書ける)
- テストランナーは簡単に始めるにはtestemでもいいけど、ある程度大きくなるならkarmaがおすすめ
(karmaも十分簡単に始められる)
ツールに関して
- TestはIsomorphicな利点が大きい
(Isomorphicなコードはテストしやすい)
- モジュール分割してロジックの分離を
(ユニットテストだけでもNodeでできると楽になる。Phantomの再現性も微妙だし)
- テストを別言語で書くかどうかは微妙なところ
(個人的にはおすすめしない)
テストと数値
テストと数値
- バグの発生曲線的な
- 難しい問題
(コードカバレッジを数値として扱うのは正直否定的)
- その他の数字はあまりとったことがないので感覚がわからない
- 誰かの不安を解消できるなら数値化した方がいい?
- 自分は必要なほど大規模な開発には参加したことがない
(数値化できるにこしたことはないとは思う)
- Webは割と更新が容易なので求められる信頼性の問題もあると思う
テストの振り返り
テストの振り返り
- そのテストはほんとうに役に立ったのか
- 前回のプロジェクトのテストと比べて品質は上がっているのか
- テストと数値に絡むと思うけど難しい
- 個人的にはまだ感覚レベル
コードカバレッジどうする
コードカバレッジどうする
- かなり微妙な問題だと思っている
- 個人的には安易に取ることはおすすめしない
- 取ることでどういう安心を得たいのか
- 個人的に「CIと連携してグラフ化」は禁じ手にしてる
コードカバレッジどうする
- 数字は簡単に増やすことができる
- 単純に数値が増えることで「偽の安心感」を得てしまわないか
- 「偽の安心感」を得るのは簡単だけど、問題が見えにくくなる
- いっそ取らないと決めるのもありだと思う
コードカバレッジどうする
- 「今このタイミングでカバーしていない部分を把握したい」のはあり
- 設定だけ書いてIDEとかから実行できる状態で置いとくのがいいと思う
テスト技術は重要なのか問題
テスト技術は重要なのか問題
- テストの技術だけあってもテストは出来ない
- 問題領域の知識が必要
- これは特に問題領域の知識を持っている人ほど軽視しがちな印象
- 特に「問題領域の不安点」は問題領域の知識を持っている人しかわからない
- これは場合によってはテスト技術の不足より解決困難
ご清聴ありがとうございました