fukuoka.ex代表のpiacereです
ご覧いただいて、ありがとうございます
JavaScriptのテスティングフレームワーク「Jest」を使って、プレーンJSとVue.jsのテストを行ってみます
TDD(Test Driven Development)の流れで実施していきます
npmのインストール
npmを利用可能にするため、下記から適宜Node.jsをインストールしてください
https://nodejs.org/ja/download/
package.jsonを作成
適当なフォルダを掘って、その配下に、下記ファイルを作成します
{
"scripts":
{
"test": "jest"
}
}
Jestのインストール
package.jsonを作ったフォルダ配下に移動し、シェル/コマンドプロンプトで、以下コマンドを実行します
npm install --save-dev jest
(なお、npmの代わりにyarnを使ってもOKですが、ここでは解説は割愛するので、分かる方だけ自己解決してください)
テストを作成
TDDをするので、まずテストを作成します
expect()に実測値(actual)を入れ、それをtoBe()で期待値(expected)と比較することで、「assertEquals」のような動きになります
Jestでのテストファイルは、ファイル名に「test」もしくは「spec」を入れると、テスト実行対象になります
テスト対象メソッドとして、add()という、足し算を行うメソッドを想定します(ただし、TDDするので、この時点ではロジック自体を作りません)
test( '1 + 2 = 3', () =>
{
expect( add( 1, 2 ) ).toBe( 3 )
} )
テストを実行(Redパターン)
以下コマンドでテストを実行します
npm test
ロジックが無いので、当然、まっ赤っかのテスト失敗(Red)になります
ロジックを追加し、テストを実行(Greenパターン)
ロジックを実装します(現在のテストを通す、最も小さい実装を行います)
なお、module.exportsで指定するのは、メソッド名です
function add( a, b )
{
return 3;
}
module.exports = add;
TDDに慣れていない方だと、「いやいや、そんなロジック作らないでしょ」と言いそうですが、より複雑なケースや、ロジックの組み合わせをする中で、「現在、詳細に実装しなくても、取り敢えずの値を返してくれればOK」というシチュエーションは、案外あります
そういう場合、上記のような、ダミー実装をして、その他の実装を進めるパターンも往々にしてあります(流石にここまで簡単だと「実装しようよ」となりますけど、あくまで実装し切らない状況もある、というTDDの例です)
テスト側も、実装を呼べるよう、requireを追加します
const add = require( './sample' )
test( 'add', () =>
{
expect( add( 1, 2 ) ).toBe( 3 )
} )
改めて、テストを実行します
npm test
テスト追加でRedになり、ロジック改修(Refactoringパターン)
テストを追加します
const add = require( './sample' )
test( 'add', () =>
{
expect( add( 1, 2 ) ).toBe( 3 )
expect( add( 2, 3 ) ).toBe( 5 )
} )
改めて、テストを実行します
npm test
ロジックをリファクタリングします
function add( a, b )
{
return a + b;
}
module.exports = add;
改めて、テストを実行します
npm test
なお、2ケースのテストを実施していますが、実行結果には、「1 passed」と出ているので、これを2ケースにしたい場合は、以下のようにテストメソッドを別々にします
const add = require( './sample' )
test( 'add 3', () =>
{
expect( add( 1, 2 ) ).toBe( 3 )
} )
test( 'add 5', () =>
{
expect( add( 2, 3 ) ).toBe( 5 )
} )
参考:テストを通す最低限の実装とは?
ちなみに、「テストを通す最低限の実装」という観点だと、実は、こんな実装もあり得ます
function add( a, b )
{
return a == 1 ? 3 : 5;
}
module.exports = add;
「なんだこりゃ?」という実装に見えますが、こういう発想を通して、「最低限のロジック実装」とは何なのか、を考える思考プロセスは、とても大事です
この感覚が分からないと、ムダに汎用性が高い、とか、やたらロバストなロジックを、「本当に必要となる前に」書いてしまい、改修やエンハンスがやりにくくなったり、延々と使いもしないロジックをメンテナンスする…といった罠にハマります
こうした、「技術的負債」を作らないための考え方が、TDD/アジャイル開発の始祖である「eXtreme Programming」では、「YAGNI(You ain't gonna need it)」という原則として挙げられています
Vue.jsのメソッドをテストする(Redパターン)
ここまでは、プレーンJSのテストだったので、今度は、Vue.jsのメソッドをテストします
まず、JestでVue.jsを使えるようにします
npm add vue jest
同フォルダ配下にテストを追加します
const app = require( './vue_sample' )
test( 'vue_add 3', () =>
{
expect( app.vue_add( 1, 2 ) ).toBe( 3 )
} )
test( 'vue_add 5', () =>
{
expect( app.vue_add( 2, 3 ) ).toBe( 5 )
} )
中身が空のvue_sample.jsも作っておきます
テストを実行すると、プレーンJS用とVue.js用の両方のテストが走ります
npm test
プレーンJS用テストは成功し、Vue.js用テストはロジック未実装のため失敗します
Vue.jsのメソッドを追加し、テストする(Greenパターン)
普通のWebページに適用するのと同じようなVue.jsでロジックを実装します(リファクタリングはしないパターンで行きます)
const Vue = require( 'vue' )
var app = new Vue
( {
el: '#app',
data:
{
},
methods:
{
vue_add: function( a, b )
{
return a + b
},
},
} )
module.exports = app
テストを実行します
npm test
テストは成功しますが、「#app」は未定義のため、warningが出ています
気になるときは、el部をコメントアウト(もしくはコンポーネント化)してください
…
var app = new Vue
( {
// el: '#app',
data:
…
補足:axiosでのAPI呼出をテストする際の注意点
Vue.jsで、API呼出に利用する「axios」のテストを書く際は、前段でJestにaxiosを導入します
npm add axios jest
また、非同期呼出のままだと、テスト実施時のexpectで空振りとなるため、async/awaitの付け忘れに注意してください
const axios = require( 'axios' )
test( 'axios_get', async () =>
{
var results = []
await axios.get( 'https://qiita.com/api/v2/items?query=elixir' )
.then( response => { results = response.data } )
expect( results.length ).toBe( 20 )
} )
終わり
こんな感じで、Jestを使うと、気軽にプレーンJSも、Vue.jsも、TDDしていけます
なお、Jest自体は、特にJSフレームワークを選ぶものでは無い、JavaScriptであれば使えるテスティングフレームワークですので、ReactやAngularをお使いの方でもトライしてみてください
p.s.「いいね」よろしくお願いします
ページ左上の や のクリックを、どうぞよろしくお願いします
ここの数字が増えると、書き手としては「ウケている」という感覚が得られ、連載を更に進化させていくモチベーションになりますので、もっとElixirネタを見たいというあなた、私達と一緒に盛り上げてください!