自動単体テストは静的型チェックを置き換えることができますか?

StackOverflow https://stackoverflow.com/questions/415434

  •  03-07-2019
  •  | 
  •  

質問

私は単体テスト/テスト駆動開発のアイデア全体を検討し始めましたが、考えれば考えるほど、静的型チェックと同様の役割を果たすように思えてきます。どちらの手法でも、プログラム内の特定の種類のエラーをコンパイル時に迅速にチェックできます。ただし、間違っている場合は訂正してください。完全にカバーする単体テスト スイートでは、静的型チェックでテストされるすべてのテストと、その後のいくつかのテストが行​​われるようです。別の言い方をすると、静的型チェックはプログラムが正しいことを「証明」するための手段の一部にすぎませんが、単体テストでは(ある程度まで)必要に応じて「証明」できます。

では、単体テストも使用している場合、静的型チェックを備えた言語を使用する理由はあるのでしょうか?やや似たような質問がありました ここ, もう少し詳しく見ていきたいと思います。静的型チェックには、単体テストに比べて具体的にどのような利点がありますか?コンパイラの最適化やインテリセンスなどの問題がいくつか思い浮かびますが、それらの問題に対する他の解決策はあるのでしょうか?私が思いつかない他の利点/欠点はありますか?

役に立ちましたか?

解決

自動化された単体テストは、動的な型付き言語にとって重要になると思いますが、それは、適用するコンテキストで静的な型チェックを置き換えるという意味ではありません。実際、動的型付けを使用する人の中には、定数型安全性チェックの煩わしさをしたくないために、実際に使用している人もいます。

静的型付け言語に比べて動的型付け言語が提供する利点は、テストをはるかに超えており、型の安全性は1つの側面にすぎません。動的および静的型付き言語のプログラミングスタイルと設計の違いも大きく異なります。

さらに、型安全性を厳しく強制するように書かれた単体テストは、ソフトウェアが結局動的に型付けされるべきではないか、適用される設計が動的な言語ではなく静的に型付けされた言語で書かれるべきであることを意味します

他のヒント

ソフトウェアの品質に関して不変の事実が1つあります。

  

コンパイルできない場合、出荷できません

このルールでは、静的に型付けされた言語が動的に型付けされた言語に勝ちます。

はい、はい、このルールは不変ではありません。 Web Appsはコンパイルせずに出荷できます(コンパイルしなかった多くのテストWebアプリをデプロイしました)。しかし、基本的に正しいのは

です
  

エラーをキャッチするのが早ければ早いほど、修正のコストは安くなります

静的に型付けされた言語は、ソフトウェア開発サイクルの最も早い時点で実際のエラーが発生するのを防ぎます。動的言語はそうではありません。ユニットテストは、超人的なレベルまで徹底していれば、静的に型付けされた言語の代わりになります。

しかし、なぜわざわざ?コンパイラの形でエラーチェックシステム全体を書いている信じられないほど優秀な人がたくさんいます。すぐにエラーが発生することが心配な場合は、静的に型付けされた言語を使用してください。

この投稿を動的言語のバッシングと見なさないでください。私は毎日動的言語を使用し、それらを愛しています。それらは信じられないほど表現力と柔軟性があり、信じられないほどファンシーなプログラムを可能にします。しかし、早期のエラー報告の場合、静的に型付けされた言語を失います。

合理的なサイズのプロジェクトでは、単体テストのみですべての状況を説明することはできません。

だから私の答えは<!> quot; no <!> quot;であり、すべての状況に対処できたとしても、そもそも動的言語を使用するという目的全体を破ってしまいました。

タイプセーフをプログラムする場合は、タイプセーフ言語を使用することをお勧めします。

コードカバレッジが100%であっても、アプリケーションを完全にテストしたわけではありません。次のコードを検討してください:

if (qty > 3)
{
    applyShippingDiscount();
}
else
{
    chargeFullAmountForShipping();
}

qty = 1およびqty = 4の値を入力すると、100%のコードカバレッジを取得できます。

今、私のビジネス状態が<!> quot; ... 3つ以上のアイテムの注文については、送料に割引を適用することを想像してください。<!> quot ;.次に、境界で機能するテストを作成する必要があります。したがって、qtyが2,3および4であるテストを設計します。まだ100%のカバレッジがありますが、さらに重要なことに、ロジックにバグが見つかりました。

それは、コードカバレッジだけに焦点を当てる場合の問題です。せいぜい、開発者がビジネスルールに基づいていくつかの初期テストを作成する状況に陥ると思います。次に、カバレッジ番号を上げるために、新しいテストケースを設計するときにコードを参照します。

マニフェスト型付け (つまり、あなたが言いたいのは) は仕様の一形態であり、単体テストは例しか提供していないため、はるかに弱いです。重要な違いは、仕様はどのような場合でも保持する必要があることを宣言するのに対し、テストは例のみをカバーすることです。テストがすべての境界条件をカバーしているかどうかを確認することはできません。

また、宣言された型のドキュメントとしての価値も忘れがちです。たとえば、Java メソッドが List<String>, そうすると、何が得られるのかがすぐに分かり、ドキュメントやテスト ケース、さらにはメソッド コード自体を読む必要もありません。パラメータについても同様です。型が宣言されていれば、メソッドが何を期待しているのかがわかります。

適切に記述されたコードでは変数の存在範囲が小さくなるはずなので、ローカル変数の型を宣言する価値ははるかに低くなります。ただし、静的型指定は引き続き使用できます。型を宣言する代わりに、コンパイラーに型を推測させます。のような言語 スカラ座 あるいは C# これだけを許可します。

テストのスタイルによっては、仕様に近づくものもあります。 クイックチェック または Scala の亜種です スカラチェック 仕様に基づいてテストを生成し、重要な境界を推測しようとします。

別の言い方をします-静的に型付けされた言語を持っていない場合、何かをするつもりなら better 非常に徹底的な単体テストを行います<!> quot; real <!> quot;そのコードで。

とはいえ、静的型付け(または、明示的な型付け)には、単体テストよりもいくつかの重要な利点があります。より理解しやすいAPIを作成し、<!> quot; skeleton <!> quot;をすばやく表示できます。動的に型付けされた言語でははるかに困難な方法でアプリケーション(つまり、各モジュールまたはコードのセクションを指すエントリ)を作成します。

要約すると、堅実で徹底的な単体テストを考えると、動的に型付けされた言語と静的に型付けされた言語の選択はほとんど好みの1つです。一部の人々はそれを好む。他は他を好む。ジョブに適したツールを使用します。しかし、これは、それらが同一であることを意味するものではありません-静的に型付けされた言語は常に特定の方法でエッジを持ち、動的に型付けされた言語は常に特定の異なる方法でエッジを持ちます。単体テストは、動的に型付けされた言語の欠点を最小限に抑えることに大きく貢献しますが、それらを完全に排除するわけではありません。

いいえ。

ただし、これは最も重要な質問ではありません。最も重要な質問は、「できないことは重要ですか?」

静的型チェックの目的を考慮してください:コードの欠陥(バグ)のクラスを回避します。ただし、これはすべてのコード欠陥のより大きなドメインのコンテキストで比較検討する必要があります。最も重要なのは、狭いスライバーに沿った比較ではなく、コード品質の深さと幅、正しいコードの記述の容易さなどの比較です。静的な型チェックを行わずにコードをより効率的に作成できれば、それだけの価値があります。これは、静的型チェックがキャッチするテストに穴がある場合でも当てはまります。

あなたが非常に徹底していればそれは可能だと思います。しかし、なぜわざわざ?静的型が正しいことを確認するために言語がすでにチェックしている場合、それらをテストすることは意味がありません(無料で入手できるため)。

また、IDEで静的型付き言語を使用している場合、テストのためにコンパイルする前であっても、IDEはエラーと警告を提供します。同じことができる自動化された単体テストアプリケーションがあるかどうかはわかりません。

動的な遅延バインディング言語のすべての利点を考えると、それが単体テストによって提供される値の1つだと思います。あなたはまだ慎重かつ意図的にコーディングする必要がありますが、それはIMHOのあらゆる種類のコーディングの一番の要件です。明確でシンプルなテストを作成できることは、設計と実装の明快さと単純さを証明するのに役立ちます。また、後でコードを見る人に役立つ手がかりを提供します。しかし、型の不一致を検出するためにそれを期待するつもりはありません。しかし、実際には、型チェックが実際に多くの実際のエラーをキャッチすることはわかりません。そもそも明確でシンプルなコーディングスタイルがあれば、実際のコードで発生するエラーの種類ではありません。

javascriptの場合、jsLintでほぼすべての型チェックの問題が見つかると期待しています。主に露出を減らすために別のコーディングスタイルを提案します。

タイプチェックは、システム内のコンポーネントの between コンポーネントの強制に役立ちます。ユニットテスト(名前が示すとおり)は、コンポーネントの内部ロジックを検証します。

単一のコードユニットの場合、ユニットテストにより、静的型チェックが不要になると思います。しかし、複雑なシステムでは、自動テストではシステムのさまざまなコンポーネントが相互作用する可能性のあるすべての方法を検証することはできません。このため、インターフェース(ある意味では、コンポーネント間の一種の<!> quot; contract <!> quot;)の使用は、潜在的なエラーを減らすための便利なツールになります。また、インターフェイスにはコンパイル時の型チェックが必要です。

私は動的言語でのプログラミングを本当に楽しんでいるので、動的型付けをバッシングしているわけではありません。これは最近発生した問題です。残念ながら、大規模で複雑なシステムで動的言語を使用した経験はあまりないので、この問題が現実のものか、単に理論上のものかを他の人から聞いてみたいと思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top