[PHP] LINE Messaging API を使ったチャットボットをテストしてみた

この記事は、NIFTY Advent Calendar 2017の1日目の記事です。

ニフティでエンジニアをしていますkiwiです。
niftyアルバイトというサービスで、LINE Messaging APIを活用したチャットボットを今年リリースしました。

このボットは、特定の文字列やパターンに反応してタスクをこなす「人工無能」と呼ばれるタイプです。意味解釈などは実現できていませんが、それでも現時点できちんと使えるボットになっている(と思います)。

さて、このようなチャットボットを開発する際には、「Aというメッセージが届いたら、Bというメッセージを返す」というテストや動作確認がしたくなります。

実際に正しく受送信できるかどうかは、サーバにデプロイし、LINEアプリからメッセージを送信して確認することになりますが、簡易的にテストできるような仕組みがあっても良いかなと思い、作ってみることにしました。

テスト結果スクショ

作成したもの

line-bot-test-helper
https://github.com/kiwi-26/line-bot-test-helper

中身

  • ユーザーからメッセージが送信されたとき、LINEサーバから送信されるJSONを作成できるWebhookEvent
  • HTTPClientとして動作し、getやpostされたリクエストをサーバに送信せず内部に溜めておくStockHTTPClient

ただし(記事執筆段階では)WebhookEventについては、Webhookイベントのうちテキストメッセージのみ実装されています。

使い方

composer 経由で導入できます。

composer require kiwi-26/line-bot-test-helper --dev
composer update

たとえば、「メッセージを受け取って次の応答を送信する」ような処理(下のコードではMessageHandler)に対して、こんな感じのテストができるようになります。

public function testReply()
{
    $channelToken = env('LINE_CHANNEL_TOKEN', 'sample-token');
    $channelSecret = env('LINE_CHANNEL_SECRET', 'sample-secret');

    // LINEから受け取る(想定の)メッセージを作成
    $source = WebhookEvent\EventSource::user('dummy-user-id');
    $event = new WebhookEvent\TextMessageEvent($source, 'test message', $channelSecret);
    $client = new StockHTTPClient($channelToken);

    // テスト対象。LINEからのWebhookリクエストをパースし、応答の送信まで行っている
    // 引数: RequestBody(string), Signature, HTTPClient
    $handler = new MessageHandler($event->body(), $event->signature(), $client);
    $handler->handle();

    // アサーション
    $this->assertEquals(count($client->queue), 1);
    $this->assertEquals($client->queue[0]->body['messages'][0]['type'], 'text');
    $this->assertEquals($client->queue[0]->body['messages'][0]['text'], 'reply text');
}

サンプルは以下のリポジトリです。
https://github.com/kiwi-26/line-bot-test-helper-sample

メッセージを受け取り、次の応答を送信するMessageHandler では parseEventRequest メソッドを使っていますが、テストでも実際にLINEからメッセージが来たときと同じようにイベントをパースすることが可能です。

StockHTTPClientについては、これを使って初期化したLINEBotで行われるメッセージ送信(replyMessage()など)を、すべてqueueという配列に入るようにしてあります。処理が完了後、意図したメッセージ送信が行えているかの確認が可能です。

今後の主な課題

WebhookEvent

  • テキストメッセージにしか対応していないので、それ以外のイベントに対応する
  • イベントが複数同時に入っているケースを作成できないので、作成できるようにする

StockHTTPClient

  • queueの使い勝手が悪すぎる(assertしづらすぎる)のでどうにかする

以下感想

サンプルではHandlerにpostのbody部やシグネチャ、HTTPClientを渡しており、若干不自然かなという作りになってしまいました。責務が大きすぎる気がなんとなくしています。

また、自分が欲しいと思ってライブラリを作ったつもりだったのですが、特にStockHTTPClientについては(設計・実装にもよりますが)単体テストでまかなえる部分が大きそうです。
WebhookEventについては、受け取ったメッセージによる分岐などのテストに利用できそうだなと思っており、その他のWebhookイベントについても早めに揃えたいなと思っています。

最後に

OSSのライブラリを作ったのは初めてですが、サンプルを作って実際に使ってみないと気づけないことが多く、作る側にとってもサンプルって大事だなと実感しました。GitHubのほうはREADMEも整えられていないので、引き続き改修していきます。

なお、本文中のコードは執筆現在(v0.1.0)のものです。最新の利用方法については、リポジトリのREADMEをご覧ください。

2日目の明日は @hicka04 さんの記事です。お楽しみに!