私は「HeadFirstJava」を読み、すべてのパズルとエクササイズを行うことでJavaを学んでいます。この本では、私が書いたコードとクラスをテストするためにTestDriveクラスを書くことを推奨しています。これは非常に簡単なことですが、これを行うと、テストコードを書いているため、コードを完全にテストできないと思います。何を取得したいのかを知っているので、それが意味があるかどうかはわかりませんが、正しく機能していないことを教えてくれる簡単な方法でコードをテストする方法があるかどうか疑問に思いました。ありがとう。
7 に答える
そうです-あなたは何を期待するかを知っており、その知識をカバーするテストケースを書きます。多くの点で、これは正常です。自分が書いたものをテストして、期待どおりに機能することがわかるようにします。
今、あなたはそれを次のステップに進める必要があります:それが機能するシステムを見つけ(すなわち、完全なパズルの他のビットnピースと統合し)、それがあなたの仮定と知識に従ってまだ機能するかどうかを確認します。
それからあなたはあなたのためにテストするために他の誰かにそれを与える必要があります-彼らはあなたが考えもしなかったビットをすぐに見つけるでしょう。
次に、それを実際のユーザーに渡すと、ユーザーはあなたとあなたのテスターが考えもしなかったものを見つけるだけでなく、要件アナリストが考えもしなかったものも見つけます。
これがソフトウェアの動作方法であり、おそらくソフトウェアが完成しなかった理由です。
PS。何よりも重要なテストコードについての1つのこと-一度実行して期待どおりに機能することがわかったら、アプリにさらに何かを追加してから、テストコードを再度実行して、期待どおりに機能することを確認できます。これは回帰テストと呼ばれ、独自の単体テストを作成する唯一の理由だと思います。
および:ディルバートのテストの考え方。
コードとはどういう意味ですか?ここで話しているのはユニットテストですが、特定のメソッドとクラスをテストしています。
何を取得したいかを知っているテストコードを書いているので、コードを完全にテストすることはできないと思います
言い換えれば、あなたはいくつかのコードが契約を履行するかどうかを調査しています。この例を考えてみましょう。
int getInvestvalue( int depositCents, double annualInterestRate, int years) {
}
どのようなテストを考案できますか?優れた一連のテストを考案すれば、このルーチンにある程度の自信を持つことができます。したがって、次の種類の入力を試すことができます。
deposit 100, rate 5.0, years 1 : expected answer 105
deposit 100, rate 0, years 1 : expected answer 100
deposit 100, rate 10, years 0 : expected anwer 100
ほかに何か?マイナスレートはどうですか?
さらに興味深いことに、1,000,000.50年や100,000年のような非常に高い利率はどうでしょうか。結果はどうなるのでしょうか。整数に収まるのでしょうか。このテストを考案することで、インターフェースに挑戦することになります。例外が文書化されていないのはなぜですか。
次に、問題が発生します。これらのテストケースをどのように把握するかです。包括的なセットを構築するための単一のアプローチはないと思いますが、考慮すべき点がいくつかあります。
- エッジ:ゼロ、1、2、多数。私の例では、5%の割合を実行するだけではありません。特に特殊なケースを考慮します。ゼロは特別です、1つは特別です、負は特別です、大きな数は特別です...
- コーナーケース:エッジの組み合わせ。私の例では、それは大きな割合であり、何年もかかります。これらを選ぶことは芸術のようなものであり、実装に関する知識によって助けられます。ここでは、レートと年の間に「乗数」効果があることがわかります。
- ホワイトボックス:実装の知識を使用してコードカバレッジを推進します。入力を調整して、コードを特定のパスに強制的に送ります。たとえば、コードに「負のレートの場合」の条件付きパスがあることがyoiuにわかっている場合、これは負のレートのテストを含めるための手がかりになります。
「テスト駆動開発」の信条の1つは、最初にテストを作成することです(つまり、コードを作成する前に)。明らかに、このテストは最初は失敗します(プログラムがコンパイルされない場合もあります)。テストが失敗しない場合は、テスト自体に問題があることがわかります。テストが失敗すると、テストに合格するまでコードを書き続けることが目的になります。
また、jUnitなどのより一般的な単体テストフレームワークのいくつかでは、何かが機能するか、明示的に機能しないかをテストできます(つまり、特定のタイプの例外がスローされると断言できます)。これは、入力不良やコーナーケースなどをチェックするのに役立ちます。
Stephen Coveyから一線を盗むには、終わりを念頭に置いて開始し、考えられる限り多くのテストを記述します。これは非常に単純なコードでは些細なことのように思えるかもしれませんが、より複雑な問題に進むにつれて、このアイデアは役に立ちます。
このサイトには、コードをテストするためのヘルプリソースがたくさんあります。SoftwareTestingHelp
まず、コードが単体テスト用に記述されていることを確認する必要があります。外部クラスへの依存関係を明示的にする必要があります(可能な場合はコンストラクターが必要とします)。これにより、物事を壊す可能性のあるすべての方法を特定せずに単体テストを作成することはできません。依存関係が多すぎる場合、または各依存関係がどのように使用されるかが明確でない場合は、単一責任の原則に取り組む必要があります。これにより、クラスがより小さく、より単純に、よりモジュール化されます。
依存関係と入力パラメーターに基づいて発生する可能性のある状況を予測できるようにコードを記述したら、予測可能なさまざまな状況から正しい動作を探すテストを作成する必要があります。単体テストで私が見つけた最大の利点の1つは、実際に「もしも...」と考え、それぞれの場合の正しい動作を理解することを余儀なくされたことです。たとえば、特定のエラーの場合に例外をスローするか、null値を返す方が理にかなっているのかどうかを判断する必要があります。
すべての基盤がカバーされたと思ったら、QuickCheckなどのツールでコードをスローして、見逃した可能性のある可能性を特定することもできます。
試乗
いいえ、 JUnitまたはTestNGテストを作成する必要があります。
正しく行われると、テストは仕様になります。それはあなたのコードが何をすべきかを定義します。各テストは、アプリケーションの新しい側面を定義します。したがって、テストは正しく機能する方法を指定するため、正しく機能しないものを探すテストを作成することは決してありません。
単体テストとコンポーネントのコーディングが完了したと思ったら、物事が正しく機能しているという確信を高めるための最も簡単な方法の1つは、探索的テストと呼ばれる手法を使用することです。これは、パーツのスクリプト化されていない探索と考えることができます。あなたが書いたアプリケーションの直感と経験(そして悪意!)に基づいてバグを探します。
ペアプログラミングは、コードからバグを防ぎ、洗い流すためのもう1つの優れた方法です。2つの心は1つよりも優れており、多くの場合、他の誰かがあなたがしなかったことを考えます(逆もまた同様です)。