testRTCを用いたWebRTCアプリケーションの負荷テスト実行時に気をつけること

# testRTCを用いたWebRTCアプリケーションの負荷テスト実行に気をつけること

この記事は[DMM.com Advent Calendar 2018](https://qiita.com/advent-calendar/2018/dmm) の 19 日目の記事です。

## 何がしたかったのか?

現在、WebRTC SFUを用いた配信基盤システムを構築しており、リリースに向けて実利用を想定したAPIやDBを含めた統合的な負荷試験の実施が必要でした。
自分たちで負荷試験ツールを作成するのか、Saasを用いるのかは開発初期からチームの議論の対象になっていたのですが、今回はリリース期限とメンバーリソース状況を鑑みてSaasの導入に踏み切りました。

## testRTCとは?
[https://testrtc.com](https://testrtc.com/)

WebRTCアプリケーションのインテグレーションテスト、解析、監視を行うことが出来るSoftware as a Serviceです。
Slack,Atlassian,appear.inなどの導入実績もあったことも導入の後押しになりました。

## 良かった点

導入を決めた点や利用中に感じた点を記載していきます。

### テスト実行ホストの管理、保守が不要
テスト実行時にはスクリプトを記述して、実行時オプションを設定して実行するだけです。
自分たちで作成する場合にはサーバースペック、ネットワーク環境などなど様々な考慮が必要であり、**負荷試験というスポットでの導入では大きなリターンを享受出来ました**。

### 並行接続によるP2P通信の試験が可能
![スクリーンショット 2018-12-18 19.19.25.png](https://qiita-image-store.s3.amazonaws.com/0/147300/326285ad-dde0-bfb8-52f3-32865a7ea92e.png)

**実行時のオプションで並行接続数を指定することで最大1000クライアントの接続テストが可能**です。

~~もちろん金額はその分かかります~~

マシンのテストタイミングもある程度コントロール出来ますが、このあたりはE2Eテストの経験値、勘所が必要でした。

### [nightmare](https://github.com/segmentio/nightmare)をベースにしたE2Eスクリプトの記述が容易

[nightmare](https://github.com/segmentio/nightmare)をベースにした実行環境のため、**ローカル環境でもtestRTCが独自で追加しているメソッド以外はテストスクリプトの実行確認が可能**です。
実行回数などには制限があるため、無駄打ちせずにスクリプトの実装を行うことが出来ました。

P2Pを接続して、ビデオの表示を待つような場合はこのようになります。

```javascript
// Join the room
client
    .pause(agentType * sec)
    .rtcProgress('Joining '+roomUrl)
    .url(roomUrl)
    .waitForElementVisible('body', 30*sec)
    .waitForElementVisible('#start', 30*sec)
    .pause(500)
    .click('#start')
    .waitForElementVisible('#username', 30*sec)
    .pause(500)
```

### チャットでのコミュニケーションによる迅速なサポート
英語でのチャットが出来れば、Webページ内でCTOである[Tsahi](https://twitter.com/tsahil)とのやり取りが可能です。
(時々によるんですが、日本時間で15時からのレスポンスが早かったです。所感としてはいつ連絡しても2~3時間内にはレスポンスがもらえました。)

契約時のプラン交渉、実行時の不明な点のサポートも手厚く、契約から試験のオペレーションまでリードタイムなく進めることが出来ました。

## イマイチな点
### 接続元IPを特定出来ないのでアプリケーションをパブリックに公開する必要がある

リリース前のサービスの確認だったため、パブリックアクセスを可能にしなければいけませんでした。
実環境想定で行うには必要な作業ですが、ある程度のIPレンジが絞れると良かったです。

### 複数クライアントで実行した際の勘所が掴みづらい

料金プランはパブリックになっていないので詳細は記載しませんが、一回のテストにそれなりの金額がかかります。
チャットでこちらの叶えたいテストケースや最大接続数を伝えると**testRTC側からカスタムプランを提示してもらうことも可能**だったので、金額で迷っている方は一度相談してみることをおすすめします。

トライアルのプランもあるんですが、並行接続数が最大2クライアントまでのため**複数クライアントでの試験時にしか気づくことが出来ない問題**もいくつかありました。
複数クライアントのテストを失敗すると結構なダメージを受けるので、ここから先は自分が実際に失敗したり、ハマった点を共有していきます。

## テスト実行時にハマった点

### 接続断の試験を行うとWebRTCの解析が出来ないことがある
#### 事象
サービスの都合上、ラグのない切断が求められているため複数クライアントの切断時のラグを検証するケースを実行した際にいくつかのクライアントがステータス失敗で終了していました。

```javascript
client
    .rtcSetTestExpectation("video.in == 0")
    .rtcSetTestExpectation("audio.in == 0")
```

テストスクリプト内にこのようにテストの成否を記述するところで判定がコケていたようです。
スクリーンショットには配信映像が記録されているため、問題なくP2P通信は成功しているはずでした。
<img width="833" alt="スクリーンショット 2018-12-18 20.27.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/147300/af2a9745-929c-e9c2-e1cb-5e1a05ce048e.png">

#### 原因
これはtestRTCが依存しているChromeのWebRTCデバッガである`chrome://webrtc-internals`が切断時にGCされていることが原因でした。

#### 解決策

- 実行時オプションに`#getstats`を設定する

getstatsオプションではWebRTCの[getstats API](https://www.w3.org/TR/webrtc-stats/)から統計情報を取得するオプションで、wertc-internalsには依存しない統計が取得可能です。

失敗した数クライアントではgetstatsの統計情報とスクリーンショットの確認することで検証の担保を行いました。

https://testrtc.com/docs/no-webrtc-data-collected-for-this-session-when-there-is-data/

### デフォルトの接続タイムアウトを超えるとテストが落ちる
#### 事象

前述しましたが、複数クライアントのテスト実行には結構な金額がかかるので、コストを一度の実行に複数のテストケースを盛り込んだときのことでした。

すべての接続でタイムアウトになり、テストが中断してしまいました。
<img width="843" alt="スクリーンショット 2018-12-18 21.04.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/147300/a463c109-7f8b-9933-8b7e-d67201265b0d.png">

#### 原因
testRTC側の設定で、デフォルトのタイムアウトが3分に設定されていました。
オプションでタイムアウトが設定出来るにも関わらず、失念していました。

>The scripts’ default maximum duration is 3 minutes. In order to keep the system’s resources from endless scripts, the tests manager will stop running scripts if reaching the script’s defined timeout. If you wish to run a longer script, please use the timeout run option #timeout:X.
Try setting the timeout to a reasonable value that isn’t too high – if tests fail and get “stuck”, the time used will be counted to your account.
X is the maximum duration (timeout) in minutes for every test iteration.

https://testrtc.com/docs/run-options/

#### 解決策

- テスト実行時間を余剰に見積もり、タイムアウトオプションを設定する
- テストケースは簡潔に保つ

**しっかりリファレンスを読み進めてから実行しましょう。**

## 最後に

前半はtestRTCの導入を検討している方へ、後半はこれから導入予定の方に向けた記事になりました。
自分のハマった点がアンチパターンとなって、皆さんのお役に立てれば幸いです。

最後にもう一度

**しっかりリファレンスを読み進めてから実行しましょう。**