フロントエンドテストフレームワークJestシリーズチュートリアル--Expect(検証)

18937 ワード

前に書く


テストを作成するときは、通常、値がいくつかの条件を満たしているかどうかを確認する必要があります.Jestで提供されているexpectでは、さまざまなものを検証するために多くの「Matchers」にアクセスできます.

Expectは何を検証できますか?


Jestでは、次の検証方法が提供されています.
expect(value)
expect.extend(matchers)
expect.anything()
expect.any(constructor)
expect.arrayContaining(array)
expect.assertions(number)
expect.hasAssertions()
expect.not.arrayContaining(array)
expect.not.objectContaining(object)
expect.not.stringContaining(string)
expect.not.stringMatching(string | regexp)
expect.objectContaining(object)
expect.stringContaining(string)
expect.stringMatching(string | regexp)
expect.addSnapshotSerializer(serializer)
.not
.resolves
.rejects
.toBe(value)
.toHaveBeenCalled()
.toHaveBeenCalledTimes(number)
.toHaveBeenCalledWith(arg1, arg2, ...)
.toHaveBeenLastCalledWith(arg1, arg2, ...)
.toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....)
.toHaveReturned()
.toHaveReturnedTimes(number)
.toHaveReturnedWith(value)
.toHaveLastReturnedWith(value)
.toHaveNthReturnedWith(nthCall, value)
.toBeCloseTo(number, numDigits)
.toBeDefined()
.toBeFalsy()
.toBeGreaterThan(number)
.toBeGreaterThanOrEqual(number)
.toBeLessThan(number)
.toBeLessThanOrEqual(number)
.toBeInstanceOf(Class)
.toBeNull()
.toBeTruthy()
.toBeUndefined()
.toContain(item)
.toContainEqual(item)
.toEqual(value)
.toHaveLength(number)
.toMatch(regexpOrString)
.toMatchObject(object)
.toHaveProperty(keyPath, value)
.toMatchSnapshot(propertyMatchers, snapshotName)
.toStrictEqual(value)
.toThrow(error)
.toThrowErrorMatchingSnapshot()

ここでは、一部の検証の使用シーンについて説明します.
expect(value)
値をテストするたびにexpect関数が使用されます.expect自体を呼び出すことはめったにありません.逆にexpectとmatcher関数を使用して、値の一部を断言します.この例をもっと理解しやすい.「柚子」という文字列を返す方法があるとします.テスト方法は次のとおりです.
test('the best flavor is grapefruit', () => {
  expect(bestLaCroixFlavor()).toBe('grapefruit');
});

上のcaseではtoBeはmatcher関数です.異なるものをテストするのに役立つために、Jestには異なるmatcher関数がたくさんあります.
expectのパラメータはコード生成の値であり、マッチングプログラムの任意のパラメータは正しい値であるべきである.それらを混ぜ合わせると、テストは依然として動作しますが、失敗したテストのエラーメッセージはおかしく見えます.
expect.extend(matchers)
expectを使ってもいいです.extendは自分のmatcherをJestに追加します.例えばtheory libraryをテストしていて、数字が他の数で割り切れるとよく断言しているとしたら、toBeDivisibleBy matcherとして抽象化することができます.
expect.extend({
  toBeDivisibleBy(received, argument) {
    const pass = received % argument == 0;
    if (pass) {
      return {
        message: () =>
          `expected ${received} not to be divisible by ${argument}`,
        pass: true,
      };
    } else {
      return {
        message: () => `expected ${received} to be divisible by ${argument}`,
        pass: false,
      };
    }
  },
});

test('even and odd numbers', () => {
  expect(100).toBeDivisibleBy(2);
  expect(101).not.toBeDivisibleBy(2);
  expect({apples: 6, bananas: 3}).toEqual({
    apples: expect.toBeDivisibleBy(2),
    bananas: expect.not.toBeDivisibleBy(2),
  });
});

expect.extendsは非同期マッチングもサポートします.非同期マッチングはpromiseを返すので、返される値を待つ必要があります.例matcherを使用して、それらの使い方を説明します.toBeDivisibleByではなく、非常に似たようなmatcherを実現するには、分割可能な数字が外部ソースから抽出されるのが唯一の違いです. 
expect.extend({
  async toBeDivisibleByExternalValue(received) {
    const externalValue = await getExternalValueFromRemoteSource();
    const pass = received % externalValue == 0;
    if (pass) {
      return {
        message: () =>
          `expected ${received} not to be divisible by ${externalValue}`,
        pass: true,
      };
    } else {
      return {
        message: () =>
          `expected ${received} to be divisible by ${externalValue}`,
        pass: false,
      };
    }
  },
});

test('is divisible by external value', async () => {
  await expect(100).toBeDivisibleByExternalValue();
  await expect(101).not.toBeDivisibleByExternalValue();
});

マッチング器は、2つのキーを持つオブジェクト(またはオブジェクトのpromise)を返す必要があります.passは一致があるかどうかを示し、messageはパラメータのない関数を提供し、失敗したときにエラーメッセージを返します.したがってpassがfalseである場合、expect(x)となる.yourmatcher()が失敗した場合、メッセージはエラーメッセージを返すべきです.passがtrueである場合、メッセージはexpect(x)を返すべきである.no . yourmatcher()が失敗したときのエラーメッセージ.
これらの補助関数は、カスタムマッチングで見つけることができます:this.isNot、ブール値を返して、このマッチングが否定的であることを知らせます.not修飾子が呼び出したので、断言を反転させることができます.
this.equals(a, b)
2つのオブジェクトが同じ値(再帰的に)を持つ場合、trueが返されます.
this.utilsには役に立つツールがたくさんあります.utilsは主にjest-matcher-utilsからの導出から構成される.最も有用なのはmatcherHint、printExpected、printReceivedであり、エラーメッセージをうまくフォーマットできます.たとえばtoBe matcherの実装を見てみましょう.
const diff = require('jest-diff');
expect.extend({
  toBe(received, expected) {
    const pass = Object.is(received, expected);

    const message = pass
      ? () =>
          this.utils.matcherHint('.not.toBe') +
          '

' + `Expected value to not be (using Object.is):
` + ` ${this.utils.printExpected(expected)}
` + `Received:
` + ` ${this.utils.printReceived(received)}` : () => { const diffString = diff(expected, received, { expand: this.expand, }); return ( this.utils.matcherHint('.toBe') + '

' + `Expected value to be (using Object.is):
` + ` ${this.utils.printExpected(expected)}
` + `Received:
` + ` ${this.utils.printReceived(received)}` + (diffString ? `

Difference:

${diffString}` : '') ); }; return {actual: received, message, pass}; }, });  

印刷結果は次のとおりです.
 expect(received).toBe(expected)

    Expected value to be (using Object.is):
      "banana"
    Received:
      "apple"

断言に失敗した場合、エラーメッセージは、ユーザが迅速に問題を解決できるように、ユーザに必要なできるだけ多くの信号を提供するべきである.カスタムブレークスルーのユーザーが良好な開発経験を持っていることを確認するために、正確な失敗メッセージを作成する必要があります.
expect.anything()
nullまたはundefined以外のコンテンツに一致します.文字値ではなくtoEqualまたはtoBeCalledWithを内部で使用できます.たとえば、シミュレーション関数が呼び出されているかどうかを確認したい場合は、そのパラメータは空ではありません.
test('map calls its argument with a non-null argument', () => {
  const mock = jest.fn();
  [1].map(x => mock(x));
  expect(mock).toBeCalledWith(expect.anything());
});

expect.any(constructor)
指定したコンストラクション関数によって作成された内容を一致させます.文字値ではなくtoEqualまたはtoBeCalledWithを内部で使用できます.シミュレーション関数が呼び出されたかどうかを確認するには、次のようにします.
function randocall(fn) {
  return fn(Math.floor(Math.random() * 6 + 1));
}

test('randocall calls its callback with a number', () => {
  const mock = jest.fn();
  randocall(mock);
  expect(mock).toBeCalledWith(expect.any(Number));
});

expect.arrayContaining(array) 
受信した配列を一致させます.この配列には、予想される配列のすべての要素が含まれます.すなわち,予想配列は受信配列のサブセットである.したがって、受信した配列と一致し、その配列には予期しない要素が含まれます.
文字の値の代わりに使用できます:toEqualまたはtoBeCalledWith
describe('arrayContaining', () => {
  const expected = ['Alice', 'Bob'];
  it('matches even if received contains additional elements', () => {
    expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));
  });
  it('does not match if received does not contain expected elements', () => {
    expect(['Bob', 'Eve']).not.toEqual(expect.arrayContaining(expected));
  });
});

  
describe('Beware of a misunderstanding! A sequence of dice rolls', () => {
  const expected = [1, 2, 3, 4, 5, 6];
  it('matches even with an unexpected number 7', () => {
    expect([4, 1, 6, 7, 3, 5, 2, 5, 4, 6]).toEqual(
      expect.arrayContaining(expected)
    );
  });
  it('does not match without an expected number 2', () => {
    expect([4, 1, 6, 7, 3, 5, 7, 5, 4, 6]).not.toEqual(
      expect.arrayContaining(expected),
    );
  });
});

expect.assertions(number)
テスト中に一定数の断言が呼び出されたことを確認します.これは、通常、非同期コードをテストするときに役立ち、コールバックの断言が確実に呼び出されることを保証します.
2つのコールバックcallback 1とcallback 2を受信する関数doAsyncがあるとします.これは、未知の順序で非同期的に呼び出されます.次のように使用できます.
test('doAsync calls both callbacks', () => {
  expect.assertions(2);
  function callback1(data) {
    expect(data).toBeTruthy();
  }
  function callback2(data) {
    expect(data).toBeTruthy();
  }

  doAsync(callback1, callback2);
});

expect.hasAssertions()
テスト中に少なくとも1つの断言が呼び出されたことを確認します.非同期コードをテストする場合、これは通常、コールバック中の断言が確実に呼び出されることを保証するために役立ちます.
状態を処理する関数がいくつかあると仮定します.prepareStateはステータスオブジェクトのコールバックを呼び出し、validateStateはそのステータスオブジェクトで実行され、waitOnStateはすべてのprepareStateコールバックが完了するまで承諾を返します.次のように使用できます.
test('prepareState prepares a valid state', () => {
  expect.hasAssertions();
  prepareState(state => {
    expect(validateState(state)).toBeTruthy();
  });
  return waitOnState();
});

expect.not.arrayContaining(array)
受信した配列を一致させます.この配列には、予想される配列の要素が含まれません.すなわち,予想される配列は受信配列のサブセットではない.expectとarrayContaining逆
describe('not.arrayContaining', () => {
  const expected = ['Samantha'];

  it('matches if the actual array does not contain the expected elements', () => {
    expect(['Alice', 'Bob', 'Eve']).toEqual(
      expect.not.arrayContaining(expected),
    );
  });
});

expect.not.objectContaining(object) 
予期した属性に再帰的に一致しない受信オブジェクトを一致させます.すなわち、所望のオブジェクトは受信オブジェクトのサブセットではない.したがって、受信したオブジェクトと一致し、そのオブジェクトには予期しないプロパティが含まれます.expectとobjectcontainsは逆です.
describe('not.objectContaining', () => {
  const expected = {foo: 'bar'};

  it('matches if the actual object does not contain expected key: value pairs', () => {
    expect({bar: 'baz'}).toEqual(expect.not.objectContaining(expected));
  });
});

expect.not.stringContaining(string)
一致は、正確な所望の文字列を含まない受信文字列です.expectとstringContaining.反対
describe('not.stringContaining', () => {
  const expected = 'Hello world!';

  it('matches if the actual string does not contain the expected substring', () => {
    expect('How are you?').toEqual(expect.not.stringContaining(expected));
  });
});

expect.not.stringMatching(string | regexp)
一致は、予想regexpの受信文字列に一致しません.expectとstringMatching.反対
describe('not.stringMatching', () => {
  const expected = /Hello world!/;

  it('matches if the actual string does not match the expected regex', () => {
    expect('How are you?').toEqual(expect.not.stringMatching(expected));
  });
});

expect.objectContaining(object) 
一致は、所望の属性の任意の受信オブジェクトに再帰的に一致する.すなわち、所望のオブジェクトは、受信オブジェクトのサブセットである.したがって、受信したオブジェクトと一致し、そのオブジェクトには予期しないプロパティが含まれます.
所望のオブジェクトの文字属性値とは異なり、matchers、expectを使用できます.anything()など.
イベントオブジェクトを使用してonPress関数を呼び出す場合、イベントにeventがあるかどうかを検証する必要があります.x属性とy属性.私たちはこのようにすることができます.
test('onPress gets called with the right thing', () => {
  const onPress = jest.fn();
  simulatePresses(onPress);
  expect(onPress).toBeCalledWith(
    expect.objectContaining({
      x: expect.any(Number),
      y: expect.any(Number),
    }),
  );
});

expect.stringMatching(string | regexp)
予想regexpに一致する受信文字列を一致させます.テキストの値の代わりに使用できます.
1.toEqualまたはtoBeCalledWith 2.arraycontainsの要素3に一致します.objectContainingまたはtoMatchObject のプロパティに一致
この例では、expectを使用して複数の非対称なマッチング器をネストする方法も示します.expectでarrayContaining stringMatching.
describe('stringMatching in arrayContaining', () => {
  const expected = [
    expect.stringMatching(/^Alic/),
    expect.stringMatching(/^[BR]ob/),
  ];
  it('matches even if received contains additional elements', () => {
    expect(['Alicia', 'Roberto', 'Evelina']).toEqual(
      expect.arrayContaining(expected),
    );
  });
  it('does not match if received does not contain expected elements', () => {
    expect(['Roberto', 'Evelina']).not.toEqual(
      expect.arrayContaining(expected),
    );
  });
});

.toBe(value)
toBeは、1つの値があなたの期待に合っているかどうかを確認するだけです.オブジェクトを使用します.完全に等しいことをチェックします.たとえば、このコードはcanオブジェクトのいくつかのプロパティを検証します.
const can = {
  name: 'pamplemousse',
  ounces: 12,
};

describe('the can', () => {
  test('has 12 ounces', () => {
    expect(can.ounces).toBe(12);
  });

  test('has a sophisticated name', () => {
    expect(can.name).toBe('pamplemousse');
  });
});

.toEqual(value)
2つのオブジェクトに同じ値があるかどうかを確認するには、を使用します.toequal.このmatcherは、オブジェクトIDをチェックするのではなく、すべてのフィールドの等化を再帰的にチェックします.これは「深さ等化」とも呼ばれます.たとえば、toEqualとtoBeはこのテストキットで異なるので、すべてのテストに合格しました.
const can1 = {
  flavor: 'grapefruit',
  ounces: 12,
};
const can2 = {
  flavor: 'grapefruit',
  ounces: 12,
};

describe('the La Croix cans on my desk', () => {
  test('have all the same properties', () => {
    expect(can1).toEqual(can2);
  });
  test('are not the exact same can', () => {
    expect(can1).not.toBe(can2);
  });
});

.toMatchObject(object)
使用するtomatchobject JavaScriptオブジェクトがオブジェクトの属性サブセットに一致するかどうかを確認します.受信したオブジェクトと、予期しないオブジェクトにないプロパティが一致します.
また、オブジェクト配列を渡すこともできます.この方法は、受信した配列の各オブジェクト(上記のトマトオブジェクトの意味)が予想される配列の対応するオブジェクトと一致している場合にのみtrueを返します.2つの配列がarrayincludeではなく要素数で一致しているかどうかを確認するには、受信した配列に追加の要素を追加できるため、非常に役立ちます.
属性を値または一致するアイテムに一致させることができます.
const houseForSale = {
  bath: true,
  bedrooms: 4,
  kitchen: {
    amenities: ['oven', 'stove', 'washer'],
    area: 20,
    wallColor: 'white',
  },
};
const desiredHouse = {
  bath: true,
  kitchen: {
    amenities: ['oven', 'stove', 'washer'],
    wallColor: expect.stringMatching(/white|yellow/),
  },
};

test('the house has my desired features', () => {
  expect(houseForSale).toMatchObject(desiredHouse);
});

 
describe('toMatchObject applied to arrays arrays', () => {
  test('the number of elements must match exactly', () => {
    expect([{foo: 'bar'}, {baz: 1}]).toMatchObject([{foo: 'bar'}, {baz: 1}]);
  });

  // .arrayContaining "matches a received array which contains elements that
  // are *not* in the expected array"
  test('.toMatchObject does not allow extra elements', () => {
    expect([{foo: 'bar'}, {baz: 1}]).toMatchObject([{foo: 'bar'}]);
  });

  test('.toMatchObject is called for each elements, so extra object properties are okay', () => {
    expect([{foo: 'bar'}, {baz: 1, extra: 'quux'}]).toMatchObject([
      {foo: 'bar'},
      {baz: 1},
    ]);
  });
});

.toHaveProperty(keyPath ,value)
使用するtohavepropertyは、指定した参照keyPathにオブジェクトのプロパティがあるかどうかを確認します.オブジェクト内の深度ネストのプロパティを確認するには、ポイント表現または深度参照を含むkeyPathの配列を使用します.
オプションとして、ターゲットオブジェクトのkeyPathの値と等しいかどうかを確認する値を指定できます.このmatcherでは、toEqual()などの「深さが等しい」を使用し、すべてのフィールドの等しい性を再帰的にチェックします.
次の例では、ネストされたプロパティを持つhouseForSaleオブジェクトを示します.tohaveプロパティを使用して、オブジェクト内のさまざまなプロパティの存在と値を確認します.
// Object containing house features to be tested
const houseForSale = {
  bath: true,
  bedrooms: 4,
  kitchen: {
    amenities: ['oven', 'stove', 'washer'],
    area: 20,
    wallColor: 'white',
    'nice.oven': true,
  },
};

test('this house has my desired features', () => {
  // Simple Referencing
  expect(houseForSale).toHaveProperty('bath');
  expect(houseForSale).toHaveProperty('bedrooms', 4);

  expect(houseForSale).not.toHaveProperty('pool');

  // Deep referencing using dot notation
  expect(houseForSale).toHaveProperty('kitchen.area', 20);
  expect(houseForSale).toHaveProperty('kitchen.amenities', [
    'oven',
    'stove',
    'washer',
  ]);

  expect(houseForSale).not.toHaveProperty('kitchen.open');

  // Deep referencing using an array containing the keyPath
  expect(houseForSale).toHaveProperty(['kitchen', 'area'], 20);
  expect(houseForSale).toHaveProperty(
    ['kitchen', 'amenities'],
    ['oven', 'stove', 'washer'],
  );
  expect(houseForSale).toHaveProperty(['kitchen', 'amenities', 0], 'oven');
  expect(houseForSale).toHaveProperty(['kitchen', 'nice.oven']);
  expect(houseForSale).not.toHaveProperty(['kitchen', 'open']);
});

最後に書く


ここにリストされているのは一部だけです.詳細は公式サイトを参照してください.https://facebook.github.io/jest/docs/en/expect.html#expectanything

チュートリアル:


   1.フロントエンドテストフレームワークJestシリーズチュートリアル--Matchers(マッチング)
   2.フロントエンドテストフレームワークJestシリーズチュートリアル--Asynchronous(非同期コードのテスト)
   3.フロントエンドテストフレームワークJestシリーズチュートリアル--Mock Functions(シミュレータ)
   4.フロントエンドテストフレームワークJestシリーズチュートリアル--Global Functions(グローバル関数)
     5.フロントエンドテストフレームワークJestシリーズチュートリアル--Expect(検証)