2011-12-23 4 views
2

学習目的のために、私は単体テストの分野に分割しました。私はQTを使用して、この問題に関するいくつかのチュートリアルを読んで、そして以下を思い付いてきました:単体テストの目的は何ですか?

class QMyUnitTest : public QObject 
{ 
    Q_OBJECT 
private: 
    bool isPrime(unsigned int ui); 
private Q_SLOTS: 
    void myTest(); 
}; 

bool QMyUnitTest::isPrime(unsigned int n) { 
    typedef std::map<unsigned int, bool> Filter; 
    Filter filter; 

    for(unsigned int ui = 2; ui <= n; ui++) { 
     filter[ui] = true; 
    } 
    unsigned int ui = filter.begin()->first; 
    for(Filter::iterator it = filter.begin(); 
     it != filter.end(); it++) { 
     if(it->second) { 
      for(unsigned int uj = ui * ui; uj <= n; uj += ui) { 
       filter[uj] = false; 
      } 
     } 
     ui++; 
    } 
    return filter[n]; 
} 

void QMyUnitTest::myTest() { 
} 

QTEST_MAIN(QMyUnitTest) 
#include "tst_myunittest.moc" 

私はプライム発見アルゴリズムは非効率的で、特に欠陥がある知っています。それはこの方法を意味します。今私はそれを完全にテストしたいが、次の質問が発生した:

正しくテストするには、何がうまくいかないかについて非常に正確な考えを持っている必要はありませんか?私は最初の1000個の素数を介して実行し、それらがtrueまたは1000素数でない数字を出てくると、彼らはfalseを出てくるかどうかを確認、それは、例えば、アルゴリズムの欠陥を(キャッチしないことがありますかどうかを確認することができます。もちろん、

return filter[n];は明らかに恐ろしいです。n<2の場合はfilter[n]が存在しない可能性があります)。

私の機能の潜在的な問題点を既に知っていなければ、単体テストはどのような用途に使用されますか?

何か間違っていますか?より良いテスト方法がありますか?

+0

あなたの質問の説明に使用するタグ以外のものを含むようにヘッダーを改訂してください。たとえば、「単体テストの目的は何ですか?」 –

+0

アドバイスありがとう、私はそれを変更しました。 – nijansen

答えて

14

単体テストの目的は、実際に書いたコードが実際に行うことを確認することです。

正確で完全なテストを書くためには、コードが何をすべきかを正確に知る必要があります。その後、確認するためにテストを書く:

  • 通常の条件(すなわち、「正常」、「通常」の入力が期待される出力を生成する)
  • 境界条件(かろうじてスペックの範囲内であるすなわち入力)
  • 障害状態を(つまり、入力が無効な場合にコードが正しく失敗することを確認します)。

あなたのisPrimeルーチンの動作を、それが処理できない数値でテストする例は良い例です。あなたの実装を知らなければ、isPrimeルーチンの良いテストケースには0,1,2、そして負の値があります。あなたのアルゴリズムを実装する際には考えられないかもしれないものなので、貴重なテストです。

正常な状態を確認することは、必ずしも最も簡単な部分ではないことに注意してください。この場合と同様に、アルゴリズムが完璧であることを確認するには、数学的分析が必要であり、コードが正しく実装していることを確認する必要があります。数百の既知の値をチェックするだけでは必ずしも十分ではありません(101番目の値で失敗する可能性があります)。

私の機能の潜在的な問題点を既に知っていなければ、単体テストはどのような用途に使用されますか?

あなたはそれを元に戻しました。実装コードを覚えて単体テストを書かないでください。仕様書を念頭に置いて記述してください。コードは仕様に適合しなければならず、テストではできるだけ多くのことを保証する必要があります。 (コードカバレッジツールは、大量のテストが完了したら、境界条件を見つけるのに役立ちます。)

+0

負の数値は '符号なしint'のための良いインスタンスではありません –

+0

+1私が働いていたのとまったく同じ文を書くために:"あなたはそれを逆転しました。 " –

+0

はい、いいえ。署名されていないコンバージョン(またはその逆、または符号付き/符号なし比較)に署名された人は、過去に複数のC(またはC++)開発者を苦しめていました。コンパイラの警告が無視されていると仮定すると、この特定のケースでは '-1'だけが入力され、コンパイルの警告は無視されているとみなして終了します) – Mat

9

ジャストたくはマットが既に記載されているものに追加します。

  • ユニットテストは、あなたと、将来的にあなたのコードに取り組む他の人が事故であなたのコードの動作を変更しないことを保証します。

  • 正しく書かれていれば、単体テストはコードの動作を記録するのに最適な方法です。

+1

+1、非常に重要! –

+1

この重要な点について少し拡張してください:コードは、最初の筆記時には理解されません。単体テストは、自動的にテスト可能な方法で期待されるコード動作に関する知識を書き留める方法です。したがって、これらの単体テストは、あなたが間違っていると思われるものや正しいものを将来のメンテナに送るメッセージです。 – thiton

+1

できるだけ早くテストを書いてください - 理想的には*それらを通過させる実装コードの前に*書くべきです。 –

関連する問題