40歳からのキャリアチェンジ

20代はエンジニア・PM、30代はWeb系エンジニア向けのキャリアアドバイザー。40代の今はフリーランスで開発含めて色々やってます。技術ネタとしてはRuby/RailsとJavaScript関連あたり

CoffeeScriptとjasmine-titaniumではじめるTDDのテストケース編

前回、環境構築についてまとめたので、今回は簡単なテストケースを例にあげながらまとめておこうと思います

Ti.Network.HTTPClientに関するテストケースを例にする

Qiita API の連携処理の実装にモヤモヤしたものを抱えていたこともあるので、Ti.Network.HTTPClientに関するテストケースを例にしてみようと思います

ひとまずのお題として「ネットワークの接続が確立しているかどうか」というテストケースについて以下順番にまとめてみようと思います

JasmineがRSpecライクの影響を受けているらしいというのを以前読んだ記憶があり、それと別のところでRSpec入門記事としてRSpec の入門とその一歩先へというエントリがとてもわかりやすかったのでこの記事の方法を取り入れながら以下にまとめていきます

仮実装までの流れ

テストとなるxhrSpec.coffeeというファイルを準備して以下をまず記述しました

xhrSpec.coffee

describe 'httpClient', ->
  it 'should be true when network connection is established', ->
    httpClient = require('httpClient')
    xhr = new httpClient()
    expect(xhr.isConnected()).toBe true

この状態でbuildすると「Couldn't find module: httpClient」という感じで当然のことながら怒られます。

[INFO] start
[DEBUG] Application booted in 57.797968 ms
[DEBUG] Jasmine: 
[DEBUG] Jasmine: httpClient===========================================
[INFO]  Jasmine: F
[ERROR] Jasmine: httpClient
[ERROR] Jasmine:   - should be true when network connection is established ... Failed.
[ERROR] Jasmine:     => Expected undefined to be true.
[ERROR] Jasmine: Suite TOTAL: 0 of 1 expectation passed.
[ERROR] Jasmine: Runner TOTAL: 0 of 1 spec passed.
[INFO]  Jasmine: Runner Finished.
[DEBUG] Jasmine: 

ひとまず、coffeeディレクトリ配下にhttpClient.coffeeをこのような感じで作成します

httpClient.coffee

class httpClient
  constructor: () ->
    console.log 'httpClient jasmine test start'

module.exports = httpClient

再度buildします

[DEBUG] Jasmine: httpClient===========================================
[INFO]  Jasmine: F
[ERROR] Jasmine: httpClient
[ERROR] Jasmine:   - should be true when network connection is established ... Failed.
[ERROR] Jasmine:     => TypeError: 'undefined' is not a function (evaluating 'xhr.isConnected()')
[ERROR] Jasmine: Suite TOTAL: 0 of 1 expectation passed.
[ERROR] Jasmine: Runner TOTAL: 0 of 1 spec passed.
[INFO]  Jasmine: Runner Finished.

今度は「Jasmine: => TypeError: 'undefined' is not a function (evaluating 'xhr.isConnected()')」となりました。

httpClientクラスには、まだisConnected()を実装していないので、まぁ当たり前ですね。

そのためひとまずisConnected()を以下のように仮実装しました。仮実装については少し長いですが今回参考にしているRSpec の入門とその一歩先へというエントリがから少し引用させていただきます

仮実装とは、テストのテスト、と考えることが出来ます。例えば今回の例で、 true を返すという絶対テストが通るだろうという実装コードを書いても、テストが失敗したらどうでしょうか? それは、テストコードの方にこそバグが潜んでいることを示唆しています。仮実装で成功しないテストは、本実装でも成功しないでしょう。本実装でもテストが通らなかったときに、なぜテストが通らないのか本実装を長い時間デバッグした結果、テストコードが間違っていたのでは目も当てられません。

httpClient.coffee

class httpClient
  constructor: () ->
    console.log 'httpClient jasmine test start'

  isConnected:() ->
    return true				
module.exports = httpClient

これでbuildすると以下のようにひとまずテストはパスしました!

[INFO]  Jasmine: .
[INFO]  Jasmine: Runner TOTAL: 1 of 1 spec passed.
[INFO]  Jasmine: Runner Finished.

しっかりと実装する

ネットワーク接続状況を確認するのに一番手軽なのはTitanium.Network.onlineの値を調べることかと思います。

これを使って以下のように実装しました

httpClient.coffee

class httpClient
  constructor: () ->
    console.log 'httpClient jasmine test start'

  isConnected:() ->
    return Ti.Network.online

module.exports = httpClient

インターネット接続できている状況でbuildするとこのようになります

[INFO]  Jasmine: .
[INFO]  Jasmine: Runner TOTAL: 1 of 1 spec passed.
[INFO]  Jasmine: Runner Finished.

参考までにMacのネットワーク接続をオフにして、buildするとこのようになります

[DEBUG] Jasmine: httpClient===========================================
[INFO]  Jasmine: F
[ERROR] Jasmine: httpClient
[ERROR] Jasmine:   - should be true when network connection is established ... Failed.
[ERROR] Jasmine:     => Expected false to be true.
[ERROR] Jasmine: Suite TOTAL: 0 of 1 expectation passed.
[ERROR] Jasmine: Runner TOTAL: 0 of 1 spec passed.
[INFO]  Jasmine: Runner Finished.

「ネットワークの接続が確立しているかどうか」というテストケースがサンプルとして良いモノなのかどうか正直なんともいえませんが、少なくともこれでCoffeeScriptとjasmine-titanium使ってテスト書ける環境は整ったので、これまでモヤモヤしていたQiita API連携処理の所について積極的にテストを書いて、モヤモヤを解消してこうと思います