web-dev-qa-db-ja.com

構文レベルでサポートされている機能を言語でテストしないのはなぜですか?

単体テスト のソースコードのメリットを宣伝するブログ、記事、ウェブサイトの無限のリストを見つけることができます。 Java、C++、C#、およびその他の型付き言語用のコンパイラーをプログラミングした開発者がユニットテストを使用して作業を検証したことはほぼ保証されています。

では、なぜ人気があるにもかかわらず、これらの言語の構文にテストが欠けているのでしょうか。

マイクロソフトは [〜#〜] linq [〜#〜]C# に導入したので、なぜテストも追加できないのですか?

私はそれらの言語の変更がどうなるかを予測するのではなく、そもそもそれらが存在しない理由を明確にすることを目指しています。

例として:forステートメントの構文なしでforループを記述できることがわかっています。 whileまたはif/gotoステートメントを使用できます。誰かがforステートメントの方が効率的であると判断し、それを言語に導入しました。

テストがプログラミング言語の同じ進化に従っていないのはなぜですか?

37
Reactgular

多くのものと同様に、単体テストは言語レベルではなくライブラリレベルでサポートするのが最善です。特に、C#には多数の単体テストライブラリと、Microsoft.VisualStudio.TestTools.UnitTestingなどの.NET Frameworkにネイティブなものがあります。

各ユニットテストライブラリには、多少異なるテストの考え方と構文があります。すべてが同じであるほど、選択肢は多いより少ないほうが優れています。ユニットテストが言語に組み込まれている場合は、言語デザイナーの選択に縛られるか、またはライブラリを使用して、言語テスト機能を完全に回避します。

  • Nunit-C#の言語機能を最大限に活用する、汎用で慣用的に設計された単体テストフレームワーク。

  • Moq-ラムダ式と式ツリーを最大限に活用して、レコード/再生のメタファーなしでモッキングフレームワーク。

他にも多くの選択肢があります。 Microsoft Fakesのようなライブラリは、インターフェイスや仮想メソッドを使用してクラスを記述する必要のない「シム...」モックを作成できます。

Linqは言語機能ではありません(名前ですが)

Linqはライブラリ機能です。ラムダ式や拡張メソッドなど、C#言語自体に多くの新機能を無料で提供しましたが、Linqの実際の実装は.NET Frameworkにあります。

LinqステートメントをきれいにするためにC#に追加された構文上の砂糖がありますが、その砂糖はlinqを使用するために必須ではありません。

36
Robert Harvey

理由はたくさんあります。 Eric Lippertは、C#に_feature X_が含まれていない理由は予算に含まれていないためだと何度も述べています。言語設計者は、物事を実装するための無限の時間もお金も持っていません。それぞれの新機能には、それに関連するメンテナンスコストがあります。言語をできるだけ小さく保つことは、言語設計者にとって簡単なだけでなく、代替の実装やツール(IDEなど)を書く人にとっても簡単です。さらに、何かが言語の一部ではなく言語の観点から実装されている場合、無料の移植性。単体テストがライブラリとして実装されている場合は、1回記述するだけで、準拠する言語の実装で機能します。

D 単体テストには構文レベルのサポートがあります であることに注意してください。なぜ彼らがそれを採用することにしたのかはわかりませんが、Dが「高水準システムプログラミング言語」であることを意図していることは注目に値します。設計者は、C++が伝統的に使用されてきた種類の安全でない低レベルのコードで実行可能であることを望んでおり、安全でないコードの間違いは信じられないほどコストがかかります-未定義の動作。したがって、いくつかの安全でないコードが機能することを確認するのに役立つあらゆるものに余分な労力を費やすことが、彼らにとって理にかなっていると思います。たとえば、特定の信頼されたモジュールのみが、チェックされていない配列アクセスやポインター演算などの安全でない操作を実行できるように強制できます。

迅速な開発も彼らにとっての優先事項であり、Dコードがスクリプト言語として使用できるように十分に速くコンパイルできるようにするという設計目標を達成するほどでした。ユニットテストを言語に焼き付けることで、コンパイラに追加のフラグを渡すだけでテストを実行できるようになり、それが役立ちます。

ただし、great単体テストライブラリは、いくつかのメソッドを見つけて実行するだけではありません。 Haskellの QuickCheck を例にとると、「すべてのxとy、f (x, y) == f (y, x)」などをテストできます。 QuickCheckはユニットテストgeneratorとしてより適切に記述され、「この入力の場合、この出力を期待している」よりも高いレベルでテストすることができます。 。 QuickCheckとLinqはそれほど違いはありません。どちらもドメイン固有の言語です。では、単体テストのサポートを言語に詰め込むのではなく、DSLを実用的なものにするために必要な機能を追加してみませんか?単体テストだけでなく、結果としてより優れた言語になるでしょう。

21
Doval

テスト、特にテスト駆動型の開発は、直感に反する現象であるためです。

ほとんどすべてのプログラマーは、実際よりも複雑さの管理がはるかに優れていると信じてキャリアを始めます。偉大なプログラマでさえcannot大量の回帰テストを使用しない限り、重大でエラーのない大規模で複雑なプログラムを作成するという事実は、多くの実務家にとって非常にがっかりし、恥ずかしくさえあります。したがって、すでによりよく知っているはずの専門家の間でさえ、定期的なテストに対する一般的な嫌悪感があります。

宗教的なテストが徐々に主流になり、期待されているという事実は、ストレージ容量とコンピューティング能力の爆発的な増加により、これまでよりも大きなシステムが構築されており、非常に大規模なシステムは特に複雑性が崩壊する傾向があるという事実が原因だと思います回帰テストのセーフティネットなしでは管理できません。結果として、特に頑固で惑わされている開発者でさえ、テストが必要で常にテストが必要であることを不本意ながら認めています(これがAA会議での告白のように聞こえる場合、これはかなり意図的です-セーフティネットの必要性は多くの人にとって心理的に認めにくいです個人)。

今日人気のあるほとんどの言語は、この態度転換の前から存在しているため、テストに対する組み込みサポートはほとんどありません。assertはありますが、コントラクトはありません。この傾向が続く場合、将来の言語はライブラリレベルではなく、言語のサポートが増えると確信しています。

13
Kilian Foth

多くの言語がテストをサポートしています。 Cのアサートは、プログラムが失敗する可能性があるテストです。ここでほとんどの言語が停止しますが、Eiffelと最近のAda 2012には、事前不変量(関数への引数が渡す必要があるもの)と事後不変量(関数の出力が渡す必要があるもの)があり、Adaは、ポストインバリアント。 Ada 2012は型の不変条件も提供するため、Adaクラスでメソッドが呼び出されるたびに、返される前に型の不変条件がチェックされます。

これは、優れたテストフレームワークが提供できる完全なテストのタイプではありませんが、言語が最もサポートできる重要なタイプのテストです。

6
prosfilaes

強く型付けされた関数型言語の支持者の中には、これらの言語機能によって単体テストの必要性が減少または排除されると主張する人もいます。

このための2つの、imho、良い例は、F#for Fun and Profit herehere からのものです。

個人的には、単体テストの価値を信じていますが、いくつかの正当な点があります。例えば。不正な状態がコードで表現できない場合、この場合の単体テストを記述する必要がないだけでなく、不可能です。

2
Pete

必要な機能のsomeの追加を逃したのは、それらが単体テストの場合として強調されていなかったためです。

たとえば、C#での単体テストは、主に属性を使用して行われます。 カスタム属性 機能は、NUnitなどのフレームワークが 理論ベースパラメータ化 テストなどと反復および競合できるようにする豊富な拡張メカニズムを提供します。

これにより、2つ目の主要なポイントにたどり着きます。それを言語に焼き付けるための優れたテスト容易性を実現するものについて、私たちは十分に理解していません。テストにおけるイノベーションのペースは他の言語構成要素よりもはるかに速いため、イノベーションの自由を残すには、言語に柔軟なメカニズムを持たせる必要があります。

私はユーザーですが、TDDに熱狂的ではありません。場合によっては、特にデザイン思考を改善するのに非常に役立ちます。大規模なレガシーシステムでは必ずしも有用ではありません-優れたデータと自動化によるより高いレベルのテストは、おそらくより多くの利益を生み出します(強力なコード検査の文化とともに} _。

その他の関連資料:

2
Andy Dent