JavaScript
test
テスト
jasmine
testing

Jasmineによるテスト対象の関数内に関数内未定義の変数があったときの対処方法

当記事におけるJavaScriptのコードは、クライアントサイドで動くことを想定されているものとします。

Jasmineのversionは 3.0 以上とします(3.0未満に関しては特に動作を確認してないため)。

関数内にglobal変数が入っている場合にテストを行う事態に遭遇し、そのときにおこなった方法の備忘録です。

通常の場合

JavaScriptで以下の関数をテストしたいとします。

calc.js
...

function add(x, y){
  return x + y;
}

...

このとき、add 関数に対するテストは以下の様に書くことができます。

calc-spec.js
describe("calcのテスト", function() {
  it("1 + 2 は 3", function() {
    expect(add(1,2)).toBe(3);
  })
});

テスト対象のjsの関数がこのようになっていればいいのですが、レガシーコード(テストがないコード)に触れていると、関数内に関数内で未定義の変数が入っている場合があります。

関数内に未定義の変数がある場合

さて、以下のような関数があったとします。

calc.js
...

function add(x, y){
  return (x + y) * coef;
}

...

このcoefという変数ですが、add関数の内部では定義していません。

簡略化してますが、実際のところ、いろんな歴史的な経緯により、100行くらいの関数内の各所に coef のような変数が埋まっていて、困った経験はあるのではないでしょうか?

この関数に対するテストとして以下の様なコードを試しに書いてみます。

calc-spec.js
describe("calcのテスト", function() {
  it("1 + 2 は 3", function() {
    const coef = 0.1;
    expect(add(1,2)).toBe(0.3);
  })
});

そして、jasmineを実行してみると、

ReferenceError: coef is not defined

となり、動きません。これは当然で、 coefのスコープが、it内の範囲しか適用されず、add関数では未定義となるためです。

テストを正常に動かす方法として以下の様にすれば動きます。

calc-spec.js
describe("calcのテスト", function() {
  it("1 + 2 は 3", function() {
    coef = 0.1;
    expect(add(1,2)).toBe(0.3);
  })
});

このcoefですが、window直下のオブジェクトとして定義されています。

この副作用として、 1 + 2 は 3 というテストケース以降のテストにおいては、 window直下に coef は定義されてままの状態になってしまいます。

実際のテストにおいては、 window.coef ということを明示しておくと、可読性が高いかと思います。

calc-spec.js
describe("calcのテスト", function() {

  it("1 + 2 は 3", function() {
    window.coef = 0.1;
    expect(add(1, 2)).toBe(0.3);
  })

});