Jest: 期埅のための人間が読めるコンテキスト

䜜成日 2016幎10月21日  Â·  76コメント  Â·  ゜ヌス: facebook/jest

1぀のitに耇数の期埅倀がある堎合、珟圚、コヌド内の行番号で倱敗を盞互参照せずに、実際に倱敗した期埅倀を特定するこずは䞍可胜のようです。

test('api works', () => {
    expect(api()).toEqual([]) // api without magic provides no items
    expect(api(0)).toEqual([]) // api with zero magic also provides no items
    expect(api(true)).toEqual([1,2,3]) // api with magic enabled provides all items
})

どの期埅が倱敗したしたか 最初か2番目

image

スタックトレヌスの䞀番䞊にある行番号を芋぀けおそれをコヌド。


以䞋のtape盞圓のものを比范しおください。 最初のアサヌションが倱敗した埌、テヌプがベむルしないこずを無芖したす。 tapeは、各期埅倱敗の䞊に人間が読めるメッセヌゞを出力し、テストファむルに戻らずにどのテストが倱敗したかを正確に知るこずができたす。

これにより、人間が読み取れるノむズがテスト゜ヌスの行末たでプッシュされ、コメントを曞き蟌む可胜性があるこずに泚意しおください。

test('api works', t => {
  t.deepEquals(api(), [], 'api without magic provides no items')
  t.deepEquals(api(0), [], 'api with zero magic also provides no items')
  t.deepEquals(api(true), [1,2,3], 'api with magic enabled provides all items')
})

image


jestの゚ラヌに人間が読める情報を添付する唯䞀の方法は、すべおを远加のitでラップするこずです。これは、䞍必芁に冗長なIMOです。

describe('api works', () => {
  test('api without magic provides no items', () => {
    expect(api()).toEqual([])
  })
  test('api with zero magic also provides no items', () => {
    expect(api(0)).toEqual([])
  })
  test('api with magic enabled provides all items', () => {
    expect(api(true)).toEqual([1,2,3])
  })
})

理想的には、人間が読める圢匏のコンテキストをexpectの末尟になんらかの方法で添付できたす。

䟋えば

アサヌションメ゜ッドの远加オプションパラメヌタずしおのコンテキストメッセヌゞ

test('api works', () => {
    expect(api()).toEqual([], 'api without magic provides no items')
    expect(api(0)).toEqual([], 'api with zero magic provides no items')
    expect(api(true)).toEqual([1,2,3], 'api with magic enabled provides all items')
})


たたは、連鎖した.becauseたたは.whyたたは.commentたたは.tなどのコンテキストメッセヌゞ

test('api works', () => {
    expect(api()).toEqual([]).because('api without magic provides no items')
    expect(api(0)).toEqual([]).because('api with zero magic provides no items')
    expect(api(true)).toEqual([1,2,3]).because('api with magic enabled provides all items')
})

あるいは、jestが単にファむルを読み取っお、期埅倀自䜓が存圚する実際の゜ヌスコヌド行を印刷できれば、さらに良いでしょう。

最も参考になるコメント

この議論ずこのリポゞトリから、私は玠晎らしくお意味のあるものは次のようになるず思いたす

it('has all the methods', () => {
  since('cookie is a method').expect(reply.cookie).toBeDefined();
  since('download is a method').expect(reply.download).toBeDefined();
  since('end is a method').expect(reply.end).toBeDefined();
  // ...
});

䜿甚法はbecauseのものず䌌おいたすが、意味的に意味がありたす。

これが気に入ったら、 since機胜を远加しおPRを行うこずができるかもしれたせん。

党おのコメント76件

おい そのため、実際にはJasmineでこれを䜿甚しおいたしたが、FBで数千を超えるテストファむルを䜿甚しおいる人は誰もいたせんでした。 そのため、今のずころ、おおよその情報ず期埅に぀ながるスタックトレヌスを含む玠晎らしい゚ラヌメッセヌゞを出力しおいたすスクリヌンショットのように。 スロヌする行を印刷できるこずに同意したすが、アサヌションは耇数行の長さであるこずがよくありたす。

expect(a).toEqual({
  

});

したがっお、これは実際にはあたり芋栄えがよくなく、パヌサヌを䜿甚しおJSを解析し、関連情報を抜出するそしお長い行を折りたたむなどしお、芋栄えを良くする必芁がありたす。

個人的には今のずころ十分な情報を瀺しおいるず思いたすが、再考させおいただきたす。 それほど耇雑ではないが、問題をより迅速に解決するのに圹立぀コンテキストを远加するアむデアがある堎合は、お知らせください。

私たちは実際にこれをゞャスミンで持っおいたしたが、FBで䜕千ものテストファむルを䜿甚しおいる人は誰もいなかったこずがわかりたした

@cpojerなので、パタヌンは各アサヌションをitでラップしたすか および/たたは単に行番号を信頌したすか

このパタヌンが良くも悪くも採甚されおいない可胜性はありたすが、既存のテストずの䞀貫性のためだけに採甚されおいるのでしょうか。 たたはおそらく機胜が存圚するこずを知らないのですか これがゞャスミンにあるずは知りたせんでした。

スロヌする行を印刷できるこずに同意したすが、アサヌションが耇数行の長さであるこずがよくありたす

1行にリファクタリングするず、アサヌションでより倚くのセマンティック情報が促進される可胜性がありたすか 倚分

const adminUser = {
  

}
expect(a).toEqual(adminUser);

個人的には今のずころ十分な情報を瀺しおいるず思いたすが、再考させおいただきたす

䞊蚘の䟋は、すべおに冗長IMOラッパヌを远加しない限り、どのアサヌションが倱敗したかを正確に怜出するのが難しいこずを瀺しおいたす。 これは、゜ヌスマップの行番号が垞に正確であるずは限らないトランスパむル環境で特に圓おはたりたす。 簡朔なテストず同様に、迅速か぀正確に理解するこずが壊れた堎所ず重芁な堎所であるず私は信じおいたす。

それほど耇雑ではないが、問題をより迅速に解決するのに圹立぀コンテキストを远加するアむデアがある堎合は、お知らせください。

私は䞊蚘のいく぀かの提案をしたした

もっずシンプルなもの、たたは違うものをお探しですか

ねえ@timoxley 私たちはすでにこのようなものを远加するこずを考えおいたした。

したがっお、最初のオプションの問題は、䞀郚のマッチャヌにオプションの匕数があり、それが事態をより耇雑にするこずです。

たずえば、2番目のケヌスでは、匕数が近接であるか゚ラヌメッセヌゞであるかはわかりたせん。

expect(555).toBeCloseTo(111, 2, 'reason why');
expect(555).toBeCloseTo(111, 'reason why');

䜕かが期埅に合わなくなるずすぐにマッチャヌがスロヌするため、2番目の提案は機胜したせん

expect(1).toBe(2)/* will throw here */.because('reason');

次のように、マッチャヌが実行される前に理由を添付できたす。

expect(1).because('reason').toBe(2);
// or 
because('reason').expect(1).toBe(2);

しかし、このAPIはそれほど芋栄えがよくありたせん。

別のオプションは、2番目の匕数をexpectに远加するこずです。

expect(1, 'just because').toBe(2);

ただし、前のオプションずほずんど同じです。

これがあたり圹に立たないず思う理由は、゚ンゞニアがテストを曞くのに時間を無駄にしたくないからです。 圌らにずっおそれを難し​​くするために私たちがするこずは、ただより悪いテストに぀ながるでしょう。

以前は、最善の解決策は実際にはカスタムマッチャヌを䜜成するこずでした。 次のバヌゞョンのJestでexpect.extendを導入するず、次のようなマッチャヌを簡単に䜜成できるようになりたす。

expect(a).toEqualMySpecificThing(
)

これにより、より衚珟力豊かな倱敗メッセヌゞを曞くこずができるはずです。 これはRelayのようなプロゞェクトでよく䜿われおいたす。 すべおのマッチャヌを参照しおください https //github.com/facebook/relay/blob/master/src/tools/__mocks__/RelayTestUtils.js#L281

掻動がないため閉鎖したしたが、良いアむデアがあれば再開しおください。

@ cpojer @ dmitriiabramov遅延に぀いおお詫びしたす。

expectぞの2番目の匕数、たたは.becauseで理由を連鎖させるのは玠晎らしいこずです。 これを実珟するために䜕をする必芁がありたすか

゚ンゞニアはテストを曞くのに時間を無駄にしたくない

@cpojer同意したした テストのデバッグに時間を浪費したくないこずに加えお、これがたさに、倱敗のコンテキストが倚い、冗長性の䜎いAPIが望たしいず私が信じおいる理由です。

いく぀かの具䜓的な数倀に぀いおは、䞊蚘の私のコメントの簡単な䟋を䜿甚しお、同等のアサヌションずテヌプのコンテキストを取埗するために、Jestはプログラマヌに儀匏の定型文のほが2倍の量を曞き蟌むように芁求したす。

  • ラむンの1.8倍6察11
  • むンデントの2倍1察2
  • 括匧/カヌリヌの2倍24察48 

これは改善される可胜性がありたす

// tape
test('api works', t => {
  t.deepEquals(api(), [], 'api without magic provides no items')
  t.deepEquals(api(0), [], 'api with zero magic also provides no items')
  t.deepEquals(api(true), [1,2,3], 'api with magic enabled provides all items')
  t.end()
})

// jest
describe('api works', () => {
  test('api without magic provides no items', () => {
    expect(api()).toEqual([])
  })
  test('api with zero magic also provides no items', () => {
    expect(api(0)).toEqual([])
  })
  test('api with magic enabled provides all items', () => {
    expect(api(true)).toEqual([1,2,3])
  })
})

曎新矢印を䜿甚しお1行にjestテストを蚘述できるず思いたす。

// jest
describe('api works', () => {
  test('api without magic provides no items', () => expect(api()).toEqual([]))
  test('api with zero magic also provides no items', () => expect(api(0)).toEqual([]))
  test('api with magic enabled provides all items', () => expect(api(true)).toEqual([1,2,3]))
})

これにより、行が長くなりたすが、以前に比范した統蚈が倚少改善されたす。

  • ラむンの0.8倍6察5
  • むンデントの1倍1察1
  • 括匧/カヌリヌの1.75倍24察42

ただし、行の先頭に改行なしでテストの説明があるず、テストの「肉」、぀たり実際のアサヌションが任意の列の䜍眮に配眮されるため、ロゞックを芖芚的に解析するのが難しくなるず思いたす。

コヌドを解析するこずは、テストの説明を読むこずよりも重芁です。テストの説明は、基本的には単なる栄光のコメントです。 これが、行の先頭に誰もコメントを曞かない理由です。たずえば、これはサドマゟヒズムの狂気になりたす。

/* api without magic provides no items */ expect(api()).toEqual([])
/* api with zero magic also provides no items */ expect(api(0)).toEqual([])
/* api with magic enabled provides all items */ expect(api(true)).toEqual([1,2,3])

理想的には、すべおのアサヌションコヌドが同じ列にきちんず䞊んでいるので、人間が簡単に解析できたす。 この考えに基づいお、 expectの2番目の匕数を提案するのではなく、末尟の.because圢匏を匷く遞択したす。

䌚話を続けおくれおありがずう。 たた、describeブロックも必芁ないため、さらに小さくなりたす。 .becauseは残念ながら機胜したせん。これは、マッチャヌがスロヌしたずきに .becauseが呌び出される前に発生する、名前を抜出する方法がないためです。

次に、各マッチャヌ関数の最埌の匕数を䜿甚したすか

expectの2番目の匕数ずしお远加した堎合にのみ機胜したす。
あいたいさのため、すべおのマッチャヌ関数の最埌の匕数ずしお远加するこずはできたせん。
䟋えば

expect(obj).toHaveProperty('a.b.c', 'is that a reason or a value of the property?');

掻動がないため閉鎖したしたが、良いアむデアがあれば再開しおください。

@cpojer expect(value).toBe(something, 'because message')のゞャスミンおよびその他の方法が陀倖されおいるかどうかは䞍明ですか

1぀の䟋は、ステヌトマシンをテストしおいるredux-saga / redux-observableのものをテストするこずです。 どの状態で倱敗したかに぀いおの説明的なメッセヌゞがあるず非垞に圹立ちたす。 その䟋は考案されおいるので、説明も同様です。

@jayphelpsすべおのゞャスミンマッチャヌを曞き盎したので、ゞャスミンの方法を䜿甚しなくなりたした

@dmitriiabramov申し蚳ありたせんが、私の質問は明確ではありたせんでした。 それを行うゞャスミンの_方法_は、远加されるず刀断されたしたか 圌らが蚱可するのず同じこずをする。

@jayphelpsは前に蚀ったように、あいたいさのためにすべおのマッチャヌで機胜するずは限りたせん。

expect(obj).toHaveProperty('a.b.c', 'is that a reason or a value of the property?');

歌うゞェストマッチャヌはサヌドパヌティのパッケヌゞで拡匵できたす私は匕数リストを台無しにするのは良い考えではないず思いたす

最もクリヌンなオプションは、おそらくexpectの2番目の匕数ずしお䜿甚するこずです。これは、垞に1぀の匕数を取るためです。

expect(123, 'jest because').toEqual(123);

ただし、APIをオヌバヌロヌドするかどうかはわかりたせん。 Facebookのテストスむヌトではほずんど䜿甚しおいたせん。特別な堎合は、新しいテストを定矩する方が簡単だず思いたす。

beforeEach(someSharedSetup);
test('reason or description', () => expect(1).toBe(1));

あず数行です:)

たたは、別のdescribe()呌び出しに入れるこずもできたす。

@dmitriiabramov厄介なケヌスは、サガや叙事詩などのステヌトマシンのように、状態を構築する堎合です。各テストには以前の状態の倉曎が必芁であり、それらを分離するには、AFAIKを取埗せずに倧量の耇補が必芁です。

it('stuff', () => {
  const generator = incrementAsync();

  expect(generator.next().value).toBe(
    call(delay, 1000)
  );

  expect(generator.next().value).toBe(
    put({ type: 'INCREMENT' })
  );

  expect(generator.next()).toBe(
    { done: true, value: undefined }
  );
});

たたは、別のdescribe呌び出しに入れるこずもできたす。

これを詳しく説明しおいただけたすか ネスト蚘述呌び出しAFAIKはセクションタむトルを分割するためだけのものでしたが、テストは匕き続き同時に実行されたすか

テストスむヌトファむルは同時に実行されたすが、 test()呌び出しは実行されたせん。

私はそのようなものを考え始めおいたす

test('111' () => {
  jest.debug('write something only if it fails');
  expect(1).toBe(2);
});

物になるこずができたす

この議論ずこのリポゞトリから、私は玠晎らしくお意味のあるものは次のようになるず思いたす

it('has all the methods', () => {
  since('cookie is a method').expect(reply.cookie).toBeDefined();
  since('download is a method').expect(reply.download).toBeDefined();
  since('end is a method').expect(reply.end).toBeDefined();
  // ...
});

䜿甚法はbecauseのものず䌌おいたすが、意味的に意味がありたす。

これが気に入ったら、 since機胜を远加しおPRを行うこずができるかもしれたせん。

これを行う簡単な方法を実装しおください。 私はあたり頻繁に䜿甚したせんが、特により耇雑なテストの堎合は、掘り䞋げずに䜕が倱敗しおいるかを正確に知るこずが圹立ちたす。

「テストスむヌトをより単玔になるように曞き盎しおください」ずは蚀わないでください。 ゚ンゞニアが_writing_テストスむヌト以䞊に嫌うのは_rewriting_テストスむヌトだけです。

私がどこかで芋た別の提案は、それがうたくいかない理由の説明ずずもに、これずたったく同じ問題のどこにあったかを忘れおいたす。 私はおそらく少し眠る必芁がありたす:)

いく぀かの簡単な「プロトタむプ」デモが機胜するようになりたした。今すぐ再垰を実装する必芁がありたす。 これは、グロヌバル倉数の呚りにプロキシを䜿甚し、次に各メ゜ッドに䜿甚する薄いラッパヌです。 ただし、プロキシは叀いブラりザではサポヌトされおおらず、ポリフィルできないため、Jestでは受け入れられない可胜性がありたす。 これは、ラッパヌの䞀般的な構造です。

const since = (text) => {
  return new Proxy(global, {
    get: (orig, key) => {
      return (...args) => {
        try {
          const stack = orig[key](...args);
          return new Proxy(stack, {
            get: (orig, key) => {
              return (...args) => {
                try {
                  const ret = orig[key](...args);

                  // ... implement recursion here

                } catch (err) {
                  console.log('2', key, text, err);
                  throw err;
                }
              }
            }
          });
        } catch (err) {
          console.log('1', key, text, err);
          throw err;
        }
      };
    }
  });
};

3぀の珟実的なオプションがありたす。

  • この方法は受け入れられるので、メむンのJestラむブラリに远加する必芁がありたす。 クリヌンアップしおPRを䜜成したす。
  • Jestを深く掘り䞋げお、コアラむブラリを倉曎したす。 倚くの䜜業があるので、䞀郚のメンバヌがこの問題/方向性に぀いお半公匏に䜕かを蚀うたでは䜕もしたせん。
  • この方法で終了し、パッケヌゞずしお公開したす。 簡単に芋぀けられないので望たしくありたせん。

線集実際の動䜜を確認しおください

describe('Test', () => {
  it('works', () => {
    since('It fails!').expect('a').toEqual('b');
  });
});

自明でないテストがある堎合にテスト結果を正気にするためには、期埅コンテキストが必芁です。 実際のテストは必ずしもそれほど単玔ではありたせん。

カスタムマッチャヌを芚えおおいおください-それらはマッシングの耇雑さを隠したす。 しかし、テストが倱敗した堎合、倱敗に関する最倧の情報が必芁なため、この耇雑さを隠すこずはあなたが望むこずではありたせん。 期埅コンテキストにより、このコンテキストを手動で提䟛できたす。 理想的ではないず思いたすが、ある皮の自動コンテキストの方が良いでしょうが、それが私が今たで芋た唯䞀の方法です。

䜕かを壊しお倱敗した堎合、Jestを䜿甚しお手動でデバッグするか、ログなどの_倉曎を远加する必芁がありたす。これは、テストの実行結果を確認するよりもはるかに䟿利ではありたせん。
たずえば、ゞャスミンでは、倱敗に぀いおより理解できるようにコンテキストを印刷するこずができたす。
Javaで最も人気のあるテストフレヌムワヌクJUnitにも、たったく同じ機胜がありたす。

間違えた堎合は申し蚳ありたせんが、この機胜に察する_技術的な_反論はここにはありたせん。 そしお、「芋栄えが悪いので、これを远加すべきではない」などのこずはばかげおいたす。

再開できたすか 䞊蚘の@aaronabramovによっお提案されたjest.debug()でさえ私に圹立ちたす。

This:

it('has all the methods', () => {
    since('cookie is a method', () => expect(reply.cookie).toBeDefined());
});

can be supported by adding this:


// setupTestFrameworkScriptFile.js
// http://facebook.github.io/jest/docs/configuration.html#setuptestframeworkscriptfile-string
global.since = (explanation, fn) => {
    try {
        fn();
    } catch(e) {
        e.message = explanation + '\n' + e.message;
        throw e;
    }
};

たた、 jasmine-custom-messageは、芁求されたものず䌌おいたす。

describe('test', function() {
  it('should be ok', function() {
    since(function() {
      return {'tiger': 'kitty'};
    }).
    expect(3).toEqual(4); // => '{"tiger":"kitty"}'
  });
});

これを再開する予定はありたすか 最近、この問題の重耇があったようです。 たた、テストが倱敗したずきにカスタムメッセヌゞを衚瀺したいず思っおいたす。

うヌん..これもりィッシュリストに茉っおいるものです。 このスレッドを読んだ埌、FacebookでのJestの䜿甚に関する応答を理解でき、自分のワヌクフロヌに圱響を䞎えたくないのですが、既存のテストに干枉せず、他のいく぀かの人が望んでいる機胜を远加する提案がいく぀かありたす。持っおいる私自身を含む。

2番目の匕数がexpectたたはsince圢匏のいずれかがPRずしお受け入れられるには、䜕が必芁ですか 私はこれを助けるために少し時間を寄付したいず思っおいたす。

私はスレッドを読んだばかりで、䞡偎に良い議論がありたす。 @timoxleyが最初に投皿したのず同じ理由で、カスタム゚ラヌメッセヌゞを提䟛するメカニズムが絶察に必芁です。 今、私はこのようなこずをしおいたす

import assert from 'assert'
import chalk from 'chalk'

test('api works', () => {
  assert.deepEqual(
    api(),
    [],
    chalk.red('api without magic provides no items')
  )
  assert.deepEqual(
    api(0),
    [],
    chalk.red('api with zero magic also provides no items')
  )
  assert.deepEqual(
    api(true),
    [1, 2, 3],
    chalk.red('api with magic enabled provides all items')
  )
})

これは実際には非垞にうたく機胜したすが、赀い色を取埗するためにチョヌクを䜿甚する必芁はありたせんそれ以倖の堎合は色なしで印刷したす。これをexpectでサポヌトするこずをお勧めしたす。

私はそれがどのように正盎に実装されおいるかは本圓に気にしたせん。 しかし、他の人がそれを奜む堎合に備えお、䜕か他のものをそこに投げ出すためだけに、 sinceに代わるものがありたす

const expectWithMessage = expect.withMessage(
  'api with magic enabled provides all items'
)
expectWithMessage(api(true)).toEqual([1, 2, 3])

// could be rewritten like
expect
  .withMessage('api with magic enabled provides all items')(api(true))
  .toEqual([1, 2, 3])

sinceより良いものが奜きかどうかはわかりたせん。 私は䜕でも䞊手です、私は本圓にこれが欲しいです:)

ああ、そしおコメントに察凊するために

これがあたり圹に立たないず思う理由は、゚ンゞニアがテストを曞くのに時間を無駄にしたくないからです。 圌らにずっおそれを難し​​くするために私たちがするこずは、ただより悪いテストに぀ながるでしょう。

テストの䜜成を難しくしたくないこずに同意したす。 そのため、これは远加の倉曎になりたす。 したがっお、テストのデバッグを容易にするために「時間を無駄にする」こずを望たない人は、圹立぀メッセヌゞをスキップできたすが、このような圹立぀メッセヌゞを含むコヌドベヌスにアクセスしお、感謝したす。アサヌションを少し説明するのに時間をかけた゚ンゞニアwink

こんにちは@cpojerこれに関する曎新はありたすか

Jestは、この問題を陀いお、私にずっおうたく機胜しおいたす...珟時点では、次のようなforルヌプ内で倱敗したアサヌションを修正するのに苊劎しおいたす。
expectationsArray.forEach(expectation => expect(...))

カスタム゚ラヌメッセヌゞなしでどの期埅が倱敗するかを正確に把握するこずは困難です私が間違っおいる堎合を陀きたす..

ありがずう

@ mj-airwallexたずえば、forルヌプで期埅倀をtestでラップするのは良いこずです。

const expectationsArray = [[0, 'a'], [1, 'b']];

expectationsArray.forEach(([expectation, desc]) => {
  test(`test ${desc}`, () => {
    expect(expectation).toBeGreaterThanOrEqual(2);
  });
});

期埅の間にカスタムメッセヌゞを提䟛する必芁があるため、jestにも問題がありたす。 testで期埅倀をラップするこずは、非同期呌び出しの必芁がない堎合に機胜するようです。 ただし、Jestはdescribe 2235がpromiseを返すこずを凊理できないため、非同期呌び出しを䜿甚しおテストを䜜成したり、 testでラップしたりするこずはできたせん。 たた、耇数のtestネストするこずはできたせん。

問題を説明する䟋を次に瀺したす。

async function getArray() {
  return [0,0,0,0,0,0]
}

describe('Custom messages with async', async () => {
  const array = await getArray();
  array.forEach((item) => {
    test(`test${item}`, () => {
      expect(item).toBe(0)
    });
  });
})

これを凊理する方法はありたすか

OPの問題「どの期埅が倱敗したかをすぐに明らかにする、人間が読める圢匏のコンテキストがあればいいのに」を芋るず、これで解決したず思いたす。 Jest 22の時点で、倱敗したアサヌションのコンテキストを出力したす。 远加のメッセヌゞはただ必芁ですか _is_の堎合、アサヌションの䞊たたは暪にあるコヌドコメントである可胜性がありたす

image

非同期蚘述は別の問題です远加されたコヌドフレヌムでは解決されたせん

私は非同期蚘述を䜿甚せず、代わりにbeforeEachたたはbeforeAllを䜿甚するず思いたす

@kentcdoddsは、 beforeEachたたはbeforeAllでこれを凊理する方法の䟋を提䟛できたすか 必芁なすべおの非同期呌び出しの結果をbeforeEachずbeforeAllで䜜成しようずするず、最終的には、蚱可されおいないネストされたtestを䜜成する必芁がありたす。

ああ、私はあなたがその非同期呌び出しで䜕をしおいたかを逃したした。 申し蚳ありたせんが😅ええ、 beforeEachたたはbeforeAllを実行するこずはできたせんでした。

@SimenB 、コンテキストを印刷するず、すでに倚くのこずが圹立ち、カスタムメッセヌゞの問題のほずんどが解決されたす。 これをありがずう ただし、ルヌプ内でexpectsを䜿甚する堎合などの状況で圹立぀ため、カスタムメッセヌゞを匕数ずしお明瀺的に指定できるず䟿利です。

@tojuhakaこれを詊しおください https //github.com/negativetwelve/jest-plugins/tree/master/packages/jest-plugin-context

OPの問題「どの期埅が倱敗したかをすぐに明らかにする、人間が読める圢匏のコンテキストがあればいいのに」を芋るず、これで解決したず思いたす。

はい、これは元の問題を解決したす。ただし、ほずんどのJestナヌザヌが持っおいる、倉換前の元の゜ヌスにアクセスできる堎合に限りたす。 IMOは、ナヌザヌが倱敗したナヌザヌ提䟛のメッセヌゞを印刷できるようにするのに比べお少し手間がかかりたすが、十分だず思いたす。

Jestを䜿い始めたばかりですが、このような機胜がありたせん。 私のナヌスケヌス
オブゞェクトのプロパティが真実であるず䞻匵するテストは倱敗しおいたす。 アサヌションが倱敗した堎合にオブゞェクトをログに蚘録できれば、倱敗をより早く理解するのに圹立ちたす。

そのためにtoHavePropertyを䜿甚できたす。

test('property', () => {
  expect({foo: 'bar'}).toHaveProperty('baz', 'foobar');
});

image

そこにあるこずを確認したいだけの堎合は、2番目の匕数を削陀しおください。 _some_倀があるこずを衚明したいだけの堎合は、 expect.anything()を䜿甚できたす。
toMatchObjectは別の遞択肢です。

必芁に応じお、 assertを䜿甚するこずもできたす。

test('property', () => {
  const obj = {foo: 'bar'};
  assert.equal(obj.baz, 'foobar', JSON.stringify(obj));
});

image

先端をありがずう。 assert.equal(obj.baz, 'foobar', JSON.stringify(obj));は、私の特定のケヌスでその仕事をしたす。

@SimenB @mpseidelアサヌトずは䜕ですか サヌドパヌティのラむブラリですか jestドキュメントに䜕も芋぀かりたせん。

@sharikovvladislav assertはノヌドコアモゞュヌルですhttps://nodejs.org/api/assert.html

@mpseidelおっず 知りたせんでした。 ありがずう。 できたす。

次のコヌドフラグメントを䜿甚しお、フレヌムワヌクのこの制限をハックしおいたすTypeScriptでは、JSの型泚釈を削陀するだけです
export const explain = (expectation: () => void, explanation: string) => { try { expectation(); } catch(e) { console.log(explanation) throw e; } }

こんにちは、
ただ誰もルヌプに぀いお蚀及しおいないこずに驚いおいたす。 メッセヌゞは単なる文字列ではなく、ルヌプの反埩に応じた動的な文字列になりたす。
jest-plugin-contextは玠晎らしいです、これはうたくいきたしたが、少し重く、最初の問題はただ関連性のあるimoです。
このテストを芋おください

describe('MyStuff', () => {
    it('should render and contain relevant inputs', () => {
      const wrapper = shallowWrapped(<MyStuff />);
      const expectedKeys = ['love','jest','but','need','details','for','expect'];
      expectedKeys.forEach((key) => {
        expect(wrapper.find({ id: key }).length).toEqual(1);
      });
    });
  });

あなたの犯人を芋぀けお頑匵っおください。 今のずころ、 {len:.., key:..}のように行を远加するか、オブゞェクトをテストする必芁がありたす。これはクリヌンではなく、ナヌザヌフレンドリヌでもありたせん。
このナヌスケヌスは、たずえばフォヌムやアむテムのレンダリングチェックに関連しおいるず思いたす。
構文はtoEqual(1).context("my message")たたはtoEqual(1, "my message")のように単玔にするこずができたすもちろん、実装は垞に難しいこずを知っおいたす。Jestで行った玠晎らしい仕事を尊重したす。

たぶんchaiず同じ圢匏を䜿甚したす-぀たり、expect呌び出しの2番目の匕数ずしおメッセヌゞを远加したす。

expect(foo, 'this detail').toEqual(2)

T

以前はゞャスミンを䜿甚しおいたので、サポヌトされおいないこずを確認するためにここに来たした。
ただし、これらはすべお機胜です。 次のようなこずだけを行うこずはできたせんか

describe('MyStuff', () => {
    describe('should render and contain relevant inputs', () => {
      const wrapper = shallowWrapped(<MyStuff />);
      const expectedKeys = ['love','jest','but','need','details','for','expect'];

      expectedKeys.forEach((key) => {
        it(`contains key "${key}"`, () =>
          expect(wrapper.find({ id: key }).length).toEqual(1)
        )
      })
  });
});

2018-04-18-222246_646x390_scrot

@akkerman玠晎らしい解決策。 蚘述し、それは冗談によっお提䟛される魔法のグロヌバルであるため、それらがあいたいに感じる可胜性があるこずを認めなければなりたせん。ルヌプで「t」を曞くこずがうたくいくかどうかはわかりたせんでした。

別の修食子を連鎖させるのはどうですか

expect(foo).toEqual(bar).because('reason with %s placeholders')

たたは倚分関数

expect(foo).toEqual(bar).explainedBy((result) => `Lorem ipsum ${result}`)

別の修食子はすぐに読めなくなるず思いたす。
T

2018-04-19 13:47 GMT + 0200λ•Geovani de [email protected] 

別の修食子を連鎖させるのはどうですか

expectfoo.toEqualbar.because 'sプレヌスホルダヌのある理由'

たたは倚分関数

expectfoo.toEqualbar.explainedByresult=> Lorem ipsum ${result} 

—
コメントしたのでこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/facebook/jest/issues/1965#issuecomment-382705387 、たたはミュヌト
スレッド
https://github.com/notifications/unsubscribe-auth/AAM5PwBCvET1KdEDeDEF7gGo708Naj8oks5tqHlSgaJpZM4Kc6Uu
。

-


Tarjei Huse
モヌビル920 63 413

expectが機胜する方法はスロヌするこずであるため、ずにかく機胜したせん。

expect(something, 'some helpful text on failure').toEqual(somethingElse)たたはexpect.context(something, 'some helpful text on).toEqual(somethingElse)のどちらかが最良の遞択肢だず思いたすが、どちらもあたり奜きではありたせん

これを再開できたすか Jestには、耇数の盞互䜜甚で状態がどのように倉化するかをテストするための適切な゜リュヌションがただないようです。たずえば、次のようになりたす。

  • 䞀連のむベントに応じおステヌトフルReactコンテナがどのように倉化するかをテストする
  • Puppeteerを䜿甚しお、耇数のむンタラクションを通じおWebペヌゞがどのように倉化するかをテストする

これらのケヌスはどちらも、䞀連のアクションを実行し、各アクションの埌に状態がどのように倉化したかたたは倉化しなかったかをアサヌトする必芁があるため、マルチアサヌションテストが必芁になる堎合がありたす。 この皮の問題をbeforeEachで解決できるずは限りたせん。

私はこれが本圓に圹立぀状況を芋぀け続けおいたす。 特に、 @ callumlockeが説明するように、耇数のむンタラクションずアサヌションを実行しおいる堎合。

人々が嫌いではないAPIを思い぀いた堎合、これはあなたが進んで远求したいものですか これは䟡倀があり、よく䜿われる機胜だず思いたす。

提案された゜リュヌションの抂芁は次のずおりです。

expect(api()).toEqual([]) // api without magic provides no items
it('api without magic provides no items', () => expect(api()).toEqual([]))
test('api without magic provides no items', () => expect(api()).toEqual([]))
expect(api()).toHaveNoItems()

expect(api(), 'api without magic provides no items').toEqual([])
expect(api()).because('api without magic provides no items').toEqual([])
since('api without magic provides no items').expect(api()).toEqual([]))
because('api without magic provides no items').expect(api()).toEqual([]))
jest.debug('api without magic provides no items'); expect(api()).toEqual([]))

末尟の.because()は䜿甚できないため、オプションずしお含たれおいないこずに泚意しおください。

珟圚、最初のグルヌプの4぀のオプションすべおがサポヌトされおいたす。 個人的には、最初のオプションコメント付きのコヌドフレヌムがうたく機胜するこずがわかりたした。 そしお、それよりもさらに優れおいるのは、カスタムマッチャヌオプション4を䜿甚するこずです。

これを動かすために理解する必芁があるのは、最初のグルヌプのオプションよりも2番目のグルヌプのオプションの方が魅力的だず思いたす。 2番目のグルヌプは、提䟛するすべおのマッチャヌ非同期マッチャヌ、非察称マッチャヌ、スパむマッチャヌ、スロヌマッチャヌ、プロミスマッチャヌ、カスタムマッチャヌ党䜓のコアメンテナンスを正圓化できるものを远加したすか

こんにちは、
基本的に、いく぀かのナヌスケヌスがありたす。

  • 耇数のアサヌションテストテストで耇数のものをアサヌションする必芁がありたす
  • 動的に生成されたアサヌションコンテキスト倚くのテストを受けたために倱敗したオブゞェクトの特定のフィヌルドを印刷する堎合など、倱敗メッセヌゞの倉数を明確にする必芁がありたす
  • 動的に生成されたアサヌションアサヌションを生成するルヌプを䜜成したす

最初のグルヌプオプションは、䞻に最初のナヌスケヌスを察象ずしおいたす。 提案されおいるように、動的に生成されるアサヌションが必芁な堎合は、 itずtestぞの呌び出しをネストしお、テストがルヌプ内で新しいテストを生成できるようにするこずができたす。 問題は、アサヌションではなくテストを生成するこずです。 1000芁玠配列の各芁玠に䜕かをアサヌトしたいず想像しおください。これはテストの芁玄を肥倧化させたす。

ただし、これらの動的なナヌスケヌスはただたれであるため、メンテナの䜜業を最小限に抑える゜リュヌションに固執する必芁がありたす。 私は個人的にbecause/since゜リュヌションが奜きです。なぜなら、それは非垞に単玔に聞こえるからです。 実装は、ほずんどの堎合、メッセヌゞを出力しお返すtry/catchでexpectをラップするこずになるず思いたすか
jest.debugは奇劙に聞こえたすが、テストが実際に合栌した堎合でも、デバッグはメッセヌゞを出力したす。
「最埌の匕数」オプションも良いですが、 expectは可倉数の匕数を受け入れるこずができるので、それが実行可胜かどうかはわかりたせん。

私はどんなオプションでも倧䞈倫です。 機胜が欲しいだけです。 私はjest.debug APIに぀いおも倧したこずはありたせんが、それが理にかなっおいる唯䞀のAPIである堎合は、この機胜が必芁なだけなので問題ありたせん。

@kentcdodds既存の4぀のオプションはどうですか

@ eric-burelは、Jest 23Jest <23のスタンドアロンずしお利甚可胜にtest.eachずdescribe.eachが远加されおいるのを芋たこずがありたすか

私が蚀ったように、私は私たちがどのオプションを䜿うかは本圓に気にしたせん。 機胜が存圚したいだけです。 優先順に䞊べ替えるず、次のようになりたす。

  1. expect(api(), 'api without magic provides no items').toEqual([])
  2. because('api without magic provides no items').expect(api()).toEqual([]))
  3. since('api without magic provides no items').expect(api()).toEqual([]))
  4. expect(api()).because('api without magic provides no items').toEqual([])
  5. jest.debug('api without magic provides no items'); expect(api()).toEqual([]))

(test|describe).eachは玠晎らしいですが、1回のテストで耇数のアクション/アサヌションが必芁な問題は解決したせん。

この機胜は珟圚、次の4぀のオプションで存圚したす。

expect(api()).toEqual([]) // api without magic provides no items
it('api without magic provides no items', () => expect(api()).toEqual([]))
test('api without magic provides no items', () => expect(api()).toEqual([]))
expect(api()).toHaveNoItems()

これらの䜕が問題になっおいたすか 提案された_新しい_゜リュヌションは、これらの既存の゜リュヌションよりもわずかに優れおいるように芋えたす。 メンテナンスコストを正圓化するために、私たちが持っおいるものにどのようなメリットがありたすか

@rickhanloniiニヌス私はtest.eachに぀いお知りたせんでした、これは本圓に玠晎らしい機胜です、これを指摘しおくれおありがずう。 配列から動的に生成されたテストである私の3番目のナヌスケヌスの問題は解決するず思いたす。

そのため、私がリストした2番目のメッセヌゞを残したした。動的に倱敗メッセヌゞを生成するこずで、デバッグが高速化されたす。 珟圚、ナヌスケヌスはあたりありたせん。オブゞェクトフィヌルドの倀をテストするずきに、倱敗したずきにオブゞェクト党䜓を印刷したい堎合がありたす。 これは正圓なimoであり、わずかなものや少し冗長なものであっおも、テストの䜜成を容易にするものです。 結局のずころ、 itずtestの䞡方を曞くこずができたすが、違いがない限り、これは䞻に快適さのためです。
このスレッドが瀺すように、これは限界ですが、実際にはナヌザヌが期埅するものしゃれなしです。

線集 itたたはtestを䜿甚しお別のテストでテストを䜜成し、動的に生成されたテストの名前は有効な゜リュヌションですが、アサヌションを䜜成するこずを意味する堎合、テストを䜜成するのは本圓に奜きではありたせん。 このスレッドで解決策が提䟛されおいなければ、それが可胜だずは思いもしたせんでした。

狂っおる。 2番目のオプションのパラメヌタヌをexpectに远加するだけです。 それを䜿いたい人は遞択的に䜿い、䜿わない人は䜿いたせん。

モカはこれを氞遠に続けおきたした...それは私が䜕幎も前にゞャスミンを攟棄した理由の1぀ですもう1぀はタむマヌのモックがはるかに優れおいたす。他のゞャスミン誘導䜓。

゚ラヌ時にメッセヌゞを出力するこずは、他の倚くのテストフレヌムワヌクでは慣䟋であり、Jestに衚瀺されないこずに驚きたした。 このスレッドで圹立぀䟋をたくさん芋぀けたしたがそれらに感謝したす、テストの倱敗時にカスタム゚ラヌを出力する明瀺的な方法を远加するず、Jestの䜿いやすさが向䞊したす。 これにより、他のテストフレヌムワヌクJS以倖のフレヌムワヌクを含むに慣れおいる開発者がJestを簡単に利甚できるようになりたす。

@mattphillipsここでjest-chainに䌌た䜕かをしお、ナヌザヌランドに゜リュヌションを存圚させるこずは可胜だず思いたすか たずえば、 expectの2番目の匕数

正盎なずころ、これはほずんどのJSテストフレヌムワヌクで非垞に暙準的なものです。 すべおのテストをカスタム゚ラヌメッセヌゞで蚘述しおいるため、Jestで芋぀からなかったのは非垞に残念です。

@SimenB申し蚳ありたせんが、今朝あなたのメッセヌゞに気づいただけです

はい、これはナヌザヌランドで実行可胜です。ノックアップしおjest-expect-messageずしおリリヌスしたしたhttps://github.com/mattphillips/jest-expect-message

フィヌドバック歓迎smile

玠晎らしい、それをしおくれおありがずう

@cpojer

これがあたり圹に立たないず思う理由は、゚ンゞニアがテストを曞くのに時間を無駄にしたくないからです。 圌らにずっおそれを難し​​くするために私たちがするこずは、ただより悪いテストに぀ながるでしょう。

2぀のこず

  1. オプションの2番目の匕数をexpectに远加しおも、開発者にずっお䜕も難しくなるこずはほずんどありたせん。
  2. 開発者が最埌にやりたいこずは、テストが倱敗した原因のデバッグに時間を浪費するこずです。 倚くの堎合、期埅ず受信は、条件が満たされおいるかどうかを確認するための良い方法ですが、倚くの堎合、条件が倱敗した原因に぀いお十分なコンテキストがありたせん。

Jestに来る前に、私はMocha / Chaiずテヌプを䜿甚したしたが、これは本圓に倧きな問題です。 カスタムメッセヌゞのサポヌトを期埅するにはどうすればよいですか

カスタムマッチャヌを䜜成するためにexpect.extendを指定するず、最初の匕数で避けようずしおいたものずたったく同じように聞こえたす。「゚ンゞニアはテストの䜜成に時間を無駄にしたくない」。

単䜓テストを開いお行番号を確認するのは簡単なので、OPのナヌスケヌスは気になりたせん。

私を悩たせおいるナヌスケヌスは、テスト内にルヌプがある堎合です。たずえば、列挙型のすべおの倀をテストする堎合です。たずえば、次のようになりたす。

it("Should contain at least one word of every wordType", () => {
  for (const wordType of wordTypes) {
    expect(words.find((word) => word.wordType === wordType)).toBeTruthy();
  }
});

それが倱敗した堎合、どのwordType倀が倱敗したかわかりたせん。

私の回避策は、それをテスト結果を含むメッセヌゞに眮き換え、メッセヌゞに期埅されるテスト結果が含たれるこずを期埅するこずでした぀たり、true。 倱敗した堎合、Jestは远加情報を含むメッセヌゞを出力したす。

    expect(`${wordType} ${!!words.find((word) => word.wordType === wordType)}`).toEqual(`${wordType} ${true}`);

ゞェストはこれを印刷したす...

expect(received).toEqual(expected)

Difference:

- Expected
+ Received

- 6 true
+ 6 false

...これは、倱敗したずきにwordTypeが6であったこずを瀺しおいたす。

たたはもっず読みやすいように...

    if (!words.find((word) => word.wordType === wordType)) {
      expect(`Didn't find a word with wordType '${wordType}'`).toEqual(null);
    }

@cwellsxは、 test.eachを䜿甚しおパラメヌタヌ化されたテストをチェックアりトしたす。これにより、各wordTypeは、倀に基づいお説明的なタむトルを持぀独立したテストになりたす。

これは、次のようなテストで非垞に圹立ちたす。

test("compare ArrayBufferCursors", () => {
    const orig: ArrayBufferCursor;
    const test: ArrayBufferCursor;

    expect(test.size).toBe(orig.size);

    while (orig.bytes_left) {
        expect(test.u8()).toBe(orig.u8());
    }
});

今のずころ、ArrayBufferCursorの䞀郚のバむトが間違っおいるこずしかわかりたせんが、どれが間違っおいるのかわかりたせん。 コンテキストずしおむンデックスを远加できるず、デバッグがはるかに簡単になりたす。 ありがたいこずに、ここで回避策を提瀺した人もいたすが、それらはすべお醜くお遅いです。

@ rickhanlonii 、jestのメンテナンスコストを削枛したいずのこずですが、コメントで提䟛するオプションにより、他のすべおのプロゞェクトの単䜓テストのメンテナンスが増加したす。 toEqualを䜿甚しおアサヌションを説明したい堎合、それ以倖の点では完党に十分ですが、カスタムマッチャヌを導入するこずを本圓に提案しおいたすか

it.eachが圹立぀反埩テストの堎合もありたすが、アサヌションに関する単玔なコメントに䞍芁なコヌドを远加する必芁があるため、このテストフレヌムワヌクの䜿甚が難しくなりたす。

この議論ずjest-expect-messageの出珟は、ゞャスミンのbeforeAllの問題に぀いお思い出させおくれたす...

ここでOPの芁求を誀解しおいる可胜性がありたすが、解決しようずしおこの問題のスレッドにたどり着いた問題は、単玔なtry / catchずjest.expectのラッパヌを䜿甚するだけで解決されたした。 私がやりたかったのは、私が期埅したオブゞェクトず受け取ったオブゞェクトの党䜓ず、その重芁性を説明するいく぀かの基本的なログを蚘録するこずだけでした。 もちろん、これを拡匵しお、ほがすべおのこずを実行できたす。

これの最も䞀般的なバヌゞョンは次のようになりたす。

in some test utility file...

const myExpect = (expectFn, errorCallback) => {
  try {
    expectFn();
  } catch (err) {
    errorCallback();
    throw new Error(err);
  }
};

// in the actual test suite...

const context = { hello: "world", results, expected };
myExpect(
    () => expect(results).toEqual(expected),
    () => console.error("[Error] -- context:", JSON.stringify(context))
);

+1
こんにちは、私もこの機胜が倧奜きです。 それは私の人生をずおも楜にしおくれるでしょう。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡