Gleyzer両氏によって共同開発されました。2019で、同言語の発表を行いました。InfoQはPurdy氏に言語と、氏らが解決を目指した問題について聞きました。設計/アーキテクチャアジャイルマニュフェスト:ソフトウェアアーキテクトの視点ソフトウェアアーキテクトの役割と責任はアジャイルソフトウェア開発のためのマニフェストの価値と矛盾していると見えますが、優れたアーキテクトはアジャイル開発チームをサポートするテクニックを見つけています。Streamingは、ストリーミングデータのためのSQLライクなインターフェースを提供します。Streamsによって、Redisがストリーミングデータを複数のプロデューサとコンシューマの間で消費、保持、配信することができるようになります。ソフトウェア開発のマニフェストたゆまず息もつかずに市場に突進することで、会社を静かに消滅の崖っぷちへと追い込みます。それは設計してコードを書く方法を再考する時です。簡単さへの投資は、速さへの投資です。簡単さは知的財産の主鉱脈でもあります。競争上の優位性は、一度失ったら、もう一度手に入れることはほとんど不可能です。Buytaerts氏が過去10年間にわたって、企業がDevOps採用のハイプサイクルをくぐり抜け、変革に対する誤解を解消する過程を支援してきた経験について語ります。裕之この記事は保守性の高いJavaScriptを作成するための集中講座です。ユニット・テストを書いて、そのテストを通るようにするという単純な法則を繰り返しながら既存の例題に機能を追加していきます。それぞれのテストは、安全策と実行可能なドキュメントの両方の意味で製品のコードを修正しようとする全ての人にとって、品質をフィードバックするのに使うことが出来ます。各機能の実装にあたって、まずは簡単な失敗するテストから始めることで確かにテストをしたことを確認します。後になってテストのためにコードを書き直す手間を避けるのです。JavaScriptの開発者にとっていかに多くの引っ掛かり易い罠があるかという事実を考えるとこれは特に効果的な方法です。APIと(JavaScript)言語の間にどれだけのグローバルで変更可能な状態があるのかを考えてみて下さい。私達が使う例題はカジノにあるの3リールスロットです。それぞれのリールは5つの状態をとることが出来、それぞれは画像で表現されます。スロット・マシーンのプレイ・ボタンを押すとそれぞれのリールはランダムに状態を選びます。3つのリールの状態が等しいかどうかによってスロット・マシーン上の持ち点は増減します。関連スポンサーコンテンツ私達が使うツールはスタブ、モック・オブジェクト、そしてDI(依存性の注入)を少しだけ使います。ユニット・テストを実行するのにJsUnitを使い、JsMockと呼ばれるJavaScriptモック・オブジェクトのライブラリも使います。インテグレーション・テストは、ユニット・テストをより丁寧にしたものですが、この記事の範疇ではありません。これはインテグレーション・テストの方が重要性が低いということを意味している訳ではなく、私達が望んでいるのはSeleniumやWatirのようなツールから得られる広範囲でゆっくりとしたフィードバックではなく、素早いフィードバックであるというだけのことです。JsUnit、JavaScript用のユニット・テスト・フレームワークJsUnitはオープンソースのJavaScript用のユニット・テスト・フレームワークです。JUnitから発想を得て全てJavaScriptで書いたものです。普及したJavaScript用のユニット・テスト・フレームワークとなっただけではなく、いくつかのantタスクが同梱されています。これらのantタスクによって開発者はサーバでのビルド時に継続的インテグレーションの一環としてテスト・スイーツを実行させることが出来ます。継続的インテグレーションは、この記事の範疇を超えるまた別の優れた実践であり、TDDと併用することで品質を強化するものです。JsUnitのテスト実行部の話から始めます。テスト実行部はHTMLとJavaScriptで作られたプレーンなWebページなので、ユニット・テストはあなたがサポートしたいと思うブラウザで直接実行することが出来るということです。JsUnitのダウンロード・ファイル(Zip)を解凍するとルート・ディレクトリにtestRunner.htmlがあります。テスト実行部をWebサーバに配置する必要はありません。ファイル・システム上にあるファイルをブラウザで開けばいいのです。テスト実行部上の最も重要な部分はページの上部にあるファイル参照用のフォーム部品になります。この部品はテスト・ページまたはテスト・ページのスイート・ファイルへのパスを保持します。JsUnit用のテスト・ページの簡単な例を見てみましょう。<body/></html>JsUnitには他のxUnitフレームワークとの共通点が多くあります。期待通りテスト実行部はテスト・ページを読み込み、テスト関数をそれぞれ呼び出します。それぞれのテスト関数はsetUpとtearDownという関数の呼び出しに挟まれています。setUp関数はテスト作成者がテストの設定を構成する機会を与えます。テストの設定はそのページの全てのテストで固定化される状態のことを指します。tearDown関数はテスト作成者がテストの設定の後始末をする機会を与えます。JsUnitと他のxUnitフレームワークの間にはテストのライフ・サイクルの面で僅かな違いがあります。テスト・ページはそれぞれ別のウィンドウに読み込まれるので、アプリケーション・コードが公開されているクラスを通してフレームワークのコードをオーバーライドしてしまうのを避けられます。(テスト・ページが)読み込まれたそれぞれのウィンドウ内で全てのユニット・テスト関数が実行されます。テスト関数を実行する度にページが再読み込みされることはありません。JUnitでテスト・ページに相当するのはテスト・ケースですが、テスト実行部は各テスト・メソッド毎に別のテスト・ケースのインスタンスを生成します。以下のようになります。JsUnitはN個のテスト関数に対して1度だけテスト・ページを読み込むJUnitはN個のテスト・メソッドに対してN回テスト・ケースを生成する従って、テスト・ページの状態を変更してしまうと後続のテストの結果に影響を与えてしまうという意味でJavaScript開発者は一歩間違えると深みにはまる状況にあると言えます。それに対してJava開発者はテスト・ケース・オブジェクトの状態を変更してもそのようなリスクにさらされることはありません。JsUnitはテストの度にテスト・ページを再読み込みするだけの手間を惜しんだのでしょうか。それはテスト・スイートに含まれる全てのテスト関数を実行する度にDOMを再構築することは性能上大きなコストを要することになるからです。JavaScript開発者はグローバルな状態の変更による副作用について考慮する必要はあまりありません。JVMやCLRのようなプラットフォーム上でのプログラミングでは、静的な変数を変更するユニット・テストは、同じテスト・ケース内のテストのみならず、同じテスト・スイートに含まれる後続のテスト全てに影響を与えてしまいます。jsUnitCore.jsというスクリプトは全てのテスト・ページに組み込まれていなければなりません。この重要なファイルはJsUnitのダウンロード・ファイルを解凍して出来たappディレクトリに配置されています。このスクリプトには他のxUnitフレームワークとほぼ同一の振る舞いをする少量のアサーション用関数が含まれています。JavaScriptには等価性に関する2つの考え方があるという事実に由来する僅かな違いが存在します。JavaScriptには等価演算子と厳密等価演算子があります。最初の演算子は以下の式をtrueと評価しますが、二つ目の演算子はfalseと評価します。falseどういうことでしょうか。等価演算子は厳密等価演算子ほどには厳密ではなく、実行時に最初のブーリアン式への型変換を許可します*。従って初心者は下記のアサーションを通ると思うかも知れません。0);実際のところ、JsUnitフレームワークで提供されているアサーション用関数は全ての比較に対して等価演算子ではなくより厳密な厳密等価演算子を使っているので、このアサーションは失敗します。等価演算子の利用を避けることでJsUnitは多くの誤検知を回避することが出来るのです。モック続いて私達の例題であるスロット・マシーンにおけるスタブとモック・オブジェクトについて見てみましょう。今回のユニット・テストは1つのオブジェクトに注目しているので、スロット・マシーンを作成してテスト対象システム呼ぶことにします。スロット・マシーンをレンダリングする簡単なテストを書いて見ましょう。reelsStub[2].src);}testRender関数では2つのDOM要素をスタブ化していて、どちらもテスト対象システムのコンストラクタに渡され、その後renderメソッドを呼んでいます。テストはrenderメソッドの期待される副作用に関するアサーションで終わっています。DOM要素をスタブ化することでこのテスト・ページにあるその他のテストを無効にしてしまうことなくrenderメソッドの副作用についてテストすることが出来ると言うことに注目して下さい。この方法と実際のDOM要素を使う方法にはトレード・オフがあります。実際のDOM要素を使う方がブラウザ互換性に関するバグをより多く見つけることが出来るでしょうが、それぞれのテストの最後もしくはtearDownの中でDOMの状態を復元しない限りテスト自体のバグが増えるでしょう。テスト対象のシステムは各リールの初期画像を決定するためにグローバル関数Math.randomを直接呼び出してはいません。その代わりスロット・マシーンはこれらの数字を得るためにスロット・マシーンの生成時に渡されたものを使っています。これによって私達はソフトウェアの予測不能な面についてあたかも完全に予測可能であるかのようにテストすることが出来るのです。ブラウザのMath.random関数の実装を上書きしないことでこのテストがどのように状態の変更や副作用を回避しているのかに注目して下さい。テスト関数には複数のアサーションがあります。これでいいのでしょうか。アジャイルのコミュニティには一つのテストで複数のアサーションをすることは悪いことであると考えている小さな一派があります。実際に利益を生み出している実際のアプリケーションのテスト・スイーツではそのような書き方(一つのテストに一つのアサーション)をすることはほとんどありません。このような人々の多くはJUnitフレームワーク自身のテスト・スイート(リンク)で一つのテスト当りにどれだけ多くのアサーションがあるのかを知ったときにとても驚いたことでしょう。(テスト対象の)オブジェクトのコンストラクタとrenderメソッドは以下のようになります。}};ではスロット・マシーンにいくらかのお金を投入してみましょう。このシナリオでは、ユーザの持ち点を取得するためにスロット・マシーンはサーバに対して非同期呼び出しをします。ユニット・テストではネットワーク環境もなくAJAX呼び出しは失敗するのでこれはとても挑戦的な取り組みになります。ユニット・テストを書く際にはそのコードが副作用をもたらさない様に努める必要があります。IOは間違いなくこの部類に含まれる問題でしょう。callback);}このテストではネットワークをスタブ化しています。スタブとは何でしょう。スタブはモックと何が違うのでしょうか。多くの開発者がこれら2つの言葉を同義語だと勘違いしています。テストの世界ではスタブという言葉は状態に依存するテストのための予約語です。JavaScriptの世界でいうとこれはほとんどの場合単にハードコードされた値を返すだけのオブジェクトのことを意味しています。モックという言葉は相互作用のテストのための予約語です。モックは振舞いを持たせることが出来るのです。こらの振舞いはテスト対象のシステムと相互作用し、その相互作用を検証することが出来るのです。ネットワーク・クライアントをスタブ化することでgetBalanceメソッドをテスト出来るようになりました。コンストラクタに渡されたスタブ化されたリテラル・オブジェクトはテスト対象システムとの相互作用についてurlとcallbackというローカル変数に記録をします。これらのローカル変数を使ってテストの最後にアサーションを行います。残念ながら私達は間違ったツールを選択してしまいました。これはスタブの限界となぜモック・オブジェクトなら目的を達成出来るかを示す古典的な例です。このテストの目的はある状態を与えられた際のテスト対象システムの振舞いを検証することではありません。このテストはdrw.SlotMachineのインスタンスとその協調相手の一つであるネットワーク・クライアントとの間の相互作用について検証することに関心があるのです。JsMock、JavaScriptのためのモック・オブジェクト・ライブラリtestGetBalanceGoesToNetworkをよく見るとそれ自身がちょっとしたモック・フレームワークであることが分かるでしょう。このテストをリファクタリングして一般的なモック・フレームワークを使うようにしてみましょう。そのためにscriptタグを一つ追加し、テストを以下のように書き換えます。}これでより少ない行数で同じ効果を得ることが出来るようになったばかりでなく将来のテストのためのよりよい基盤を作る土台を用意することも出来ました。これはどのように機能するのでしょうか。コードの最初の1行はJsMockで提供されるMockControlのコンストラクタを使ってオブジェクトを生成しています。その後2つ目のメソッドを使ってモック・オブジェクトを生成しています。実際にNetworkClientクラスを使ったアプリケーションではcreateMockメソッドにリテラル・オブジェクトを渡す必要すらないのです。JsMockではprototypeを使うことで同じ効果を得ることが出来ます。mockControl.createMock(NetworkClient.prototype);ネットワーク・クライアントのモック・オブジェクトを生成した後、あるパラメータを使ってsendメソッドが呼ばれることを確認するようにプログラミングされています。サーバ・リソースの名前が正しいことと2つ目の引数がコールバック関数となっていることを確認します。モック・オブジェクトはテスト対象システムのコンストラクタに渡されMockControlオブジェクトのverifyメソッドを通してこの相互作用を確認してテストは終わります。何らかの理由によりスロット・マシーンの実装がネットワーク・クライアントのsendメソッドを呼ばなかったか、パラメータが期待値と一致しなかった場合には、verifyメソッドが例外を投げてテストは失敗します。続けてdrw.SlotMachineのインスタンスがどの程度の頻度でネットワーク通信を行っているのかを確認するテストを作成してみましょう。サーバの応答が完了する前にgetBalanceメソッドが呼ばれた場合は、持ち点を2度も取得したくはありません。してしまうとスロット・マシーンはユーザの持ち点を二重に反映してしまう上に余計な通信をすることになります。}最初の試みを覚えていますか。独自のちょっとしたモック・フレームワークを作成した時のことです。その時点では実用的な解決策と思えたかも知れませんが、このような相互作用をテストするのにどれだけのコードが必要となるか想像してみて下さい。議論のために以下のスタブを使った欠点のある方法を見て下さい。}このテストでは一度ネットワークのスタブが呼び出されると以降の呼び出し時にはエラーを返すようにすることでネットワーク・クライアントが一度しか呼び出されないことを確認しています。テスト対象のオブジェクトを制御することでアサーションを行おうとしているという点でこのテストにはちょっとした問題があります。テスト対象のシステムがネットワークのスタブを複数回呼び出すとして、(テスト対象のシステムが)投げられた例外を握り潰してしまっているとしたら、テスト実行部は例外が発生したことを知ることができないのでテストは失敗することがありません。複雑な独自のモック・フレームワークを作ることでこの問題を回避することは出来ますが、このような場合はJsMockのような一般的な目的向けに作成されたものを使う方が簡単なのです。JsMockはメソッドの呼び出しとパラメータのテストをする機能だけを提供しているわけではありません。次のコードはネットワーク障害の場合にスロット・マシーンがどのように振舞うのかを再現したものです。}ここではネットワーク障害の場合にスロット・マシーンが"お行儀良く"失敗することを検証しています。上記の例はユニット・テストがシステム統合テストより優れている場合の好例です。品質保証/リリースの度に全てのシステム統合箇所について手動でネットワーク障害を再現するのにどれだけの時間と予算が必要となるか想像出来るでしょうか。ここまででgetBalanceメソッドの実装は以下のようになっています。}};モックの欠点の一つは、少なくてもそのままだと、スタブと比較してテスト対象のシステムと密結合してしまうという点です。テスト対象のシステムが想定通りの振舞いをしなくなったらテストが失敗して欲しいでしょうが、実装の詳細を隠ぺいするためには修正の度にテストが失敗するのは避けたいことでしょう。この状況を改善するためにJsMockではユルイ表現を用意しています。実は既にこの例を紹介しています。ネットワークのモック・オブジェクトを作成した際に以下のようなコードを書きました。TypeOf.isA(Function));2つ目の引数でどの関数がコールバックされるかまでは特定しませんでした。コールバック関数がセットされることだけを確認しました。これらの期待値をさらにユルイ設定にしたければ以下のようにすることも出来ます。TypeOf.isA(Function));もしネットワーク・クライアントのモック・オブジェクトのsendメソッドに渡された実際のコールバック関数を参照する必要があれば、JsMockフレームワークの提供するandStubメソッドを使って以下のように書くことも出来ます。);depositCallback({responseText:"10"});話を続ける前にモック・オブジェクトについて二点注目する点があります。それぞれのテストがMockControlのverifyメソッドをどのように呼んで終了しているのか注意して下さい。これは重要なことです。verifyメソッドを呼んでいないユニット・テストは処理に失敗してはいけないユニット・テストです。多くの開発者が、いくつかの標準的なユニット・テスト関数を実装した後で、verifyメソッドの呼び出しを各テスト関数からtearDown関数へ移動した方がいいという結論に至ります。これによって数行のコードが削減され各テスト関数の最後にこの重要な呼び出しを行うことを覚えなければならないことから解放されますが、一方で新たな問題をもたらします。tearDownで発生した例外はテスト内部で発生した最初の例外によって隠蔽されてしまうのです。2つ目の落とし穴は、モック・オブジェクトを使い慣れない開発者はしばしば過剰にモック・オブジェクトを利用してしまうということです。言うと、そのような開発者はモック・オブジェクトをスタブの代わりとして使ってしまうということです。スタブは状態に依存するテストに、モックは振舞いに依存するテストに使いましょう。勝つ場合のシナリオ・テストこれまでに学習したことを全て使って以下のシナリオに対するテストを作りましょう。このテストではユーザが一旦スロットに負けた後で勝つ状況をシミュレーションしています。reelsStub[2].src);}drw.SlotMachineクラスのplayメソッドの実装は以下のようになります。--this.balance;};そして最後に実際に稼働するスロット・マシーンの実証コードになります。DeWind氏が作成した完全な機能を有するJavaScript向けのモック・オブジェクト・ライブラリです。JsUnitはクライアント・サイド(ブラウザ内)のJavaScriptのためのユニット・テスト・フレームワークです。Fowler氏による記事です。Steele氏がJavaScriptで作成した関数型プログラミング用のライブラリです。Fowler氏による記事です。Trading(リンク),で勤務しています。Dennis氏はライター兼プレゼンターでありオープン・ソース・コミュニティの活動的なメンバでもあります。毎週火曜日に前週のまとめコンテンツがお送りいたします。25万人ものシニアデベロッパーのコミュニティーにぜひご参加ください。サンプルを見るあなたのメールアドレスはこちら国を選んでください。プライバシーポリシーに従って私の個人情報を扱うことに同意します。登録するとさまざまなことができます。アカウント登録をしてInfoQをお楽しみください。あなたの意見をお聞かせください。毎週火曜日に前週のまとめコンテンツがお送りいたします。25万人ものシニアデベロッパーのコミュニティーにぜひご参加ください。サンプルを見る様々なイノベーターとアーリーアダプターがお送りするテクノロジーの概要を見る。自分がまだ知らないことに気づいていないと知るあなたが興味のあるトピックスをいつでも最新な情報に。あなたのメールアドレスはこちら国を選んでください。プライバシーポリシーに従って私の個人情報を扱うことに同意します。よい世界へ私たちが暮らす世界を大切に思い、よりよいものにしたいと考えています。人のためのソフトウェア開発を加速し私たちのミッションを実現することで、この思いを成し遂げようとしています。私たちは利益の1%をさまざまな慈善団体に寄付しています。会社として、また従業員として、そうしたことの価値を強く信じているからです。with.プライバシーBTあなたのプロファイルは最新ですか?プロフィールを確認してアップデートしてください。アドレス*Eメールを変更すると確認のメールが配信されます。会社名:現在の会社名をご入力ください。Other組織規模:現在の組織規模をご入力ください。2,501+国:現在の国を設定してください。Zimbabwe都道府県:現在の都道府県に設定してください。次の都道府県にアップデートする:ニュースレターを購読しますか?インダストリーメールを購読しますか?本Eメールに登録すると、以前より関心のあったトピックの関連情報をお送りする場合がございます。詳細はこちらのプライバシーポリシーをご覧ください。newsletter?新しいメールアドレスに確認用のメールを送信します。このポップアップ画面は自動的に閉じられます。