4

現在、プレーン C で組み込みプラットフォーム用の低レベル ドライバーをいくつか開発しています。単体テスト フレームワークとして unity+cmock を使用しています。

ただし、低レベルのものを書いているときに、次のパターンに出くわすことがよくあります。

テスト:

void test_mcp2515_read_register(void)
{
    spi_frame_t expected_frame = {{0}};
    expected_frame.tx_length = 2;
    expected_frame.rx_length = 3;
    expected_frame.tx_data[0] = MCP2515_READ_CMD;
    expected_frame.tx_data[1] = TEST_ADDR;
    expected_frame.callback = callback_test;

    spi_transmit_ExpectAndReturn(expected_frame, true);

    mcp2515_read_register(TEST_ADDR, callback_test);
}

実装:

void mcp2515_read_register(uint8_t addr, spi_callback callback)
{
    spi_frame_t frame = {{0}};
    frame.tx_length = 2;
    frame.rx_length = 3;
    frame.tx_data[0] = MCP2515_READ_CMD;
    frame.tx_data[1] = addr;
    frame.callback = callback;

    spi_transmit(frame);
}

ご覧のとおり、テストと実装の間のコードには多くの重複があります。

これは問題ですか?私のテストの書き方は間違っていますか? それとも、この低レベルのテストをまったく書く必要はありませんか?

4

1 に答える 1

2

通常、テスト コードの効率は重要ではありません。何をテストしようとしているかによって異なりますが、コードの重複は設計上の欠陥を示している可能性があります。

あなたの場合、おそらく mcp2515_read_register 関数を 2 つの部分に分割できます。1 つは構造体を作成し、もう 1 つは SPI 送信を処理します。

最適なオブジェクト指向プログラムの設計には、おそらく次のモジュールが含まれます。

  • SPI ドライバーは、実際の通信のみに関係します。
  • CAN コントローラー ドライバーは、コントローラーの詳細のみに関係します。
  • 呼び出し元 (「メイン」など)。
  • CAN コントローラ ドライバのテスト コード: main を置き換えます。

SPI ドライバーは、不透明な型(SPI データと通信のみに関係する構造体)spi_frame_tとして宣言します。SPI ドライバーの外部では、この構造体の内容を認識していないか、または認識する必要はありません。コールバック関数が何をするのかわかりませんが、SPI ドライバに関連するものではないようです。むしろ、SPI ドライバーを呼び出すコードに関連するもののように見えます。

CAN コントローラ ドライバには、SPI ドライバが含まれています。SPI ドライバーから「コンストラクター」を呼び出してフレームを作成し、そのフレームを SPI 通信ルーチンに渡します。その場合、CAN コントローラー ドライバーは SPI 機能と密結合しません。たとえば、SPI にバグが見つかったために CAN コントローラーのコードを書き直しても意味がありません。別のプロジェクトで SPI ドライバーを再利用したい場合は、SPI を使用できるようにするための CAN コントローラーも必要ありません。

テスト ケースは、テストしようとしているプログラムの部分に応じて、呼び出し元 (「メイン」) または CAN コントローラー コードのいずれかを置き換えます。本番コードとまったく同じ機能を使用します。

于 2014-11-20T12:40:11.027 に答える