Test Drivenでフォーマッターの実装
今回はTest Driven(テストを先に書く方式)でフォーマッターの機能を実装します。フォーマッターとは、データを所定の表示形式になるように整形する機能です。
以下のチュートリアルを参照します。
Step 2: A First Unit Test
Step 3: Adding the Price Formatter
「チュートリアルを見ながらTest Driven Developmentを体験する」シリーズの目次はこちら
QUnitテスト用の設定を確認
今回のテストで使うファイルは、test/unitフォルダの配下に格納されています。
QUnitテストを実行するときはunitTests.qunit.htmlを実行します。
ここからunitTests.qunit.jsが呼ばれ、さらにAllTests.jsが呼ばれるという構成になっています。テンプレートからアプリを作った場合も同じ構成となります。(ベストプラクティス)
各ファイルの中身を見てみます。
unitTests.qunit.js
QUnitを開始しています。
AllTests.js
テスト対象の機能(formatterなど)を呼ぶjsファイルをdependencyに設定しています。
model/formatter.js
Number unitのテストケースが入っています。
model/models.js
デバイスモデル作成のテストケースが入っています。
お気づきのように、テスト用のフォルダ、ファイルは、テスト対象機能と同じ構成になっています。これが慣例だそうです。
どこに手を入れればいいの?
AllTests.jsとテスト対象の機能を呼ぶjsファイルに手を入れます。
AllTests.jsはテスト対象のjsファイルを追加した場合だけ変更が必要で、今回は変更しません。
Test Driven Developmentのステップ
Test Driven Developmentは以下の順序で進みます。
- テストを書く
- 機能を実装する
- テストを実行する
- 機能をアプリに組み込む
実装する機能
条件
1. テストを書く
仕様が決まったところで早速テストを書きます。
フォーマッターのガラだけ作成
テスト実行用jsから呼べるように、フォーマッターのガラだけ先に作っておきます。
webapp/model/formatter.js
priceState: function(){
}
QUnitテストを書く
PriceState用のモジュール(テストの単位)と、priceStateを呼ぶミニ関数を定義します。この関数はこの後、色々な値でテストを実行するときに使います。
assertionでPriceStateから返された値と想定結果を比較し、一致すればOKとなります。
webapp/test/unit/model/formatter.js
QUnit.module("Price State");
function priceStateTestCase(oOptions){
// Act
var sState = formatter.priceState(oOptions.price);
// Assert
oOptions.assert.strictEqual(sState, oOptions.expected, "The price state was correct");
}
次に、上記の関数を呼び出してテストを実行します。テストすべき条件をコメントで先に書いておくと良いと思います。
//price < 50: Status is green (Success)
//price >= 50 and price < 250: Status is normal (None)
//price >= 250 and price < 2000: Status is orange (Warning)
//price >= 2000: Status is red (Error)
コメントの下にテストを書きます。
//price < 50: Status is green (Success)
QUnit.test("Should format the products with a price lower than 50 to Success", function(assert){
priceStateTestCase.call(this, {
assert: assert,
price: 42,
expected: "Success"
});
});
残りのケースも同様に、目的に合ったpriceと想定結果の組を与えます。
//price >= 50 and price < 250: Status is normal (None)
QUnit.test("Should format the products with a price of 50 to Normal", function(assert){
priceStateTestCase.call(this, {
assert: assert,
price: 50,
expected: "None"
});
});
QUnit.test("Should format the products with a price betweenn 50 and 250 to Normal", function(assert){
priceStateTestCase.call(this, {
assert: assert,
price: 112,
expected: "None"
});
});
//price >= 250 and price < 2000: Status is orange (Warning)
QUnit.test("Should format the products with a price betweenn 250 and 2000 to Warning", function(assert){
priceStateTestCase.call(this, {
assert: assert,
price: 798,
expected: "Warning"
});
});
//price >= 2000: Status is red (Error)
QUnit.test("Should format the products with a price higher than 2000 to Error", function(assert){
priceStateTestCase.call(this, {
assert: assert,
price: 2001,
expected: "Error"
});
});
実行結果
PriceSateのテスト結果は全てエラーになりました。まだ機能を実装していないので想定通りです。
2. 機能を実装する
フォーマッターを実装します。
priceState: function(iPrice){
if(iPrice < 50){
return "Success";
}else if(iPrice >= 50 && iPrice < 250){
return "None";
}else if(iPrice >= 250 && iPrice < 2000){
return "Warning";
}else{
return "Error";
}
}
3. テストを実行する
実装後に改めてテストします。今回は正常終了します。
これで機能が正しく実装できていることが確認できました。
4. 機能をアプリに組み込む
ObjectNumberのコントロール(priceを出しているところ)に、stateという属性を追加します。ここにpriceStateを設定します。
view/Worklist.view.xml
<ObjectNumber
number="{
path: 'Price',
formatter: '.formatter.numberUnit'
}"
state="{
path: 'Price',
formatter: '.formatter.priceState'
}"
unit="{Currency}"
/>
実行結果
Priceの色が金額に応じて変わりました。実装と同時にテストも終わりました!
関連記事
チュートリアルを見ながらTest Driven Developmentを体験する (1) 概要
チュートリアルを見ながらTest Driven Developmentを体験する (3) OPA5