アプリの単体テストを作成していますが、プライベート メソッドをテストするクラスを見つけました。これは、特定のクラスの設計が不十分な結果である可能性がありますが、それを行う必要があります。おそらくQMetaObjectなどを使用して、Qtでプライベートメソッドを呼び出す方法はありますか?
単体テストには QTestLib フレームワークを使用しています。
アプリの単体テストを作成していますが、プライベート メソッドをテストするクラスを見つけました。これは、特定のクラスの設計が不十分な結果である可能性がありますが、それを行う必要があります。おそらくQMetaObjectなどを使用して、Qtでプライベートメソッドを呼び出す方法はありますか?
単体テストには QTestLib フレームワークを使用しています。
適切な(読みにくい)答えは、プライベートメソッドをテストするべきではないということです。これらは実装の詳細;-)
です。
OTOH-テスト中かどうかに応じて、条件付きで保護/プライベートを宣言してから拡張することを考えましたか?私は過去に同じようなピンチから抜け出すためにそれを使用しました。
#ifdef TESTING
// or maybe even public!
#define ACCESS protected
#else
#define ACCESS private
#endif
/* your class here */
class Foo {
ACCESS
int fooeyness;
}
// or better yet, place this in a different file!
#ifdef TESTING
/*
class which extends the tested class which has public accessors
*/
#endif
解決策 1、迅速かつ簡単: テスト クラスをパブリック クラスのフレンドにします。
class Foo {
// ...
private:
friend class FooTest;
};
このようにして、FooTest
クラスは public クラスのすべてのメンバーにアクセスできます。ただし、この方法では、別のテストからプライベート データにアクセスするたびに元のクラスを変更する必要があり、パブリック API でテストに関する情報が漏洩し、クラスの名前付けの競合が発生する可能性があります (/別の/ FooTest クラスの周り?) など。
解決策 2、別名適切に行われた: パブリック クラスにプライベート メソッドを配置しないで、パブリック メソッドでプライベート クラスを作成します。
class Foo {
//
private:
friend class FooPrivate;
FooPrivate *d;
};
FooPrivate
インストールされていないか、include-privates/サブディレクトリなどにとどまっている可能性がある独自のヘッダーで宣言されます-つまり、通常の使用では邪魔になりません。public クラスはこのようにしてクリーンなままです。
class FooPrivate {
public:
// only public stuff in here;
// and especially this:
static FooPrivate *get(Foo *f) { return f->d; }
};
テストには、プライベート ヘッダーとFooPrivate::get(fooObj)
、プライベート クラス インスタンスを取得するための呼び出しが含まれており、それを問題なく使用しています。
「プライベートメンバーは実装の詳細です」という考え方には同意しません。これは、大まかに「コードの一部のみをテストする」と解釈できます。
「ユニットはユニットである」という議論に関連することはできますが、ユニット内であっても、できるだけ多くのコードをテストでカバーしようとしないのはなぜですか? 別名。あなたのユニットに徹底的な直腸検査を与えます。
そして、このイメージを念頭に置いて、他の回答では言及されていない、私が頻繁に使用しているアプローチの1つは、次のことです。
protected
コード内ではなく、テストするメンバーを常に宣言private
します。注: 複雑なインスタンス化パターンに依存するクラスには注意して、それらを正しく構築する必要があります (参照: サブクラス ctor から元のクラスのコンストラクターを呼び出します)。
これを行うためのより便利な方法を見つけました。まず、すべてのプライベート メソッドはプライベート スロットにする必要があります。次に、クラスのインスタンスを作成します。
Foo a;
次に、QMetaObject::invokeMethod を使用して、メソッドが持つ任意のスロット (パブリックまたはプライベート) を呼び出すことができます。したがって、メソッド Test を呼び出したい場合は、次のように実行できます。
QMetaObject::invokeMethod(&a, "Test", Qt::DirectConnection);
また、戻り値を取得して引数を送信することもできます...実際には、すべてここで回答されています: http://doc.qt.nokia.com/stable/qmetaobject.html#invokeMethod
Unit Test は、保護された/プライベートなものではなく、クラスのパブリック インターフェイスをテストする必要があることを読んだことがあります。
あなたのクラスは、外側から正しく振る舞うべきです。実装戦略が変わっても、単体テスト クラスは変わりません。