7

私は、簡略化されたバージョンが次のようなクラスに取り組んでいます:

class Http_server {
public:
    void start(int port)
    {
        start_server();
        std::string content_type = extract_content_type(get_request());
    }

private:
    void start_server()
    {
        ...
    }

    std::string get_request()
    {
        ...
    }

    std::string extract_content_type(const std::string& request) const
    {
        ...
    }
};

のテストケースを書きたいと思いますextract_content_type。問題は、プライベートなので、外部から呼び出すことができないことです。私がテストできる関数は だけですがstart、それは実際にサーバーを起動し ( start_server)、要求を待ちます ( get_request)。

私の見方では、3 つのオプションがあります。

  1. 公開extract_content_typeする
  2. extract_content_typeユーティリティ クラスまたは名前空間に抽出する
  3. それらをオーバーライドするモック オブジェクトを作成して仮想化して作成start_serverするget_request

何かを公開したり、単一のクラスで一度だけ使用されるユーティリティ名前空間に移動したりしたくないので、最も害が少ないのはオプション 3 です。

V8コードベースでこれの例を少なくとも1つ見ました: http://code.google.com/p/v8/source/browse/trunk/test/cctest/test-date.cc

それでも、それが良い考えかどうかはわかりません。virtual次の 2 つの理由から、C++ のデフォルトではありません。

  1. それはパフォーマンス/メモリのオーバーヘッドを誘発します(おそらく私の場合は問題になりません)
  2. すべてのクラスが基本クラスとして使用されることになっているわけではなく、明示的にすることも設計上の決定でした

あなたならどうしますか?役に立たない仮想と一緒に暮らす?それとも、関数をまったくテストしないのですか? 私は TDD には興味がありませんし、なりたいとも思っていませんがextract_content_type、テストに対するような関数を開発する方が簡単です。

4

6 に答える 6

3

別のオプションがあると思います:

単体テスト クラスをテストするクラスのフレンドにする

class Foo {
  public:
#ifdef UNITTEST
    friend class FooTest;
#endif
    ...

  protected:
    ...

  private:
    ...
};

そして、ここに参照があります:http://praveen.kumar.in/2008/01/02/how-to-unit-test-c-private-and-protected-member-functions/

于 2012-09-27T06:04:55.847 に答える
3

答えは、プライベート関数をテストしないことです。理想的には、それらを作成するのではなく、リファクタリングによって作成します (ただし、これが実際には非常に難しいことは認めます)。

パブリック/保護された関数をテストするときに、プライベート関数を暗黙的にテストする必要があります。プライベート関数の機能がそのように完全にアサートされていない場合、それは関数がクラスの外部で目に見える効果を持たないことを行うことを意味します。

これは TDD だけの問題ではありません。プライベート関数は実装の詳細であるため、通常、何も壊さずにリファクタリングできると想定しています。関数のテストがあり、その署名をリファクタリングすることにした場合、それはもはや保持されず、非常に混乱します。

于 2012-09-27T06:05:32.247 に答える
0

私はこれについてビョルンに同意します。クラスが持っているか持っていないプライベート関数は、クラス次第であり、呼び出し元には関係ありません。そのプライベートメソッドを削除した場合はどうなりますか?つまり、コンテンツタイプを抽出するのはそれほど難しくないと判断したため、start関数で直接実行しますか?さて、クラスは正常に機能していますが、テストケースイベントを破ることになります。プライベートはプライベートです!:)

私の提案は、コンテンツ処理用のユーティリティクラスに入れてextract_content_type、そのクラスをテストキャストで使用することです。このクラスをテストするためにサーバーコードが存在する必要はありません。

于 2012-09-27T06:18:56.900 に答える
0

extract_content_type が Http_server クラスに含まれる情報を必要としない場合は、そのクラスに属している必要はありません。本当に、独自のコンテンツ タイプを返すことができるリクエスト自体のクラスが必要なようです。次に、そのリクエスト クラスをテストできます。

于 2012-09-27T05:58:46.037 に答える
0

別のオプションを提案できますが、ご希望かどうかはわかりません。

作成できます

#define TESTING_VIRTUAL

virtualコンパイル時のオプションに応じて、どちらかに展開されるか、何も展開されません。したがって、テストをコンパイルしている場合は、置換するように設定できますvirtual。本番用の場合は、仮想メソッドではありません。

テストモードでコンパイルしているかどうかに応じて、privateまたはにマクロが展開される場合、同じことが可能です。public

于 2012-09-27T06:06:36.670 に答える