副作用の多いコードの単体テスト


10

ロボットを実行するためのC ++コードを書き始めていますが、実際にできる場合は、単体テストを組み込む方法がわかりません。私は、自動的にスケジュールされて実行されるロボットの「コマンド」の作成を可能にするライブラリーを提供されています。これらのコマンドを作成するためのメカニズムは、それらが提供するコマンドの基本クラスをサブクラス化し、仮想実装することでvoid Initialize()void Execute()、およびvoid End()方法を。これらの機能は、ロボットに対して何かを行う(モーターの実行、ピストンの伸長など)副作用のためにのみ実行されます。このため、ライブラリ全体をモックしてロボットの状態の前後を確認できるようにするまでは、ユニットテストをコードに添付する場所は実際にはありません。過度に負担にならない、これを単体テストする方法はありますか?

編集する

ライブラリの機能について誤解を招いていたと思います。ライブラリは、ロボットへのインターフェースのほとんどとコマンド/スケジューリングシステムを提供するため、コマンドの基本クラスをモックするほど単純ではないため、ハードウェアへのインターフェース全体をモックする必要があります。残念ながら、そのための時間はありません。


ロボットに実行させるアクションは元に戻せると思いますよね?テストのアクションを元に戻すことはできませんか?
Neil

1
ライブラリが継承の代わりにコンポジションを使用しなかったのは残念です。そうなった場合、コマンドクラスをモックするだけで済むからです。
Robert Harvey

@ニール私はあなたが何を求めているのかよくわかりません。質問を言い換えることができますか?
Will Kunkel

回答:


7

この場合、実際のlibのメソッドに対応するメソッドを使用して、独自のRobotControlインターフェースを導入します。

これを行った後、実際のロボットライブラリに対してこのインターフェイスを実装するRobotControlImplクラスを作成します。

その結果、私が作成するコマンドは基本クラスを拡張せず、代わりに、導入したインターフェースで動作します。

このようにして、RobotControlをモックし、モックを任意のコマンドに渡して、インターフェースで正しいメソッドが呼び出されていることを確認できます。

本番環境では、実装したコマンドにRobotControlの実際の実装を渡します。

これがあなたが考えていて面倒だと思っていたものかどうかわかりませんか?

編集:ああ、そして完了を待つためにコマンドがスリープすることを期待する場合(悪夢ですが、これはあなたが持っているものです)、RobotControlのスリープメソッドを呼び出すコマンドが必要になります。このようにして、テスト中にスリープを無効にして、コマンドがスリープしようとすることを確認できます。


2
+1。インターフェイスが好きではないですか?自分で作る。
Neil

これは、ライブラリ全体をあざけるように言っているようです。コマンドが呼び出す関数のほとんどすべてがライブラリの内部にあります。
Will Kunkel

0

低侵襲な方法でコードをテスト可能にすることは可能だと思います。つまり、ロボットライブラリの作成者が意図したとおりにコマンドを記述できるということです。これは、中間層を使用していない他のユーザーとコードを交換する場合に有利です。

これには、コードの個別の「単体テストビルド」が必要です。

あなたがすることは、1つの中央ヘッダーファイルで、コンパイル時の定義を確認し、これが単体テストビルドかどうかを定義し、そうであれば、基本クラスの名前を再定義し、ロボットライブラリ内の他のクラスをクラスの名前に再定義しますテスト実装の。ロボットlibと同じ仮想関数を定義し、ロボットで呼び出すメソッドのスタブを提供する必要があります。

次に、ロボットライブラリが行うのと同じメソッドを呼び出す独自のテストフレームワークにスローできるコマンドがあります。

これにはある程度のスタブとモックが含まれますが、単体テストの設計ではそれは避けられません。

基本クラス名の変更は、#defineまたはおそらく優先されるtypedefで行うことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.