🐍

通信ミドルウェア評価用のPythonによる(比較的)汎用なテストドライバ

に公開

主に組み込み向けのミドルウェア、特に通信をするような種類のソフトウェアを開発している場合、開発対象であるミドルウェアを評価するために、以下のような構成を取ることがよくあります。

テストは殆どの場合、以下のように進みます:

  1. PC で動いている Test Driver から、IUT と、IUT の通信相手となるターゲット (Test Device) にコマンドを送信し、所望の機能をトリガします
  2. 各ターゲット (IUT & Test Device) はコマンドによりトリガされた動作に対する応答メッセージを送信します。多くの場合、応答メッセージは、コマンドに対するレスポンスと、コマンドによって惹起されるイベントに分けられます
  3. テストドライバを介して応答メッセージを受信したテストスクリプトは、応答に応じて次のコマンドを行ったり、テスト結果を判定したりします

この場合、Test Driver に期待される機能は結局のところ以下に集約されます:

  1. Send: ターゲット (IUT ないし Test Device) に対してコマンドを送る
  2. Receive: ターゲットから送られれてくるメッセージ (レスポンス、イベント) を受信し、蓄積します。また、以下のような付帯的な動作を実現します:
    1. Wait: 特定の文字列を待ち受ける
    2. Search: 今まで受信したものの中に特定の文字列があるか確認する
  3. Logging: 上の2つの処理のログを残して証拠とする

日本ではよく利用されているターミナルエミュレータ TeraTerm にはマクロの機能があるため、これを使うと接続先が1つで良い場合、上記のすべてがマクロで実現できるため、組み込みソフトウェア開発の現場では TeraTerm をある種の Test Driver として利用することがよくあります。

しかし、図のように複数のターゲットに接続してテストをする必要がある場合 TeraTerm はあまり取り回しがよくありません。

コアの機能は十分少なくても良さそうなので、TeraTerm がやっているようなことを、複数のターゲットに対して実施できるようなものを作ってみました。

tcp_test_driver.py

できたものがこちらです:

https://github.com/aikige/tcp_test_driver.py

やっつけで作ったので以下の割り切りをしています:

  1. ターゲットとの接続に使うのは TCP/IP(ソケット通信、ターゲット側がサーバ)のみ
  2. ターゲットとの間でやり取りするのは文字列のみ
  3. ただし、ターゲットとの接続部分をコネクタというクラスに切り分けているので、これを継承したクラスをユーザー側で作れば上記の制限は回避できる

主な機能

スクリプトが提供する TestTarget クラスのオブジェクトは前述の Test Driver として動作し、以下のような機能を提供します。

機能 メソッド 補足
ターゲットと接続する start 接続が確立すると、すべての送受信メッセージは受信バッファ (とロガー) に保管されます
ターゲットから切断する stop
メッセージを送信する send_str or send
受信バッファの検索 find_str or find_multi_str オブジェクトのプロパティ rx_buffer を自力で検索しても良い
特定の文字列の受信を待つ wait_str
任意のメッセージの受信を待つ wait_any

これらを使うことで、テストスクリプトを Python で実装することが可能です。

詳細は、GitHub プロジェクトの README を参照してください。

簡単な例

一つのターゲットと繋いで、単純にメッセージのやり取りをするだけのサンプルがプロジェクトに含まれています。

https://github.com/aikige/tcp_test_driver.py/blob/main/cui.py

Discussion