chai-iterator: 反復可能なオブジェクトに対するアサーション

Version Build Coverage Dependencies

コンテンツ

概要

chai-iteratorChai アサーションライブラリを、反復可能な オブジェクトをテストするためのメソッドで拡張しています。 ES2015 仕様 で導入された反復可能なオブジェクトには @@iterator メソッドがあり、これにより for...of ループを使用してオブジェクトを反復処理できます。多数の組み込み 型がデフォルトで反復可能である一方、カスタム反復可能オブジェクト も定義できます。chai-iterator を使用すると、こうしたオブジェクトをすべて簡単にテストできます。

chai-iterator は不要な場合があります

配列スプレッド構文 は、多くの場合反復可能なものをテストする最適な方法です。ただし、chai-iterator は非常に長い(または無限)反復可能なもののうち、一部をテストするときに非常に役立ちます。

基本的な使用方法

Chai Iterator を使用して行えるアサーションの非常に包括的なサンプルを以下に示します。 expect または assert を簡単に使用できますが、ここでは Chai の should() アサーションスタイル を使用して、単に違いを示します。

[2, 3, 5].should.be.iterable;

[2, 3, 5].should.iterate.over([2, 3, 5]);
[2, 3, 5].should.iterate.from([2, 3]);
[2, 3, 5].should.iterate.until([3, 5]);

[2, 3, 5].should.iterate.for.lengthOf(3);
[2, 3, 5].should.iterate.for.length.above(2);
[2, 3, 5].should.iterate.for.length.below(4);
[2, 3, 5].should.iterate.for.length.of.at.least(3);
[2, 3, 5].should.iterate.for.length.of.at.most(3);
[2, 3, 5].should.iterate.for.length.within(2, 4);

[2, 3, 5].should.not.iterate.over([1, 2, 3]);
[{n: 2}, {n: 3}].should.deep.iterate.from([{n: 2}]);

配列に限定しません。反復可能なオブジェクトはどれでもテストできます。

'abcde'.should.iterate.until(['c', 'd', 'e']);

そして、任意の反復可能なものを期待される値として渡すこともできます。

'abcde'.should.iterate.until('cde');

ユーザー定義の反復可能オブジェクト

chai-iterator は、以下の クラス で構築されたオブジェクトなど、ユーザー定義の反復可能オブジェクト をテストするために最適に使用できます。

class Count {

  constructor(start=0, step=1) {
    this.start = start;
    this.step = step;
  }

  *[Symbol.iterator]() {
    for (let n = this.start; true; n += this.step) {
      yield n;
    }
  }
}

Count.prototype[@@iterator]() によって生成されるシーケンスは無限であり、値をいつまでも生成し続けます。それでも from() アサーションを安全に使用できます。期待される反復可能処理が完了するとすぐに終了するためです。

let tens = new Count(10, 10);

tens.should.be.iterable;
tens.should.iterate.from([10, 20, 30]);
tens.should.iterate.from([10, 20, 30, 40, 50]);

無限のシーケンスに対して over() または until() を使用しようとしないでください。前者は常に失敗し、後者は決して停止しません。

ジェネレーターと反復処理

フィボナッチ数列を生成しましょうフィボナッチ数列. ジェネレータ関数とは、Generatorオブジェクト、つまり反復子を兼ねたイテラブルを返す、単なる関数にすぎません。他のイテラブルと同様にGeneratorをテストできます。

function* fibonacci() {
  for (let [x, y] = [1, 1]; true; [x, y] = [y, x + y]) {
    yield x;
  }
}

fibonacci().should.iterate.from([1, 1, 2, 3, 5]);

ただし注意してください。イテレータは過去に戻ることができません。値が生成されると、それは永遠に失われます。したがって、以降の主張が通ります。

let fiborator = fibonacci();

fiborator.should.iterate.from([1, 1, 2, 3, 5]);
fiborator.should.iterate.from([8, 13, 21, 34]);

主張ごとに新しいGeneratorを構築する方が、通常はより適切です。

fibonacci().should.iterate.from([1, 1, 2, 3, 5]);
fibonacci().should.iterate.from([1, 1, 2, 3, 5, 8, 13]);

互換性

chai-iteratorでは、Symbol.iteratorが環境で利用可能である必要があります。 Nodeでは、バージョンがv4.0以降である必要があります。ほとんどのブラウザの最新バージョンは互換性がありますが、Webに直面するプロジェクトではほぼ確実にポリフィルを使用する必要があります。

Symbol.iteratorをネイティブでサポートしていない環境では、バベルポリフィルが1つのオプションです。より必要最小限に、次のようにcore-jsライブラリから2つのサブモジュールだけで済ますことができます。

require('core-js/es6/symbol');
require('core-js/fn/symbol/iterator');

インストール

npmを使用してchai-iteratorをインストールします。そしてもちろんChaiをインストールしてください。

npm install --save chai chai-iterator

セットアップ

chai-iteratorはNodeモジュール、AMDモジュールとしてインポートするか、HTML<script>タグに含めることができます。TypeScriptユーザーの場合は、宣言がパッケージにインストールされます。

ノード

Nodeのchai-iteratorを設定するには、バージョンがv4.0以降であることを確認してください。以前のバージョンでは@@iteratorメソッドのサポートがありません。

const chai = require('chai');
const chaiIterator = require('chai-iterator');

chai.use(chaiIterator);

AMD

chai-iteratorは次のようにAMDモジュール内に設定できます。

define((require, exports, module) => {
  let chai = require('chai');
  let chaiIterator = require('chai-iterator');

  chai.use(chaiIterator);
});

HTMLスクリプトタグ

chai-iteratorには<script>タグから含めることができます。 chai.jsの後にロードされると、Chaiは自動的にそれを使用します。

<script src="chai.js"></script>
<script src="chai-iterator.js"></script>

タイプスクリプト

TypeScript宣言はパッケージに含まれています。それらを使用するには、chai-iteratorがnpmでインストールされていることを確認し、宣言とその依存関係をtypingsを介してインストールします。chaiの宣言もインストールしてください。

typings install --save-dev npm~chai npm:chai-iterator

コンパイラオプションで、"target""es6"に設定するか、少なくともlib.es6.d.tsへの参照を含めてください。これで以下は機能するようになります。

import chai = require("chai");
import chaiIterator = require("chai-iterator");

chai.use(chaiIterator);

[2, 3, 5].should.iterate.over([2, 3, 5]);

Expect/Should API

アサーション

反復可能

ターゲットが反復可能オブジェクト、つまり@@iteratorメソッドを持つことをアサートします。

expect([2, 3, 5]).to.be.iterable;
expect('abcdefg').to.be.iterable;
expect(12345).not.to.be.iterable;

iterate.over(expected)

ターゲットが与えられたシーケンスの値を反復することをアサートします。deepフラグを設定して値を比較する際にディープイコールを使用します。

Param タイプ 説明
expected object 反復可能オブジェクト。
expect([2, 3, 5]).to.iterate.over([2, 3, 5]);
expect('abcdefg').to.itetate.over('abcdefg');
expect([2, 3, 5]).not.to.iterate.over([2, 3]);
expect([{n: 2}, {n: 3}]).to.deep.iterate.over([{n: 2}, {n: 3}]);

iterate.from(expected)

ターゲットが与えられたシーケンスの値を反復し始めることをアサートします。deepフラグを設定して値を比較する際にディープイコールを使用します。

Param タイプ 説明
expected object 反復可能オブジェクト。
expect([2, 3, 5]).to.iterate.from([2, 3]);
expect('abcdefg').to.iterate.from('abc');
expect([2, 3, 5]).not.to.iterate.from([3, 5]);
expect([{n: 2}, {n: 3}]).to.deep.iterate.from([{n: 2}]);

iterate.until(expected)

ターゲットが与えられたシーケンスの値で反復を終了することをアサートします。deepフラグを設定して値を比較する際にディープイコールを使用します。

Param タイプ 説明
expected object 反復可能オブジェクト。
expect([2, 3, 5]).to.iterate.until([3, 5]);
expect('abcdefg').to.iterate.until('efg');
expect([2, 3, 5]).not.to.iterate.until([2, 3]);
expect([{n: 2}, {n: 3}]).to.deep.iterate.until([{n: 3}]);

iterate.for.lengthOf(n)

ターゲットが正確にnの値を返すことをアサートします。

Param タイプ 説明
n number 正の整数
expect([2, 3, 5]).to.iterate.for.lengthOf(3);
expect('abcdefg').to.iterate.for.lengthOf(7);
expect([2, 3, 5]).not.to.iterate.for.lengthOf(7);

iterate.for.length.above(n)

ターゲットがn以上の値を返すことをアサートします。

Param タイプ 説明
n number 正の整数
expect([2, 3, 5]).to.iterate.for.length.above(2);
expect('abcdefg').to.iterate.for.length.above(5);
expect([2, 3, 5]).not.to.iterate.for.length.above(3);

iterate.for.length.below(n)

ターゲットがn未満の値を返すことをアサートします。

Param タイプ 説明
n number 正の整数
expect([2, 3, 5]).to.iterate.for.length.below(4);
expect('abcdefg').to.iterate.for.length.below(10);
expect([2, 3, 5]).not.to.iterate.for.length.below(3);

iterate.for.length.of.at.least(n)

ターゲットが少なくともnの値を返すことをアサートします。

Param タイプ 説明
n number 正の整数
expect([2, 3, 5]).to.iterate.for.length.of.at.least(2);
expect([2, 3, 5]).to.iterate.for.length.of.at.least(3);
expect([2, 3, 5]).not.to.iterate.for.length.of.at.least(4);

反復.for.長さ.of.最大(n)

ターゲットがn個の値で反復することをアサートします。

Param タイプ 説明
n number 正の整数
expect([2, 3, 5]).to.iterate.for.length.of.at.most(4);
expect([2, 3, 5]).to.iterate.for.length.of.at.most(3);
expect([2, 3, 5]).not.to.iterate.for.length.of.at.most(2);

反復.for.長さ.範囲内(最小, 最大)

ターゲットが最小最大の値の間、両端を含むで反復することをアサートします。

Param タイプ 説明
最小 number 正の整数
最大 number 正の整数
expect([2, 3, 5]).to.iterate.for.length.within(2, 4);
expect([2, 3, 5]).to.iterate.for.length.within(3, 3);
expect([2, 3, 5]).not.to.iterate.for.length.within(4, 7);

Assert API

アサーション

パラメータ

アサートメソッドのパラメータを以下に示します。

Param タイプ 説明
任意 任意の値です。
expected object 反復可能オブジェクト。
n number 正の整数です。
メッセージ 文字列 エラー時に表示するオプションのメッセージです。

反復可能である(, [メッセージ])

値が反復可能なオブジェクト、つまり、@@iteratorメソッドを持つオブジェクトであることをアサートします。

assert.isIterable([2, 3, 5]);
assert.isIterable('abcdefg');

反復可能でない(, [メッセージ])

値が反復可能なオブジェクトではなく、@@iteratorメソッドを持たないことをアサートします。

assert.isNotIterable(235);
assert.isNotIterable(true);

反復する(, 期待値, [メッセージ])

値が与えられた値のシーケンスを正確に反復することをアサートします。

assert.iteratesOver([2, 3, 5], [2, 3, 5]);
assert.iteratesOver('abcdefg', 'abcdefg');

反復しない(, 期待値, [メッセージ])

値が与えられた値のシーケンスを正確に反復しないことをアサートします。

assert.doesNotIterateOver([2, 3, 5], [1, 2, 3]);
assert.doesNotIterateOver('abcdefg', 'abc');

深層反復する(, 期待値, [メッセージ])

値が与えられた値のシーケンスを正確に反復し、かつ深い等価性を使用することをアサートします。

assert.deepIteratesOver([{n: 2}, {n: 3}], [{n: 2}, {n: 3}]);
assert.deepIteratesOver([[0, 2], [1, 3]], [[0, 2], [1, 3]]);

深層反復しない(, 期待値, [メッセージ])

値が与えられた値のシーケンスを正確に反復せず、かつ深い等価性を使用することをアサートします。

assert.doesNotDeepIterateOver([{n: 2}, {n: 3}], [{n: 5}, {n: 7}]);
assert.doesNotDeepIterateOver([[0, 2], [1, 3]], [[1, 3], [0, 2]]);

iteratesFromvalue expected [message])

値が与えられた値のシーケンスで反復を開始することをアサートします。

assert.iteratesFrom([2, 3, 5], [2, 3, 5]);
assert.iteratesFrom([2, 3, 5], [2, 3]);
assert.iteratesFrom('abcdefg', 'abc');
assert.iteratesFrom('abcdefg', '');

doesNotIterateFromvalue expected [message])

値が与えられた値のシーケンスで反復を開始しないことをアサートします。

assert.doesNotIterateFrom([2, 3, 5], [3, 5]);
assert.doesNotIterateFrom('abcdefg', 'cdef');

deepIteratesFromvalue expected [message])

値が与えられた値のシーケンスで反復を開始することを、深い等価性を使用してアサートします。

assert.deepIteratesFrom([{n: 2}, {n: 3}], [{n: 2}]);
assert.deepIteratesFrom([[0, 2], [1, 3]], [[0, 2]]);

doesNotDeepIterateFromvalue expected [message])

値が与えられた値のシーケンスで反復を開始しないことを、深い等価性を使用してアサートします。

assert.doesNotDeepIterateFrom([{n: 2}, {n: 3}], [{n: 5}]);
assert.doesNotDeepIterateFrom([[0, 2], [1, 3]], [[1, 3]]);

iteratesUntilvalue expected [message])

値が与えられた値のシーケンスで反復を終了することをアサートします。

assert.iteratesUntil([2, 3, 5], [2, 3, 5]);
assert.iteratesUntil([2, 3, 5], [3, 5]);
assert.iteratesUntil('abcdefg', 'efg');
assert.iteratesUntil('abcdefg', '');

doesNotIterateUntilvalue expected [message])

値が与えられた値のシーケンスで反復を終了しないことをアサートします。

assert.doesNotIterateUntil([2, 3, 5], [2, 3]);
assert.doesNotIterateUntil('abcdefg', 'cdef');

deepIteratesUntilvalue expected [message])

値が与えられた値のシーケンスで反復を終了することを、深い等価性を使用してアサートします。

assert.deepIteratesUntil([{n: 2}, {n: 3}], [{n: 3}]);
assert.deepIteratesUntil([[0, 2], [1, 3]], [[1, 3]]);

doesNotDeepIterateUntilvalue expected [message])

値が与えられた値のシーケンスで反復を終了しないことを、深い等価性を使用してアサートします。

assert.doesNotDeepIterateUntil([{n: 2}, {n: 3}], [{n: 5}]);
assert.doesNotDeepIterateUntil([[0, 2], [1, 3]], [[0, 2]]);

lengthOfvalue n [message])

イテラブルが与えられた数の値を生成することをアサートします。valueがイテラブルオブジェクトでない場合、または「'length'」プロパティがある場合、Chaiの内蔵のassert.lengthOf()が使用されます。

function* range(min=0, max=Infinity, step=1) {
  for (let n = min; n < max; n += step) {
    yield n;
  }
}

assert.lengthOf(range(0, 10), 10);
assert.lengthOf(range(6, 42), 36);

ライセンス

Copyright © 2016~2017 Akim McMath。[MIT License][ライセンス]の下でライセンスされています。