SONICMOOV Googleページ

ブラウザだけではじめるミニマムテスト駆動開発

ブラウザだけではじめるミニマムテスト駆動開発

  • このエントリーをはてなブックマークに追加

こんにちわ、ソニックムーブのセイカイです。

この投稿はソニックムーブ Advent Calendar 201318日目の投稿になります。
さて、今回はテスト駆動開発について書いてみることにします。

テスト駆動開発と聞くと、割とプログラマっぽい響きに敬遠してしまうひともいるかもしれませんが、全然そんなことはないですよ。
ということで簡単に手の届きやすいところからということでJavaScriptを用いてライブラリ等を使わずブラウザだけではじめて見ましょう。

前置き

ちなみにテスト駆動開発はWikiによると

テスト駆動開発 (てすとくどうかいはつ、test-driven development; TDD) とは、プログラム開発手法の一種で、プログラムに必要な各機能について、最初にテストを書き(これをテストファーストと言う)、そのテストが動作する必要最低限な実装をとりあえず行った後、コードを洗練させる、という短い工程を繰り返すスタイルである。

簡単に言うと、先に要件ベースでテストコード書いて、それが通る実装をする、実装したらテストが通る部分を担保したままリファクタリングすれば良いですね的なノリですね。

メリットでメリット

「要件に対して正しく動作する」という判定を自動化することで、コードの変更が起こった時や修正時に、この部分を担保しやすいというのがテストコードを書く主なメリットです。
すなわち、コードの品質を担保しやすいって話ですね。

デメリットとしてはテストコード自体をメンテナンスしないと、更新されない仕様書と同じく意味の無いものになりますので、その分のコストは見込む必要があることでしょうか。

また、テストコードは適切な粒度で書かないと、細か過ぎると手間が増え、大雑把過ぎるとあまり意味が無いので注意です。

続きを読む

テストコード

上記におけるテストコードは主に、assertというクラスなり関数なりを利用するものが主流です。今回は、ブラウザに実装されているconsole.assertを使ってみます。

console.assert

console.assertは第一引数が評価式で、第二引数が評価式がfalseを返した時に出力されるメッセージになります。

console.assert(true, "失敗時のメッセージ");

上記は評価式がtrueになるので、何も起こりません。

console.assert(false, "失敗時のメッセージ");

上記は、エラーと共に「失敗時のメッセージ」が出力されます。

準備

今回はとりあえずFizzBuzzのプログラムをテスト駆動で書いてみることにします。
ちなみに、FizzBuzzは「1 から順に数を数えて、その数が 3 で割り切れるならばFizz と、5 で割り切れるなら Buzz と言うゲーム。3 でも 5 でも割り切れる場合は、FizzBuzz の順に言う」

今回は1から100までをカウントしてみます。

ファイル構成は下記の用にして空のjsファイルを2つと、htmlファイルを用意します。

index.html
 ┣fizzBuzz.js
 ┗testFizzBuzz.js

index.htmlは下記の用に2つのjsファイルを読み込みます。

<!DOCTYPE HTML>
<html lang="en-US">
<head>
	<meta charset="UTF-8">
	<title>FizzBuzz</title>
</head>
<body>
	<script type="text/javascript" src="fizzBuzz.js"></script>
	<script type="text/javascript" src="testFizzBuzz.js"></script>
</body>
</html>

これで準備は完了です。

プログラムの全体

数字をカウントアップする過程で下記の処理を行うのがプログラムの要件となります。

  • 3で割り切れる=>「Fizz」を出力
  • 5で割り切れる=>「Buzz」を出力
  • 3でも5で割り切れる=>「FizzBuzz」を出力
  • 上記以外=>そのまま数字を出力

縮めれば1行で書けるコードですが、テストを前提にというところでカウント毎の数字を処理する関数をつくり、その結果を評価する方式とします。

STEP1:Fizz

fizzBuzz.jsに下記のようなコードを書きます。

function fizzBuzz(num) {
    return "";
}

fizzBuzz関数はとりあえず空文字列を返す様にしておきます。

次にtestFizzBuzz.jsにテストコードを書きます。
今回は簡単な用件なので一気に書いてしまいます。

//3で割り切れる=&gt;「Fizz」が返ってくる
console.assert( fizzBuzz( 3 ) === 'Fizz', '1' );
console.assert( fizzBuzz( 33 ) === 'Fizz', '2' );

//5で割り切れる=>「Buzz」が返ってくる
console.assert( fizzBuzz( 5 ) === 'Buzz', '3' );
console.assert( fizzBuzz( 50 ) === 'Buzz', '4' );

//3でも5で割り切れる=>「FizzBuzz」が返ってくる
console.assert( fizzBuzz( 15 ) === 'FizzBuzz', '5' );
console.assert( fizzBuzz( 45 ) === 'FizzBuzz', '6' );

//上記以外=>そのまま数字が返ってくる
console.assert( fizzBuzz( 4 ) === '4', '7' );
console.assert( fizzBuzz( 17 ) === '17', '8' );

※今回は説明用に失敗時のメッセージに番号を入れていますが、本来は処理結果に対して分かりやすいメッセージを入れる方が良いです。

index.htmlをブラウザで開くと、fizzBuzz関数は期待した値を返さないので全てのテストに失敗しエラーメッセージが出力されます。

とりあえず、3で割り切れる場合Fizzを返す様にします。

function fizzBuzz(num) {
    var result;
    if ( num%3 === 0 ) {
        result = 'Fizz';
    }
    else {
        result = "";
    }
    return result;
}

これで、とりあえずテストが2まで通りますね。

STEP2:Buzz

こんどは5で割り切れる場合Buzzを返す様にします。

function fizzBuzz(num) {
    var result;
    if ( num%3 === 0 ) {
        result = 'Fizz';
    }
    else if ( num%5 === 0 ) {
        result = 'Buzz';
    }
    else {
        result = "";
    }
    return result;
}

これで、とりあえずテストが4まで通りますね。

STEP3: FizzBuzz

次は、3でも5で割り切れる数字がFizzBuzzを返す様に実装を見直します。
基本的には、この繰り返しで順にテストが通る様にしていきます。

function fizzBuzz(num) {
    var result;

    if ( num%3 === 0 && num%5 === 0 ) {
        result = 'FizzBuzz';
    }
    else if ( num%3 === 0 ) {
        result = 'Fizz';
    }
    else if ( num%5 === 0 ) {
        result = 'Buzz';
    }
    else {
        result = "";
    }
    return result;
}

まだ7と8が失敗するので実装を見直します。

function fizzBuzz(num) {
    var result;

    if ( num%3 === 0 && num%5 === 0 ) {
        result = 'FizzBuzz';
    }
    else if ( num%3 === 0 ) {
        result = 'Fizz';
    }
    else if ( num%5 === 0 ) {
        result = 'Buzz';
    }
    else {
        result = String(num);
    }
    return result;
}

これで全てのテストを通過しますね。
最後にカウントアップの処理を追加して完成です。

for(var i=1; i < 100; i++) {
    console.log( fizzBuzz( i ) );
}

以降要件が追加されれば、テストコードを追加し、実装を見直すという手順で修正していきます。

今回は単純なものでしたので、「コードを洗練させる」という部分には触れていませんが、とりあえずこんな感じで、日々簡単なところからテストコードを書く習慣をつけていくことで、コードの品質が上げていけるのではないでしょうか。

応用

今回は簡単なケースですので、単純なテストコードとなりましたが、複雑なものであれば前後に処理が入るケースもあるかと思います。

例えばFizBuzzの結果をDOMに追加することを考えた場合、対象となるノードの子の数や、追加された要素のinnerHTML等を評価すれば良いのではないでしょうか。

まとめ

  • テストは習慣付け
  • 簡単なものならブラウザだけでも出来る(JS)
  • テストコードもメンテナンスを
  • ロジックを上手く切り離せればテストも書きやすい

テストに興味が湧いた方は、テスト用のフレームワーク等もありますので、色々触ってみると良いかもしれません。

  • このエントリーをはてなブックマークに追加

記事作成者の紹介

セイカイ(フロントエンジニア)

新規事業推進部のセイカイです。猫を飼い始めて幸せな毎日を送っています。

関連するSONICMOOVのサービス

フロントエンドエンジニア募集中!

×

SNSでも情報配信中!ぜひご登録ください。

×

SNSでも
情報配信中!
SONICMOOV Facebookページ SONICMOOV Twitter SONICMOOV Googleページ
フロントエンドエンジニア募集中!

新着の記事

mautic is open source marketing automation