GROUPエンジニアブログです。TDD2014年09月24日14:15カテゴリprogrammingtestingQUnit+PhantomJS+JenkinsでJavaScriptの品質を改善!はじめまして!cosmiRelationshipSuiteの開発者であるマルィシェフ・ドミトリーと申します。世の中で、Webベースシステムが増えており、管理画面の開発を担当している、エンジニアの視野から抜けがちであるJavaScriptのテストについてお話します。最近の数年、TDD概念が非常に流行っており、Model(ビジネスロジック)をテストするJUnitやPHPUnitの利用は当たり前のようなことになりました。それと同じく、JS(要するに、Front側のロジック)のテストがをしっかりできる環境として、QUnit+PhantomJS+Jenkinsの組み合わせを紹介したいと思います。初めにこの度、localhostで開発・テスト・本番環境を設定し、開発→テスト→本番マシンへの展開を再現し、JavaScriptのTDDを実践で試してみましょう。Integration→継続的インテグレーション)のツールです。Jenkinsの詳しい資料は、http://jenkins-ci.org/にあります。APIで動くヘッドレスWebKitです。要するに、ブラウザーがなくてもJavaScriptが実行できる仕組みを提供していただいております。Frameworkです。callbackのテストが可能モジュール定義により、htmlファイル毎にJSテストを分けることもできるQUnitの利用に関して、詳しくはhttp://qunitjs.com/cookbook/#introductionをご覧ください。環境を用意しましょう。前提条件gitがマシンに既にインストールされていて、GitHubのアカウントを保有していること。cloneでPhantomJSを取得し、下記の手順に従い、ビルドしてください。私の場合、/myprojects/phantomjsにgithubからcloneしました。git://github.com/ariya/phantomjs.gitそこからQUnitを実行するスクリプトを呼び出します。PhantomJSをインストールします。ビルドは数時間かかる場合もございます。jenkins今回は、Ubuntuでインストールしましたので、その他のシステムのJenkinsインストール手順に関して、https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkinsをご覧ください。デフォルトでJenkinsはhttp://127.0.0.1:8080で見れます。必要となるpluginをインストールします。Plugin」を検索し、インストールしてください。pluginインストールが完了したらJenkinsを再起動してください。restartJenkinsとGitHubを連携する際、必要となる鍵を生成しましょう。jenkinsユーザ(Jenkinsインストール時に自動的に作成されるユーザ)の権限で、鍵を生成しなければなりません。"jenkins@hogehoge.com"鍵を生成する際、デフォルトのまま進めてください。jenkins@hogehoge.com生成された鍵、Ubuntuの場合、デフォルトで/var/lib/jenkins/.sshに生成されます。できた鍵をknown_hostsに追加します。Titleに適当な名前を入力して、/var/lib/jenkins/.ssh/id_rsa.pub(生成されたJenkins公開鍵Jenkinsのデフォルト保存場所)の内容をコピーして、Keyに貼り付けます。GitHubの鍵生成の詳しくは、https://help.github.com/articles/generating-ssh-keysを参照できます。GitHubのリポジトリーを作成GitHubでtestrepoリポジトリーを作成します。開発環境の用意testrepoをローカルの作業フォルダーにcloneします。開発フォルダーのtestrepoの下で、加算・引き算をする簡単なファイルを実装しましょう。それより、先にGitHubのtest_branchのブランチを作成します。test_branchプロジェクトは以下のファイル構造になります。Testまずは、htmlページを実装します。res);</script></body></html>今回、テストしたいJavaScriptのロジックはadd.htmlとsubtract.htmlのページに実装していきます。QUnitでテストできるには、ソースコードに数行を追加しなければいけません。QUnitのライブラリjsとその表示用のcssをhtmlのheadに追加します。src="//code.jquery.com/qunit/qunit-1.15.0.js"></script>QUnitのテスト結果が表示されるqunitとqunit-fixtureのidを持っているdivもhtmlのbody追加します。Testも実装します。expected);});すべてを組み合わせると、以下のようになります。id="qunit-fixture"></div></body></html>ブラウザで見ると、この感じになります。CLIでもテストできます。そのために、phantomjsから、QUnitを実行するrun-qunit.jsを呼び出します。run-qunit.jsのパスはPhantomJSのソースコードの保存先によって変わります。QUnitテストのソースコードをテスト専用のjs/test/unit_test.jsに移行しましょう。各htmlファイルにQUnit用のcssやdiv.qunitとdiv.qunit-fixtureを追記しないように、それを動的に生成するようにしましょう。unit_test.jsは以下のようになります。expected);});add.htmlも修正します。Testは失敗します。failed.失敗の理由は、subtract.htmlでテストしようとしているcalculateAddの関数がないからです。Testは成功します。Testのjsを用意するのが非常に面倒です。そのために、QUnitでModuleという仕組みが設けられ、複数htmlページの関数テストを一つのjsファイルでまとめて、モジュール毎の呼び出しは可能です。足し算処理のテストと引き算処理のテストをそれぞれ、add_testとsubtract_testに分けます。expected);});できたモジュールをもう一度、呼び出してみます。Testは、http://yourdomain/filename?module=moduleName形式で呼び出されます。failed.最後には、unit_test.jsにもう少し手を加えましょう。実は、その開発環境でも本番環境でもQUnitのJavaScriptは毎回呼ばれるのが困ります。結局、テスト用のマシンのみQUnitを実行したいわけです。そのため、QUnit.config.autostartの設定項目が存在しています。そこで、テスト用のtest.myserver.comでのみ実行できるようにQUnit.config.autostartを工夫します。Test用のjs/test/unit_test.jsファイルは下記の形をとります。expected);});できたソースコードをGitHubのtest_branchにpushしましょう。Jenkinsのjobを作成こちらで、ソースコードをbuild/test/deployするjobを作成します。build状態をGitHubに知らせるjobを作成プロジェクトをビルドするjobはそれを参照するので、先に作ります。status_update_job「OK」で作成画面に入ります。「ソースコード管理」→「なし」にチェック「ビルド」→「シェル実行」を選択します。\https://api.github.com/repos/${REPOSITORY_NAME}/statuses/${UPDATE_COMMIT}tokenはOAuth用に生成してください。token」でOAuthトークンを生成し、その文字列をどこかで保存してください。トークンを作成する際、repoにチェックが入っていることを、確認してください。build_job「OK」で作成画面に入ります。Branch」で追加してください。Specifier」に「*/master」と「*/release」を入力してください。build」を選択し、その中から「Inverse」にしてください。*「ビルド」→「シェル実行」を選択します。deploy_job「OK」で作成画面に入ります。ジョブ作成画面で「ソースコード管理」→「なし」にチェック「ビルド・トリガー」→「定期的に実行」にチェック「ビルド・トリガー」→「スケジュール」に常に起動するように設定。*「ビルド」→「シェル実行」を選択します。本番環境の用意GitHubでbranchがmasterにmergeされた後、本番環境にソースコードをdeployします。今回、開発環境や本番環境は同じマシンになっていますので、本番環境は別のマシンになる場合、rsyncなどをご利用ください。/myserverフォルダーを作成してください。Jenkinsでのテスト環境の用意PhantomJSはQUnitをテスト用のサーバで実行するので、先ほど作成されたJenkinsのbuild_jobはtest.myserver.comテストサーバのDocumentRootになるように、apacheのconfファイルに下記を追記します。PhantomJS+QUnit+Jenkinsの実践これで、やっと開発・テスト・本番環境が揃いました。本番環境にはまだ何もdeployされていないので、本番サーバはこの感じです。add.htmlを修正し、bugを仕込みましょう。result+1;}そして、そのソースコードを、先作成してきたtest_branchにpushします。Requestを作成してみます。それをやってみると、最近の当ブランチにpushされたcommitのbuild_jobが失敗したことが分かります。ブランチをクリックすると、ビルドが失敗したcommitを見れます。Jenkinsのjob一覧画面を見ると、build_jobの#8が失敗したことが分かります。そのbuild_jobをクリックし、job結果一覧画面に移動します。Outputでbuildの失敗した原因を調べることもできます。build_jobの次に、status_update_jobが起動し、GitHubでcommitの状態をfailureに設定しました。仕込んできたbugを修正し、またtest_branchにpushしましょう。result;}そして、test_branchにpushします。test_branch今度、build_jobは成功し、GitHub上の結果はこのとおりとなります。branch」でtest_branchを削除します。その後、deploy_jobは起動し、masterから最新版のソースコードを本番サーバにpullします。先ほど設定した本番サーバのhttp://prod.myserver.comにアクセスし、ソースコードは問題なく表示されていることをご確認ください。まとめ「使いやすさと良き見映えは成功の8割」と言われるWeb画面ですが、そのJavaScriptのバグは、ユーザーエクスペリエンスを低下させ、お客様からの多くのクレームの原因にもなります。そこで、QUnit+PhantomJS+Jenkinsを利用したら、Front側JSの品質向上に充分貢献できるかと思います。:TDDjenkinsgithubPhantomJSQUnitvoyagegroup_tech2013年11月12日16:19カテゴリprogrammingプライベートメソッドのテストは必要ない!!こんにちは、RPAの関口です。最近週に一度、来年の新卒達と一緒にTDDをやりながらワイワイガヤガヤしております。いう話題がありました。プライベートメソッドのテストについてはプライベートメソッドのユニットテストは書かないもの?がよくまとまっていると思います。プライベートメソッドのテスト方法について考える中で「TDDの手順に従えばプライベートメソッドのテストがしたくなることは無い」のではないか?と思うようになりました。プライベートメソッドはリファクタリングの結果現れる!数値の配列を渡すと平均を計算して返してくれる機能を持ったクラス、AverageCalculatorを作りたいとします。平均計算の手順をまとめると以下のようになります。配列の合計値を計算する合計値を配列の要素数で割って返すここで「よし!まずは配列の合計値を計算する機能をつけよう!」と思って次のようなテストを書くとcalcSumメソッドの可視性について途中計算でしか使わない合計値の計算は、プライベートメソッドにしたいでもプライベートメソッドだとテストのためにReflectionを使う必要があって面倒という悩みが発生してしまいます。最初「平均値を返すメソッドを追加」しようと思っていたのに「合計値を返すメソッドを追加」しようとしたためです。平均値計算の手順はあくまで手順、初心に帰って平均値を返すテストを書きましょう。合計値計算のメソッドは分離したいなぁと思ってリファクタリングする際に、calcSumという名のプライベートメソッドが自然と現れます。このプライベートなcalcSumメソッドのためにテストを追加する必要はありません。中身がどのような実装になっていようと外部から呼び出されるcalcAverageメソッドが期待通りの結果を返してくれれば良いのです。calcSumメソッドはパブリックなcalcAverageメソッドを通じてテストされている、とも言えます。パブリックメソッド経由でテストする多くの場合、そのクラスのパブリックメソッド経由でプライベートメソッドのテストも同時に行えます。テストできているか不安があるならカバレッジを測定しましょう。プライベートメソッドのユニットテストは書かないもの?より。calcSumの代わりに大変複雑な処理だった時はどうするの?そのような場合、いきなりcalcAverage相当のメソッドを作るの事は難しいでしょう。calcSumのメソッドの追加を行う必要が出てくるかと思います。そのcalcSumはAverageCalculatorクラスがやるべき事なのでしょうか?実はSumCalculatorという名の新しいクラスを作って、その中にパブリックメソッドとして書くのが正しいのではないでしょうか?別クラスのパブリックメソッドとするプライベートなメソッドのテストを書きたいということは、実はテスト対象の責務が多すぎることを示唆している場合があります。テストがどうしても書きたい場合は、その責務はテスト対象のプライベートな振る舞いでは無く、誰かのパブリックな振る舞いなのでしょう。テスト対象のプライベートメソッドを「クラスの抽出」や「メソッドの移動」を使って、テスト対象のコラボレータのパブリックメソッドとして抽出し、普通にパブリックメソッドとしてテストしましょう。プライベートメソッドのユニットテストは書かないもの?より。他の方法ここまで書いておいてなんですがcalcSumのテストと実装をパブリックで書くcalcAverageのテストと実装をパブリックで書くリファクタリングでcalcSumメソッドの可視性をプライベートにして、calcSumのテストは削除という手もあるかと思います。いうかこちらのほうが自然ですね。書いたテストを捨ててしまうのは勿体無い気がしますが、実装中に書いたテストと最後に残すテストを同じにしなければならないというルールはありません。calcSumはcalcAverageを通してテストされているので良しとしましょう。そんなこんなでプライベートメソッドのテストは必要ない!!・・・のではないかと最近思い始めました。:TDDtestingvoyagegroup_tech2011年10月07日14:43カテゴリ勉強会TDDワークショップを開催しました株式会社adingo所属かつアジャイル戦略室(勝手メンバー)の@katzchangです。GROUP社内勉強会としてTDDワークショップを開催してみましたので、そのご報告です。Campスタイルをとりました。課題は「ECナビ会員のグレード(http://ecnavi.jp/mypage/guide/condition/)を判定しよう」。言語はもっとバラエティに富んでた方がよい全員ペアプロだったので、ペアプロじゃない人と比較したかった(PHPで)Shift_JISでは日本語メソッドは構文エラーになるパソコンは一人一台あるとよいもう少し時間が長くてもよい仕様が不明な時に、もっと積極的に出題者に質問できればよかった(コードレビューのとき)ThinkPadがプロジェクターに映らなかったEclipseよくわからなかったお腹すいたTryパラメタライズド・テストでテストを書いてみたいペアプロ大会したい今日参加できなかったエンジニアのためにまた開催してほしいピザでも食べながらコードレビューこれを受けてペアプロがとても好評だったのは、想定通りでした(ドヤッペアプロとTDDの相性の良さについては、書籍「ペアプログラミング」(ピアソン・エデュケーション)の中でも触れられています(私の席に置いているので、読みたい方は声をかけてみてください)。テスト駆動開発を活用してください。(中略)テストファーストプログラミングと組み合わせると、ペアプログラミングの価値が本当にわかると言った人たちがいます。その人たちは、最初にテストを作成することで、ペアが2人とも、取り組んでいる問題を正確に把握すると述べています。p101TDDを使わずに作業の結果を確認するためには、ドライバーは黒目を動かして広大なブラウザ画面のどこかの文字列を網膜に写し、それがドライバーの脳内にある意図に沿っているかを検査することなります。横で見ているパートナーには伝わるはずがありません。ドライバーが「ここがゴールド会員だから、このメニューがこうなって...」みたいな独り言を言いながら進めるのはとても良いことですが、なかなか限界があるでしょう。目標(テストコード)を明確にして実装を進めるTDDは、ペア同士のコミュニケーションも促進するということだと思います。Campを企画中です。社内向けの研修ではあるのですが、外部の方にも参加していただけるような形で開催したいと私個人としては思っていて、おそらく、そのようにできると信じています。時期は年明けくらい、12月くらいには何かお知らせできればば、順調に進んでると安心していただけるはずです。あと2回程度ワークショップを開催してみて、そこから先の「使える武器」をどう増やしていくにフォーカスするという方向もアリかもしれないと思いながら、まーどうしましょうかねぇ。現状、プロダクトによってはレガシーコードとの熾烈な戦いがあったり、自分も含めてまだまだ経験が足りていない――言い方を変えれば、挑戦すべき多くのことが目の前に転がっています。これはとても恥ずかしい話ではありますが、ただ、それらを一つ一つ片付けながら進むという、泥臭く、かつ人間臭い仕事ができるエンジニアは、プロフェッショナルと呼ばれるにふさわしいのではないかと思うわけです。いうわけで、最速最強の開発を目指して、今の開発を加速していきましょう。