自動テストに関する誤解

こんにちは、私の名前はドミトリー・カルロフスキーです。これは「なぜテストを書くのが好きではないのですか?」という伝統的な見出しの続きです。 簡単な答え:彼らから受け取ったボーナスは費やされた努力を上回らないからです。 もしそうなら、我々は何か間違ったことをしている。 何が間違っていたのか見てみましょう..







注目を集める絵







このメモは、新しい誤解と議論を追加することで、 「自動化されたテストの概念 」長文の「誤解」の章から発展しました。







単体テストは、コンポーネントテストよりも高速です。



はい、mokasは通常、実際のコードよりも速く実行されます。 しかし、それらはある種のエラーを隠しているため、さらにテストを記述する必要があります。 フレームワークが遅延しておらず、コンポーネントツリーを上げるために多くの不必要な作業を行う場合(DOMに釘付けされたWebコンポーネント初期化中に世界のすべてを作成するAngularのTestBedなど )、テストは大幅に遅くなりますが、致命的ではありません。 フレームワークが要求されるまでレンダリングせず、コンポーネントが必要になるまで作成される場合( $ mol_viewなど)、コンポーネントテストはユニットテストより遅くなりません。







コンポーネントテストでバグを見つけるのは難しい



はい、それらがランダムな順序で実行された場合、ロジックのエラーにより、どこから掘り始めるべきかが明確でない可能性のある一連のテストが削除されることがあります。 残念ながら、これは一般的なアンチパターンです。特定の拡張子を持つすべてのファイルを見つけてランダムな順序で実行するために、テストは互いに独立していると言われています。 そして、これは単体テストにも当てはまります。







ただし、コンポーネントテストの実行は、依存度の低いコンポーネントから依存度の高いコンポーネントの順に意味があります。 その後、最初の落ちたテストは問題の原因を示します。 通常、残りのテストは実行できなくなり、テストに合格するまでの時間を節約できます。 繰り返しますが、 MAMアーキテクチャでは、すべてのコード(生産、テスト)が単一の順序でシリアル化されます。 これにより、依存関係テストが依存関係テストの前に実行されるようになります。つまり、依存関係が正しく機能していることを安全に信頼できます。 他のツールを使用する場合は、それらを使用してテストを正しい順序で作成する方法を検討してください。







テストするテンプレートはありません



ロジックをテストする必要があります。 まれなテンプレートエンジン( mustacheview.tree )は、テンプレートにロジックを埋め込むことを禁止しています。つまり、テンプレートもテストする必要があります。 多くの場合、単体テストはこれに適していないため(まれな例外として酵素 )、コンポーネントテストを使用する必要があります。







テストは、Given / When / Thenパターンに従う必要があります。



はい、テストシナリオではこれらの手順を強調表示できますが、手順がない場合は指から吸い出さないでください。 多くの場合、スクリプトはより単純な構造(たとえば、Thenブロックのみ)または複雑な構造(指定/チェック/いつ/次に)を持っています。 いくつかの例:







多くの場合、純粋な関数にはThenブロックのみがあります。







console.assert( Math.pow( 2 , 3 ) === 8 ) // Then
      
      





それほど頻繁ではないが、アクション(When)は、状態の準備(Given)で正確に構成されます。







 component.setState({ name : 'Jin' }) // Given/When console.assert( component.greeting === 'Hello, Jin!' ) // Then
      
      





そして、コードの実行が成功したという事実で十分であるため、チェックは必要ありません。







 ensurePerson({ name : 'Jin' , age : 33 })
      
      





同様のコードは完全に無意味です:







 const component = new MyComponent // Given expect( component ).toBeTruthy() // Then
      
      





決してクラッシュしないテストのように、何もテストしません。 したがって、例外をスローしたことのないアサート-何もチェックしません。







適切なテストには1つのアサートしかありません。



多くの場合、途中で検証することで状態を正しく準備したかどうかを確認する必要があります。







 wizard.nextStep().nextStep() // Given console.assert( wizard.passport.isVisible === false ) // Check wizard.toggleRegistration() // When console.assert( wizard.passport.isVisible === true ) // Then
      
      





このテストを次の2つに分割することはできません。2番目のテストは、最初のテストで作成された状態に暗黙的に依存しているためです。







 wizard.nextStep().nextStep() // When console.assert( wizard.passport.isVisible === false ) // Then
      
      





 wizard.nextStep().nextStep() // Given wizard.toggleRegistration() // When console.assert( wizard.passport.isVisible === true ) // Then
      
      





要件が変更され、デフォルトで登録フォームが表示されることを想像してください。







 wizard.nextStep().nextStep() // When console.assert( wizard.passport.isVisible === true ) // Then
      
      





今、例えば、その状態を使用して作業を高速化するような方法でtoggleRegistration



実装されている場合、2番目のテストに合格し、まだtrueを返し、 toggleRegistration



の最初のアプリケーションはフォームの何も変更しないことがtoggleRegistration



ます:







 isPassportVisible = false toggleRegistration() { this.passport.isVisible = this.isPassportVisible = !this.isPassportVisible }
      
      





デフォルト状態の追加の検証を備えたバージョンでは、この場合、落ちたテストをキャッチします。 さらに、次のステップが前のステップの状態に基づいている場合、より長いスクリプトを書くことを恐れないでください。







 wizard.nextStep().nextStep() // When console.assert( wizard.passport.isVisible === false ) // Then wizard.toggleRegistration() // When console.assert( wizard.passport.isVisible === true ) // Then wizard.toggleRegistration() // When console.assert( wizard.passport.isVisible === false ) // Then
      
      





通常、このアプローチに対する議論は、どのアサーションが落ちたかを理解するのが難しいことです。 しかし、待ってください。テストが失敗した場所に関する包括的な情報を提供しないテストツールを使用するように強制する人はいません。 適切なツール(たとえば、 $ mol_test )を使用すると、この場所でデバッガーを停止することもでき、問題の調査をすぐに開始できます。







要約すると、「Given / When / Then」パターンではなく、絶対的なボイドから始まり、特定の数の状態を通過し、特定の数の状態を通過する小さな冒険としてテストを書くことをお勧めします。








All Articles