フロントエンドの単体テストを理解するための4つのヒント

各プロジェクトの複雑さ、コードの高い再利用性要件、フロントエンドコードモジュール間の高い結合性と低い結合により、フロントエンドエンジニアリングでのユニットテストプロセスが非常に必要になります。

1.フロントエンドユニットテストとは

まず、テストが何であるかを明確にする必要があります。

特定のターゲットが基準を満たしているかどうかを検出するために、検証に特別なツールまたは方法が使用され、最終的に特定の結果が得られます。

フロントエンド開発プロセスの場合、ここでの特定のターゲットは、私たちが作成したコードを指し、ツールは、使用する必要があるテストフレームワーク(ライブラリ)、テストケースなどです。検査部門の結果は、問題のトラブルシューティングと後での修正を容易にするために、テストが成功したかテストレポートを提供したかを示すことです。

テストの "what"ステートメントに基づいて、フロントエンド開発に従事している同僚の高度な理解を促進するために、ユニットテストの "what"をリストします。

データベースへのアクセスを必要とするテストは単体テストではありません

ネットワークアクセスを必要とするテストは単体テストではありません

ファイルシステムへのアクセスを必要とするテストは単体テストではありません

—コードを修正する技術

単体テストの引用された説明については、これまでのところ「ありません」。スペースの制約を考えると、フロントエンドの開発部門の同僚は、引用の内容を見た後、自分のことを事前に理解していると思います。

2.ユニットテストの意味とユニットテストが必要な理由

2.1単体テストの重要性

現在のフロントエンドエンジニアリング(標準の完全なプロジェクト)では、テストが非常に必要です。多くの場合、プロジェクトを完了してプロジェクトテストの一部を無視しましたが、テストの重要性は次の点にあります。

  1. TDD(テスト駆動開発)は、より機能的なインターフェースをカバーできる、効果的なソフトウェア作成原理であることが証明されています。
  2. 関数の出力をすばやくフィードバックし、アイデアを確認します。
  3. コードリファクタリングの安全性を確保するために、固定コードはありません。テストケースでは、変更可能なコード構造に安心感を与えることができます。
  4. テストしやすいコードは、優れた設計を示しています。単体テストを実行する前に、モノをインスタンス化する必要があります。これに多くの依存関係がある場合、テスト構造は非常に時間がかかり、テストの効率に影響します。どうすればよいですか?分離に依存するために、クラスはビューと関数の分離などの単一の関数を確実にしようとする必要があります。これにより、コードの保守と理解も容易になります。
2.2ユニットテストが必要な理由
  1. 1つ目は、フロントエンドの単体テストの根本的な理由です。JavaScriptは動的言語であり、型チェックが欠けており、コンパイル中にエラーを見つけることができません。JavaScriptホストの互換性の問題です。たとえば、さまざまなブラウザでのDOM操作のパフォーマンス。
  2. 正確性:テストではコードの正確性を検証できるため、オンラインに入る前に自信を持つことができます。
  3. 自動化:もちろん、手動でテストしたり、コンソールから内部情報を印刷したりすることもできますが、これは1回限りのことです。次のテストは最初から行う必要があり、効率は保証できません。テストケースを作成することで、1回作成して複数回実行できます。
  4. 説明:テストケースは、インターフェイスとモジュールの重要性をテストするために使用されるため、これらのAPIの使用方法がテストケースに含まれます。他の開発者がこれらのAPIを使用したい場合は、テストケースを読むことをお勧めします。ドキュメントよりも明確な場合があります。
  5. 開発とガイドの設計を推進する:テストするコードの前提条件は、コード自体のテスト容易性であるため、コードのテスト容易性を確保するには、開発中にAPIの設計に注意を払う必要があります。TDDは、そのような役割を果たすためにテストを進めます。
  6. リファクタリングの保証:インターネット業界の製品は反復的に高速であり、反復後にコードリファクタリングのプロセスが必要ですリファクタリングされたコードの品質はどのように保証されますか?テストケースに支えられて、大胆にリファクタリングできます。

3.単体テストケースの書き方

3.1原則
  • コードをテストするときは、内部実装ではなく、テストのみを考慮してください
  • データはできるだけ現実をシミュレートし、現実に近いほど良い
  • データの境界条件を十分に考慮する
  • 重要で複雑なコアコードに焦点を当て、テストに焦点を当てる
  • AOP(beforeEach、afterEach)を使用して、テストコードの量を減らし、無駄な関数を回避する
  • テストと機能開発の組み合わせは、設計とコードのリファクタリングに役立ちます
3.2一般的に使用される2つの単体テスト方法

単体テストでは、TDD(テスト駆動開発)とBDD(動作駆動開発)の2つの一般的に使用される方法論があります。

3.3 TDDとBDDを読んだ後、個人的にTDDとBDDを見ることができると思います。ここでは、TDDとBDDについての私の理解についてお話しします。

TDD(テスト駆動開発)

基本的な考え方は、テストを通じて開発全体を促進することです。

  • ユニットテストの主な目的は、すべてのテストに合格するテストコードを広い範囲で記述できるようにすることではなく、ユーザー(呼び出し元)の観点から関数ロジックのさまざまな可能性を試し、コードの品質を向上させることです

  • テストは手段であり、目的ではありません。テストの主な目的は、コードが正しいことを証明することではなく、低レベルのエラーを含むエラーを見つけるのに役立ちます

  • 高速テスト。高速実行、高速書き込み

  • テストコードを簡潔にする

  • 失敗したテストを無視しません。チームが1つのテストビルドの失敗を受け入れ始めると、2、3、4、またはそれ以上の失敗に徐々に適応します。この場合、テストセットは機能しなくなります

次の点に注意してください。

  • TDDの主要な目的を誤解してはなりません。

  • テストはカバレッジと精度のためではありません

  • しかし、例として、どのコードを書くかを開発者に伝えます

  • 赤信号(コードは完全ではない、テストはハングしている)->緑信号(コードを記述、テストに合格)->リファクタリング(コードを最適化し、テストに合格することを確認)

TDDのプロセスは次のとおりです

  1. 需要分析、実現について考える。製品コードがインスタンスメソッドであるかクラスメソッドであるか、コンストラクターまたはメソッド呼び出しからパラメーターを渡すかどうか、メソッドの名前付け、戻り値などであるかどうかを検討する。現時点では、実際に設計を行っており、設計はコードで具体化されています。現在、テストは赤です

  2. テストを「青信号」にするコードを実装する

  3. リファクタリングしてからテストを繰り返す

  4. 最終的には、すべての要件を満たします。

    • すべてのコンセプトが明確に表現されている

    • コードに自己反復がない

    • 余分なものはありません

    • テストに合格

BDD(行動主導型開発):

行動主導型開発(BDD)は、利害関係者(つまり、顧客)との話し合いを通じて予想されるソフトウェアの動作を理解することに重点を置き、コミュニケーションに焦点を当てています

BDDプロセスは次のとおりです。

  1. ビジネスの観点から具体的で測定可能な目標を定義する

  2. ビジネスにとって最も重要な機能を実現する方法を見つける

  3. 次に、ストーリーのような特定の実行可能な動作をそれぞれ説明します。記述方法は、正確な表現能力と一貫した意味を持ついくつかの一般的な語彙に基づいています。たとえば、expectshouldassert

  4. 行動を実現するための適切な言語と方法を見つける

  5. テスターは、製品の動作結果が期待される動作に準拠しているかどうかを確認します。ユーザーの期待に最大限応え、一貫性のない表現による問題を回避する製品を提供する

4. Mocha / Karma + Travis.CIフロントエンドテストワークフロー

上記の内容は、単体テストとは何かからの単体テストの方法論について述べています。では、単体テストに共通のフレームワークをどのように使用するのでしょうか。単体テストのツール環境は何ですか?単体テストの実際的な例は何ですか?

まず、モカ、カルマ、トラビスを簡単に紹介します。CI

MochaMochaは、機能豊富なフロントエンドテストフレームワークです。いわゆる「テストフレームワーク」は、テストを実行するためのツールです。これにより、JavaScriptアプリケーションのテストを追加して、コードの品質を確認できます。Mochaは、Node.js環境に基づいて、またはブラウザー環境で実行できます。

Karma:Node.jsに基づくJavaScriptテスト実行プロセス管理ツール(テストランナー)。このツールは、すべての主要なWebブラウザーのテストに使用でき、CI(継続的インテグレーション)ツールに統合することも、他のコードエディターで使用することもできます。このテストツールの強力な機能は、ファイルの変更を監視し、それ自体を実行して、console.logを通じてテスト結果を表示できることです。Karmaの強力な機能は、一連のファイルの変換を監視し、テキストエディターを離れることなく、保存されたファイルのテストをすぐに開始できることです。テスト結果は通常、コードエディターではなくコマンドラインに表示されます。これにより、Karmaを基本的にあらゆるJSエディターで使用することもできます。

Travis.CI:継続的インテグレーションサービス(継続的インテグレーション、略してCI)を提供します。Github上のプロジェクトをバインドします。新しいコードがある限り、自動的にクロールされます。次に、実行環境を提供し、テストを実行し、ビルドを完了して、サーバーにデプロイします。

継続的な統合とは、コードが変更されている限り、ビルドとテストが自動的に実行され、結果がフィードバックされることを意味します。新しいコードは、期待に沿うようにした後、バックボーンに「統合」されます。

継続的インテグレーションの利点は、開発サイクルの最後に大きなコードブロックをマージする代わりに、コードの小さな変更ごとの結果を確認できるため、小さな変更を蓄積できることです。

アサーションライブラリ

基本的なツールフレームワークの導入後、テストについて少し知っている人なら、ユニットテストを行うにはテストスクリプトを作成する必要があるため、テストスクリプトでアサーションライブラリを使用する必要があることを知っていると思います。「アサーション」、個人的な理解は「コードを使用してテストコードの正確さを判断し、このコードのエラーを確認して公開すること」です。フロントエンドユニットテストでは、次の一般的に使用されるアサーションライブラリがあります。

コード例を見てください。

expect(add(1, 1)).to.be.equal(2);

これはアサーションコードです。

いわゆる「アサーション」とは、ソースコードの実際の実行結果が期待される結果と一致しているかどうかを判断し、矛盾している場合はエラーをスローすることです。上記のアサーションは、add(1、1)が呼び出されると、結果が2に等しくなることを意味します。すべてのテストケース(ブロック)には、1つ以上のアサーションが含まれている必要があります。それはテストケースを書くための鍵です。アサーション関数はアサーションライブラリによって実装されますが、Mochaにはアサーションライブラリがないため、最初にアサーションライブラリを導入する必要があります。

アサーションライブラリのコード例を紹介します。

var expect = require('chai').expect;

アサーションライブラリにはさまざまな種類がありますが、Mochaは使用するアサーションライブラリを制限せず、必要なアサーションライブラリを使用できます。上記のコードで導入されたアサーションライブラリはchaiであり、その期待アサーションスタイルを使用するように指定されています。次の一般的なアサーションライブラリ:

ここでは主にノードアサートで一般的に使用されるAPIを紹介します

  • assert(value [、message])
  • assert.ok(value [、message])
  • assert.equal(actual、expect [、message])
  • assert.notEqual(実際、期待される[、メッセージ])
  • assert.strictEqual(actual、expect [、message])
  • assert.notStrictEqual(actial、expected [、message])
  • assert.deepEqual(actual、expect [、message])
  • assert.notDeepEqual(実際、期待される[、メッセージ])
  • assert.deepStrictEqual(actual、expect [、message])
  • assert.notDeepStrictEqual(actual、expected [、message])
  • assert.throws(block [、error] [、message])
  • assert.doesNotThrow(block [、error] [、message])

assert(value [、message])

valueの値がtrueであるかどうかをアサートします。ここでの等式判断では、===ではなく==を使用します。メッセージはアサーションの説明であり、オプションのパラメーターです。

const assert = require('assert');
assert(true);

assert.ok(value [、message])

同じ方法を使用してくださいassert(value[, message])

assert.equal(actual、expect [、message])

実際と期待値が等しいことを期待します。比較に使用される実際のデータと期待値は、基本タイプ(文字列、数値、boolearn、null、未定義)データです。比較では===ではなく==を使用します。

it('assert.equal', () => {
  assert.equal(null, false, 'null compare with false');  // 报错
  assert.equal(null, true, 'null compare with true');  // 报错
  assert.equal(undefined, false, 'undefined compare with false'); // 报错
  assert.equal(undefined, true, 'undefined compare with true'); // 报错
  assert.equal('', false, '"" compare with false');  // 正常
})

notEqual(実際、期待される[、メッセージ])

assert.equal(actual, expect[, message])期待される結果を否定したものと同じものを使用します(つまり、等しくない)。

assert.strictEqual(actual、expect [、message])

assert.equal(actual, expect[, message])代わりに== ===を使用して、同じをより内部的に使用します。

assert.notStrictEqual(actial、expected [、message])

assert.strictEqual(actual, expect[, message])期待される結果を無効にした同じものを使用します(つまり、厳密に等しくない)。

it('assert.strictEqual', () => {
  assert.strictEqual('', false); // 报错
})

assert.deepEqual(actual、expect [、message])

deepEqualメソッドは、2つのオブジェクトを比較するために使用されます。比較のプロセスは、2つのオブジェクトのキーと値の値が同じであるかどうかを比較することです。比較するときは、===ではなく==を使用してください。

it('assert.deepEqual', () => {
  const a = { v: 'value' };
  const b = { v: 'value' };
  assert.deepEqual(a, b);
})

assert.notDeepEqual(実際、期待される[、メッセージ])

同じassert.deepEqual(actual, expect[, message])期待どおりの結果が否定されたものを使用します(つまり、厳密に等しい深さではありません)。

assert.deepStrictEqual(actual、expect [、message])

assert.deepEqual(actual, expect[, message])代わりに== ===を使用して、同じをより内部的に使用します。

assert.notDeepStrictEqual(actual、expected [、message])

同じものを使用しますassert.deepStrictEqual(actual, expect[, message])が、結果は逆になります(つまり、厳密に等しい深さではありません)。

assert.throws(block [、error] [、message])

エラーのアサーションとキャプチャ、指定されたコードブロックがエラーを報告するか、エラーをスローすることをアサートします。コードがエラーなしで実行される場合、アサーションは失敗し、アサーションは異常です。

it('throws', () => {
  var fun = function() {
    xxx
  };
  assert.throws(fun, 'fun error');
})

assert.doesNotThrow(block [、error] [、message])

エラーのアサーションとキャプチャ、使用法はスローに似ていますが、予想されるスローの結果とは逆です。指定したコードブロックが実行時にエラーを報告したり、エラーをスローしたりしないことを表明します。コードが正しく実行されない場合、アサーションは失敗し、アサーションは異常です。

it('throws', () => {
  var fun = function() {
    xxx
  };
  assert.doesNotThrow(fun, 'fun error');
})

対応するツールの紹介後、モカ、カルマ、Travis.CIの使用方法について、実際の運用経験についてお話します。

モカ

  • mochaをインストールする
npm install mocha -g

もちろん、グローバルにインストールすることも、しないこともでき、プロジェクトでローカルにのみインストールできます

npm install mocha --save
  • テストファイルを作成する test.js
var assert = require('assert')

describe('Array', function() {
  describe('#indexOf()', function() {
    it('should return -1 when the value is not present', function() {
      assert.equal(-1, [1, 2, 3].indexOf(-1))
    })
  })
})

このファイルは簡単なテストであり、Array1つのindexOf()方法です。ここAssertでは、APIのノードモジュールによって提供されるアサーションライブラリを使用しています。ここで、アサーション-1 は、後で返される値[1, 2, 3]を実行するための配列等しくindexOf(-1)、テストに合格した場合は文句を言わず、エラーがある場合はエラーを報告します。

ここでは、インストールされmochaいるグローバルを使用して、このファイルを実行しますmocha test.js
以下は戻り結果です

基本的なテストケースの例

const assert = require('assert');

describe('测试套件描述', function() {
  it('测试用例描述: 1 + 2 = 3', function() {
    // 测试代码
    const result = 1 + 2;
    // 测试断言
    assert.equal(result, 3);
  });
});

Mochaテストケースには、主に次の部分が含まれます。

  1. 定義されたテストスイートの説明(テストスイート)
  2. それによって定義されたテストケース
  3. テストコード
  4. アサーション

注:各テストファイルには、複数のテストスイートとテストケースを含めることができます。Mochaはノード環境だけでなくブラウザー環境npm i mocha -gでも実行できます。また、mochaをグローバルにインストールしてからコマンドラインでテストケースを実行することにより、ノードで実行することもできます

ここでは、テストスクリプトの記述について少し詳しく紹介します。

Mochaの役割はテストスクリプトを実行することです。まず、テストスクリプトの作成方法を学ぶ必要があります。いわゆる「テストスクリプト」は、ソースコードのテストに使用されるスクリプトです。以下は、追加モジュールadd.jsのコードです。

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

module.exports = add;

追加モジュールが正しいかどうかをテストするには、テストスクリプトを作成する必要があります。通常、テストスクリプトはテストするソーススクリプトと同じ名前ですが、サフィックスは.test.js(テスト用)または.spec.js(仕様用)です。たとえば、add.jsのテストスクリプト名はadd.test.jsです。

// add.test.js
var add = require('./add.js');
var expect = require('chai').expect;

describe('加法函数的测试', function() {
  it('1 加 1 应该等于 2', function() {
    expect(add(1, 1)).to.be.equal(2);
  });
});

上記のコードは、独立して実行できるテストスクリプトです。テストスクリプトには1つ以上の記述ブロックを含める必要があり、各記述ブロックには1つ以上のitブロックを含める必要があります。

記述ブロックは「テストスイート」と呼ばれ、関連するテストのセットを表します。これは関数で、最初のパラメーターはテストスイートの名前( "追加関数テスト")で、2番目のパラメーターは実際に実行される関数です。

itブロックは「テストケース」と呼ばれ、単一のテストを表し、テストの最小単位です。これも関数で、最初のパラメーターはテストケースの名前( "1 + 1は2と等しい")で、2番目のパラメーターは実行される実際の関数です。

期待アサーションの利点は、自然言語に非常に近いことです。

// 相等或不相等
expect(4 + 5).to.be.equal(9);
expect(4 + 5).to.be.not.equal(10);
expect(foo).to.be.deep.equal({ bar: 'baz' });

// 布尔值为true
expect('everthing').to.be.ok;
expect(false).to.not.be.ok;

// typeof
expect('test').to.be.a('string');
expect({ foo: 'bar' }).to.be.an('object');
expect(foo).to.be.an.instanceof(Foo);

// include
expect([1, 2, 3]).to.include(2);
expect('foobar').to.contain('foo');
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');

// empty
expect([]).to.be.empty;
expect('').to.be.empty;
expect({}).to.be.empty;

// match
expect('foobar').to.match(/^foo/);

基本的に、アサーションは同じ方法で記述されます。先頭はexpectメソッドで、末尾はequal、a / an、ok、matchなどのアサーションメソッドです。2つを接続するには、toまたはto.beを使用します。expectアサーションがtrueでない場合、エラーがスローされます。実際、エラーがスローされない限り、テストケースはパスします。

it('1 加 1 应该等于 2', function() {});

上記のテストケースでは、内部にコードはありませんが、エラーがスローされなかったため、パスします。

カルマ

カルマテストに基づいていくつかの一般的に使用されるモジュール

モジュールのインストール

# 基础测试库
npm install karma-cli -g
npm install karma mocha karma-mocha --save-dev

# 断言库
npm install should --save-dev
npm install karma-chai --save-dev

# 浏览器相关
npm install karma-firefox-launcher --save-dev
npm install karma-chrome-launcher --save-dev

ソフトウェアテスト、インターフェーステスト、自動テスト、インタビューの経験を交換する場合。興味がある場合は、ソフトウェアテスト通信(1085991341)を追加できます。同僚との技術交流があります。

構成

ここでの設定は、主karma.conf.jsに関連する設定に関係しています。KarmaとMochaを使用する場合は、npm install karma-cli -gグローバルインストールすることをお勧めしますkarma-cli

注意すべき2つのフィールド:

  • singleRun:値がtrueの場合、テストの実行後、ブラウザーは自動的に終了してブラウザーウィンドウを閉じます。singleRunの値は、動作環境に応じて動的に割り当てることができ、NODE_ENV変数をスタートアップコマンドに追加できます
  • ブラウザー:ブラウザー構成(複数のブラウザーを構成できます);ブラウザーを開始できない場合は、関連するブラウザー構成が必要です。自動起動ブラウザの設定時にブラウザが起動しない場合は、--no-sandboxモードに設定する必要があるかもしれません
{
  "browsers": ["Chrome", "ChromeHeadless", "ChromeHeadlessNoSandbox"],
  "customLaunchers": {
    "ChromeHeadlessNoSandbox": {
      "base": "ChromeHeadless",
      "flags": ["--no-sandbox"]
    }
  }
}

または

{
  "browsers": ["Chrome_travis_ci"],
  "customLaunchers": {
    "Chrome_travis_ci": {
      "base": "Chrome",
      "flags": ["--no-sandbox"]
    }
  }
}

GithubプロジェクトがTravis.CIにアクセスして、統合および自動テスト手順を実行

  • githubでテストできるプロジェクトを作成して完成させます。ここでの完了とは、基本的なプロジェクト機能とテストケースコードを完了する必要があることを指します。
  • 読み込まれた構成ファイルを認識するようにtravis-ciを構成します。これにより、travis-ciが接続されている場合、テスト中に構成の一部を認識できます。
  • githubとtravis-ciはサイト、つまり2つのものが接続できる場合のサイトです。ユーザーは、travis-ciにログインし、githubプロジェクトへのアクセスを承認し、関連するプロジェクト設定を行う必要があります。
  • 接続が完了したら、必要に応じて作成したテストコードを実行するか、テストを実行するための定期的なタスクを設定できます。

プロジェクトの作成、プロジェクト機能とテストコードの改善。

  • プロジェクト要件:総和法を実装する
  • テスト:mochaメソッドを合計してテストを完了します。

これは、モジュールのnpm i mocha -Dインストールによってプロジェクトの完了後に作成されたプロジェクト構造mochaです。次に、ローカルで実行してnpm test、テストに合格したかどうかを確認します。テストに合格した場合は、次のステップに進むことができます。

travis-ciテスト構成ファイルを作成する

travis-ci構成ファイル.travis.yml、ファイルコンテンツを作成します

language: node_js
node_js:
  - "node"
  - "8.9.4"

この時点で、プロジェクト開発とテストコードの記述のプロセスは基本的に完了しており、次のステップはtravis-ciテストに接続できます。

アクセスtravis-ci

GitHubからtravis-ciの公式Webサイトにログインします。

GitHubで作成したばかりのテストが必要なプロジェクトを見つけて、テストを開始します

テストプロセスをチェックし、時間内に問題を見つけます。

テストのステータスがテストに合格したかどうかを確認します。失敗した場合は、問題を確認して繰り返し修正します。合格した場合は、プロジェクトドキュメントにテスト合格マークを追加できます。


上記の内容は、この記事の内容全体です。上記の内容は、あなたのお役に立てれば幸いです。

おすすめ

転載: blog.csdn.net/Chaqian/article/details/106603727