自動テストは基本的に、次のような場合にエラーをスローまたは発生させるコードです。 なんらかの問題が発生しています。ほとんどのライブラリやテスト フレームワークでは、 プリミティブが含まれています。
前のセクションで説明したように、これらのプリミティブにはほとんどの場合、 独立したテスト(テストケースと呼ばれます)を定義し、 記述できます。アサーションは、結果の確認と、 なんらかの異常があった場合にエラーが発生するため、 テストプリミティブ。
このページでは、これらのプリミティブへの一般的なアプローチについて説明します。選択したフレームワーク はこれに似ていますが、正確な参照ではありません。
例:
import { fibonacci, catalan } from '../src/math.js';
import { assert, test, suite } from 'a-made-up-testing-library';
suite('math tests', () => {
test('fibonacci function', () => {
// check expected fibonacci numbers against our known actual values
// with an explanation if the values don't match
assert.equal(fibonacci(0), 0, 'Invalid 0th fibonacci result');
assert.equal(fibonacci(13), 233, 'Invalid 13th fibonacci result');
});
test('relationship between sequences', () => {
// catalan numbers are greater than fibonacci numbers (but not equal)
assert.isAbove(catalan(4), fibonacci(4));
});
test('bugfix: check bug #4141', () => {
assert.isFinite(fibonacci(0)); // fibonacci(0) was returning NaN
})
});
この例では、「数学」というテストのグループ(スイートとも呼ばれます)を作成します 「tests」という関数があり、それぞれがアサーションを実行する 3 つの独立したテストケースを定義します。 これらのテストケースは通常、個別に対処することも、実行することもできます。たとえば、 フィルタフラグを指定します。
プリミティブとしてのアサーション ヘルパー
Vitest を含むほとんどのテスト フレームワークには、一連のアサーションが含まれています。
ヘルパーを使用して assert
オブジェクトで
いくつかの期待に反しています。その期待は「正常と認識されている」ことが多い
使用できます。前の例では、13 番目のフィボナッチ数は
233 なので、assert.equal
を使用して直接確認できます。
また、値が特定の形式を取ることを期待している、または 値が別の値よりも大きいか、値が別の値であることを意味します。このコースでは、 使用可能なアサーション ヘルパーをすべて網羅していますが、フレームワークのテスト 少なくとも以下の基本的なチェックを必ず実施してください。
「truthy」 チェック(しばしば「OK」と表現される)条件が満たされているかチェックされます うまくいかないかチェックする
if
や 正解。多くの場合、assert(...)
またはassert.ok(...)
として提供されます。 は 1 つの値と、コメント(省略可)を受け取ります。数学のテストの例のような、等価チェック。 オブジェクトの戻り値または状態を既知の有効な値と等しいとみなすことができます。これらは、 プリミティブ等価(数値や文字列など)または参照等価 (同じオブジェクトか)?内部的には、これらは単なる「真実」チェック
==
または===
の比較。- JavaScript では、等価性(
==
)と厳格(===
)を区別します。 ほとんどのテスト ライブラリには、メソッドassert.equal
とメソッドが用意されています。 それぞれassert.strictEqual
です。
- JavaScript では、等価性(
詳細な等価チェック。等価チェックを拡張し、 オブジェクト、配列、その他の複雑なデータ型のコンテンツと、 内部ロジックを使用してオブジェクトを走査し、それらを比較します。これらは重要です。 JavaScript には、ファイルの内容を比較する手段が組み込まれていないため、 2 つのオブジェクトまたは配列ですたとえば、
[1,2,3] == [1,2,3]
は常に false です。テスト 多くの場合、フレームワークにはdeepEqual
ヘルパーまたはdeepStrictEqual
ヘルパーが含まれます。
「truthy」チェックのみではなく、2 つの値を比較するアサーション ヘルパー。 通常、2 つまたは 3 つの引数を取ります。
- 実際の値。テスト対象のコードから生成されたか、 指定します。
- 予想される値。通常はハードコードされています(例: リテラル数値または string)。
- 想定される動作や失敗した可能性のある動作を説明するコメント(省略可)。 この行が失敗した場合にそれが含まれます。
また、複数のアサーションを組み合わせてさまざまな ステータスを正しく確認できることは稀であるため、 考えてみましょう。例:
test('JWT parse', () => {
const json = decodeJwt('eyJieSI6InNhbXRob3Ii…');
assert.ok(json.payload.admin, 'user should be admin');
assert.deepEqual(json.payload.groups, ['role:Admin', 'role:Submitter']);
assert.equal(json.header.alg, 'RS265')
assert.isAbove(json.payload.exp, +new Date(), 'expiry must be in future')
});
Vitest は Chai アサーション ライブラリを使用します。 アサート ヘルパーを提供します。また、アサート ヘルパーを コードに適したアサーションとヘルパーを確認してください。
Fluent および BDD アサーション
一部のデベロッパーは、動作駆動型と呼べるアサーション スタイルを好みます。
開発(BDD)または
Fluent スタイル
記述できます。「予測」とも呼ばれるエントリ ポイントが
期待値の確認は、expect()
という名前のメソッドです。
期待ヘルパーは、単純なメソッドとして記述されたアサーションと同じように動作します。
assert.ok
や assert.strictDeepEquals
などの呼び出しを使用していますが、デベロッパーによってはこれらの方が読みやすいと感じています。
BDD アサーションは、次のようになります。
// A failure here would generate "Expect result to be an array that does include 42"
const result = await possibleMeaningsOfLife();
expect(result).to.be.an('array').that.does.include(42);
// or a simpler form
expect(result).toBe('array').toContainEqual(42);
// the same in assert might be
assert.typeOf(result, 'array', 'Expected the result to be an array');
assert.include(result, 42, 'Expected the result to include 42');
このようなアサーションは、メソッド チェーンという手法により機能します。
ここで、expect
から返されるオブジェクトを
追加のメソッド呼び出しです。通話の一部(to.be
、that.does
など)
関数を持たず、呼び出しを行うためにのみ含められています。
テストにより、自動的にコメントが生成される可能性があります。
失敗しました。(特に、通常 expect
は省略可能なコメントをサポートしていません。これは、
チェーンでエラーを明確に説明する必要があります)。
多くのテスト フレームワークは、Fluent/BDD と通常のアサーションの両方をサポートしています。Vitest、 たとえば、 Chai は BDD に対する独自のアプローチを少し簡潔にしています。ジェスト 一方、予測値のみを含む メソッドがデフォルトです。
ファイル間でテストをグループ化する
テストを作成する際には、コードではなく暗黙的なグループ化を提供する傾向があります。 すべてのテストを 1 つのファイルにまとめるよりも、複数のテストを できます。実際、テストランナーは通常、ファイルがテスト用であることを (たとえば、vitest はすべての属性を含む) 「.test.jsx」などの拡張子で終わるプロジェクト内のファイルまたは「.spec.ts」 (「.test」と「.spec」、および複数の有効な拡張子)。
コンポーネント テストは多くの場合、テスト対象コンポーネントのピアファイルに配置されます。 次のようなディレクトリ構造になります。
<ph type="x-smartling-placeholder">同様に、単体テストはテスト対象のコードに近接して配置する傾向があります。 エンドツーエンド テストをそれぞれ独自のファイルに含めることも、統合テストで 個別のフォルダに配置されます。これらの構造は、 複雑なテストケースが増大し、次のような独自のテスト以外のサポート ファイルが必要になり、 テスト専用のサポート ライブラリも用意されています。
ファイル内のテストをグループ化する
前の例で使用したように、テストは呼び出し内に
suite()
: test()
で設定したテストをグループ化します。スイートは
関連するテストをグループ化して構成できます。
渡されるメソッドを呼び出します。test()
の場合、渡されるメソッドは、
テスト自体のアクションを定義します
アサーションと同様に、Fluent/BDD にも標準的な テストのグループ化一般的な例を次のコードで比較します。
// traditional/TDD
suite('math tests', () => {
test('handle zero values', () => {
assert.equal(fibonacci(0), 0);
});
});
// Fluent/BDD
describe('math tests', () => {
it('should handle zero values', () => {
expect(fibonacci(0)).toBe(0);
});
})
ほとんどのフレームワークで、suite
と describe
はtest
と
expect
と assert
を使用する場合の違いとは異なり、it
アサーションを記述します。
他のツールでは、スイートとテストの配置方法が微妙に異なります。対象
たとえば、Node.js の組み込みテストランナーは、test()
の呼び出しのネストをサポートしています。
暗黙的にテスト階層を作成します。ただし、Vitest ではこの種の
suite()
を使用したネストであり、別の test()
内で定義された test()
は実行されません。
アサーションと同様に、グループ化の正確な組み合わせは 技術スタックが提供する方法はそれほど重要ではありません。このコースで取り上げる内容は 理解する必要がありますが、 多岐にわたります。
ライフサイクル メソッド
テストをグループ化する理由の 1 つは、 すべてのテストに対して、または 1 回だけ実行される setup メソッドと teardown メソッドを テストグループですほとんどのフレームワークには、次の 4 つのメソッドがあります。
`test()` または `it()` の | スイートで 1 回 | |
---|---|---|
テスト実行前 | `beforeEach()` | `beforeAll()` |
テスト実行後 | `afterEach()` | `afterAll()` |
たとえば、各ユーザー アカウントごとに仮想ユーザー データベースを事前入力し、 次のようにしてテストし、後でクリアします。
suite('user test', () => {
beforeEach(() => {
insertFakeUser('bob@example.com', 'hunter2');
});
afterEach(() => {
clearAllUsers();
});
test('bob can login', async () => { … });
test('alice can message bob', async () => { … });
});
これはテストを簡素化するのに役立ちます。共通の設定や共通の機能を共有できます テストごとにコードを複製する必要はありません。また、 setup と teardown のコードはエラーをスローします。エラーは、構造的な テスト自体の失敗を伴わない問題
一般的なアドバイス
これらのプリミティブについて考えるときに覚えておくべきヒントをいくつか紹介します。
プリミティブは
ここで説明するツールやプリミティブは、この後の数ページで Vitest、Jest、Mocha、Web Test Runner などに サポートします。Vitest を一般的なガイドとして使用しましたが、 任意のフレームワークに適用できます
必要に応じてアサーションを組み合わせる
テストは基本的に、エラーをスローする可能性のあるコードです。どのランナーも
プリミティブ(test()
の可能性)。個別のテストケースを記述します。
ただし、そのランナーが assert()
、expect()
、アサーション ヘルパーも提供している場合は、
この部分は便利さを重視しているため、スキップしてもかまいません。
できます。次のような、エラーをスローする可能性のあるコードをすべて実行できます。
アサーション ライブラリ、あるいは従来の if
ステートメントを使用することもできます。
IDE のセットアップが救命の道に
VSCode などの IDE が予測入力と
ドキュメントを使用して、生産性を向上させることができます。対象
たとえば、Chai アサーションの assert
には 100 を超えるメソッドがあります。
ライブラリがあり、対応するドキュメントが
インラインで表示するのが便利です。
これは、 そのテストメソッドを使用します。微妙な違いですが、 多くの場合、必要な場合は、テスト ライブラリをインポートせずに使用 自動的にグローバル名前空間に追加されます。
// some.test.js
test('using test as a global', () => { … });
ヘルパーが自動的にサポートされている場合でも、ヘルパーをインポートすることをおすすめします。
IDE でこれらのメソッドを
見つけやすくなるからです(
React のビルド時にこの問題が生じました。これは、
React
グローバルですが、一部はそうではなく、
React.)
// some.test.js
import { test } from 'vitest';
test('using test as an import', () => { … });