多機器タイミング試験でタイミング競合を捕まえる

「たまに動かない」「客先でだけ起きる」——機器が複数あるシステムの不具合は、どの機器がどの順で返ってきたかで結果が変わることが少なくありません。このチュートリアルは、わざとタイミング競合を仕込んだテスト対象アプリに対して掃引を実行し、失敗する条件を特定 → 何度でも再現 → レポート化するまでを実機なしで通します。

TCP機器 2 台掃引 6 ランアサーション実機不要

このページでできること

  • 複数機器を共有時計で協調させて動かし、機器間の相対タイミングを機械的に振る(掃引する)。
  • アサーションで合否を自動判定し、「どのタイミング条件で壊れるか」を一覧で見る。
  • 失敗したランを同じシード・同じパラメータで何度でも再現する。
  • 失敗条件・根拠・再現手順を含むレポート(HTML/JSON)を出力し、そのまま不具合票に添付する。
画面の各項目・アサーション種別の網羅的な説明は 多機器タイミング試験 を参照してください。このページは手順に絞っています。

登場人物(役割)

実機は要りません。CommSim 本体=2 台の機器役(在席センサ TCP 9710/ゲート制御装置 TCP 9711 で待受け)と、CommSim.Sample=テスト対象アプリ役(入退室ゲート管理アプリ)で完結します。アプリは機器ごとに 1 本ずつ、合計 2 本の接続を張ります(① が在席センサ、② がゲート制御装置)。

CommSim.Sampleテスト対象アプリ役:① と ② の 2 接続
TCP 9710 / 9711機器ごとに 1 本
CommSim 本体機器役:在席センサ/ゲート制御装置

やりとりは 3 通だけです。

  • SENSOR:VACANT在席センサ → アプリ①(フロアは無人)
  • GATE:READYゲート制御装置 → アプリ②(開閉準備ができた)
  • GATE:CLOSE または GATE:OPENアプリ② → ゲート制御装置(開けるかどうかの指示)
接続は 2 本でも、アプリは 1 つです。在室状態のキャッシュ(このあと出てくる不具合の舞台)は ①② で共有されます。現場でも「複数の機器を 1 つのアプリが相手にする」のが普通で、機器ごとの接続をまたいで状態を持つところに競合が生まれます。

仕込んである不具合

テスト対象アプリ(CommSim.Sample 側)には、次の実装ミスを意図的に入れてあります。

ゲートの準備完了を受け取った時点の在室キャッシュを、センサ報告が届いたかどうかを確認せずに使っている。キャッシュの初期値は「在室あり」なので、センサ報告がゲートの通知より遅れて届くと、無人のフロアでゲートを開けてしまう

手で疎通確認する限り、機器はすぐ応答するので必ず正しい順序になり、この不具合は表に出ません。センサ側の応答が遅れる条件(回線が混む・機器の処理が重い・再送が挟まる)でだけ壊れます。掃引はこの「特定のタイミング条件」を機械的に探します。

用意するもの

ファイル/ツール内容
timing-race/timing-race.commsim機器役 2 セッション(在席センサ=TCP サーバ 9710/ゲート制御装置=TCP サーバ 9711)+試験定義 1 件
CommSim.Sampleテスト対象アプリ役。「動かすサンプル」で「多機器タイミング試験(入退室ゲートの競合)」を選ぶと、① が 9710・② が 9711 へ接続するクライアントになり、競合バグ入りの判定ロジックが有効になる

timing-race.commsim は CommSim.Sample の実行フォルダ内 samples/timing-race/ に同梱されています。実機・追加インストールは不要です。

ステップA:テスト対象アプリをつなぐ

  1. CommSim.Sample を起動し、上部の「動かすサンプル」で「多機器タイミング試験(入退室ゲートの競合)」を選ぶ。
  2. 両ペインの表題が「① テスト対象アプリ役(在席センサとの接続)」「② テスト対象アプリ役(ゲート制御装置との接続)」に変わり、①=9710・②=9711、どちらも役割=Client・「自動応答」が ON になっていることを確認する。
  3. ①② の「接続」をそれぞれクリックする。相手(機器役)はまだ起動していないので、状態は「再接続待ち…」のままになります。これで正常です(このあとは試験側が全部動かすので、Sample 側の操作は不要)。
「押してもつながらない」のが、この機能の前提そのものです。多機器タイミング試験はランごとに機器を停止・起動します(ラン間で接続・乱数・状態を持ち越さないため)。アプリから見ると機器の再起動なので、テスト対象アプリ側には再接続が要ります。CommSim.Sample は 250 ms 間隔で自動再接続し、試験が機器を起動した瞬間につながります。

ステップB:試験の中身を確認する

  1. CommSim 本体で samples/timing-race/timing-race.commsim を開く(「ファイル」→「ファイルから開く…」/Ctrl+O)。
  2. メニュー「ツール」→「多機器タイミング試験」を開く。左の一覧の「入退室ゲート:在室判定のタイミング競合」が選ばれている。
  3. タブを順に見る。ここが試験定義の全体像です。
タブこの試験での設定
参加機器在席センサ/ゲート制御装置の 2 台(呼び名は結果一覧・レポートにそのまま出る)
タイムライン0 ms に両機器を起動 → 1500 ms にセンサ報告1700 ms にゲート準備完了
掃引軸在席センサの応答遅延を 0〜400 ms・刻み 80(=6 通り)
アサーションゲート制御装置が「CLOSE」を 1 回以上受信すること(=無人のフロアでゲートを開けない)
多機器タイミング試験ウィンドウのタイムラインタブ:0ms に在席センサ起動、0ms にゲート制御装置起動、1500ms に在席センサのオートメーション実行(在室状態を報告)、1700ms にゲート制御装置のオートメーション実行(ゲート準備完了を通知)
「タイムライン」タブ。センサ報告(1500 ms)とゲート準備完了(1700 ms)の間隔 200 ms が、この不具合の境界になる。センサの遅延が 200 ms を超えると順序が入れ替わる。起動が 0 ms でも送信を 1500 ms から始めるのは、アプリ側の再接続が終わるのを待つため
掃引軸タブ:対象=在席センサ、パラメータ=応答遅延(ms)、値域=0〜400 刻み80、点数6。下部に 6 通り中 6 ランを実行・推定所要時間 14.7 秒と表示
「掃引軸」タブ。値域を決めると組み合わせ数と推定所要時間がその場で出る。刻みを細かくしすぎると爆発するので、まず粗く振って当たりを付けるのが早い。

ステップC:掃引を実行して失敗条件を特定する

  1. 下部の「実行」をクリックする。ランごとに機器の起動 → 送信 → 停止が自動で回り、進捗が更新される。
  2. 20 秒ほどで 6 ラン終わる。「結果」タブに合否が並ぶ。
実行中、CommSim.Sample 側の状態は「接続済み」と「再接続待ち…」を行き来します。ランごとに機器が停止・起動し、そのたびにアプリがつなぎ直しているためで、これも正常な動きです。
結果タブ:遅延0/80/160msのランがPASS、240/320/400msのランがFAILで「無人のフロアでゲートを開けない(CLOSE 指示が届く)」が失敗した条件として表示。下部にPASS 3 FAIL 3
「結果」タブ。遅延 0/80/160 ms は PASS、240/320/400 ms は FAIL。タイムライン上の間隔(200 ms)を境に、はっきり結果が割れている。行を選ぶと下段に判定の根拠(期待: ゲート制御装置 が「CLOSE」(Contains) を 1 回以上 / 実際: 0 回)が出る。試験全体を何度回しても同じ内訳になる。

これが「掃引で失敗条件を特定する」ということです。不具合の再現条件が「センサ応答が 200 ms 以上遅れたとき」だと数字で言い切れるようになり、報告も修正の確認も一気に楽になります。

テスト対象アプリ側(CommSim.Sample)のログを見ると、同じことが通信の中身で確認できます。② に GATE:READY が届いた時点でアプリが GATE:OPEN を返してしまっており、① に SENSOR:VACANT が届くのはその後です(=間に合っていない)。
CommSim.Sample の 2 ペイン:② で GATE:READY を受信した直後に自動応答 GATE:OPEN を送信し、① にはそのあとで SENSOR:VACANT が届いている。ランごとの切断・再接続もログに残っている
テスト対象アプリ役の 2 ペイン。② の GATE:READYGATE:OPEN のあとに ① の SENSOR:VACANT が届いている。センサ報告が間に合わず、初期値のまま判定してしまった瞬間。ラン間の「切断 → 再接続しました。」も残る。

ステップD:再現・ログ確認・レポート出力

  1. 失敗した行(例:遅延 400 ms)を選び、「このランを再現」をクリックする。同じシード・同じパラメータでそのランだけを実行し直す。何度実行しても同じ FAIL になる(=修正後に「直った」と言い切れる)。
  2. このランのログを開く」で、そのランの時間帯の採取ログをログビュワーで確認できる。
  3. レポート出力」で HTML を保存する。同じ場所に同名の JSON も同時出力される(HTML=人が読む用・JSON=CI や集計用)。
ログビュワー:試験中の 12 コネクション(6 ラン × 機器 2 台)と、9710/9711 の待受開始・接続・状態変化を含む 114 行のログ
「このランのログを開く」で開いたログビュワー。試験中の通信は採取ログ(プロジェクト×日の .commsimlog)に記録されるので、ラン 6 回ぶんの接続(機器 2 台 × 6 ラン=12 コネクション)を左のコネクション一覧から追える。ランごとに Tcp Server 0.0.0.0:9710 / :9711 が起動し直しているのも見える。

レポートには、掃引空間の要約・PASS/FAIL 集計・失敗したランのパラメータと判定の根拠・再現手順が含まれます。不具合票にそのまま添付できます。

レポートには受信データそのもの(生バイト列)は含めません。通信内容が要る場合は採取ログ(.commsimlog)をエクスポートして添えてください。

自分のケースへの当てはめ方

問いはいいいえ
不具合が機器の応答順序で変わりそうか?この試験と同じく、片方の機器の応答遅延を掃引して境界を探す単体の応答内容の問題なら、まずオートメーションで再現できないか試す
不具合が再送・欠落でだけ出るか?掃引軸を「送信ロス率」や「N 回送信後に切断」に変える(軸は同じ手順で追加できる)遅延だけで十分
合否を時間で判定したいか?アサーション種別を「タイミング」にし、タイムラインイベントから受信までの上限・下限を指定する「受信あり/なし」「順序」で足りる
機器がアプリへ接続しにくる構成か?(機器がセンタへダイヤルアウトする現場)セッションをクライアントで作る(接続先=アプリの待受ポート)。試験の手順はこのサンプルと同じこのサンプルと同じくセッションをサーバにし、アプリから接続させる
テスト対象アプリは機器の再起動に追随できるか?そのまま試験を回せるまずそこが実装の穴。試験はランごとに機器を停止・起動するため、再接続できないアプリは 1 ラン目しか通らない(これ自体が有用な発見)
試験は通信のタイミングだけを再現します。機器内部の状態遷移までは再現しません(それはシミュレータの領分です)。「この順序・この間隔で通信が起きたとき、テスト対象アプリはどうふるまうか」を確かめる道具として使ってください。

次に読む