研究開発部の伊尾木です。
研究開発部では、Alexaのスキルを公開しています(Google Assistantも公開していますよ!)。
今回はAlexaスキルのテストを便利にするKuchimaneというツールを公開したので紹介したいと思います。
E2Eテストが難しい
音声UIの開発はまだまだ新しい分野で知見やツールがそろっているわけではありません。 特に E2E (End To End) テスト、RSpecでいうところの Feature spec に相当するようなテストを行うことがとても困難でした。
AlexaでのE2Eテスト
以下のような一連の会話があったとします。
あなた「クックパッドを開いて」 Alexa「クックパッドへようこそ」 あなた「大根のレシピを教えて」 Alexa「大根ですね。サラダ、ナムル、スープのどのレシピがいいですか」 あなた「スープ」 Alexa「大根のスープですね。レシピを送信しました」
Alexaでは、この一連の会話「クックパッドを開いてから、レシピを送信するまで」をローカルでテストする方法がありません。 (Alexaのデモ環境に都度リクエストを投げればテストはできますが、やっぱりローカルだけでやりたいですよね)
会話の一部だけ、一回のやりとりだけのテストなら可能です。
例えば、「クックパッドを開いて」->「クックパッドへようこそ」 の組み合わせのみテストするといったことは可能です。 が、全部通したテストを書くことはできません。
通常のWebアプリのテストでいえば、 「一回のHTTPリクエストごとのテストは可能だけど、複数HTTPリクエスト、あるいは複数画面にまたがるテストが書けない」 という状況と同じです。
とても不便ですよね。
なぜできないのか
Alexaでは、ユーザの生の発話を、開発者が直接操作することはありません。 一旦、内部的なインテントとよばれるユーザの意図を表している処理に変換します。
例えば「クックパッドを開いて」という発話は、内部的に LaunchRequest というインテントに変換されて処理を実行します。 Webアプリとの対比でいえば、URLからコントローラ・アクション名に変換するルーティング処理と同じような感じです。
このルーティング処理が、Alexa内部に隠蔽されているため、ローカルでテストすることができないのです。 どうしてもローカルで一連の会話をテストしたい場合、ルーティング処理を自前で処理する必要があります。
Kuchimane
私達も当初、インテント単位のテストだけで乗り切ろうとしていましたが、複数インテントが絡む処理はテストできないため、エラーが起きやすい状況でした。
そこで、一連の会話をテストするための Kuchimaneを開発しました!
じゃぁ Kuchimane では、さきほどのルーティング処理をどうしているのかというと、これまた自前で実装しています。
より正確にはsatori-flowというルーティング処理用のライブラリを開発しています。 KuchimaneがAlexaの会話モデル定義を解析し、このsatori-flowに「どんな発話がどのインテントになるのか」を登録します。
というわけで、以下のようなコードが書けるようになります!
const intents = { LaunchRequest, SearchDishIntent, SearchRecipeIntent }; const kuchimaneRunner = Kuchimane.runner(intents, __dirname + '/kuchimane_config.json'); it('searchRecipe', () => {return kuchimaneRunner.talkCheck('クックパッドを開いて', (message) => { expect(message).to.include('クックパッドですね') })() .then(kuchimaneRunner.talkCheck('大根のレシピを教えて', (message) => { expect(message).to.include('大根ですね。サラダ、ナムル、スープのどのレシピがいいですか'); })) .then(kuchimaneRunner.talkCheck('スープ', (message) => { expect(message).to.include('大根のスープですね。レシピを送信しました'); })) } );
最初の行でintents
というオブジェクトを生成していますが、ここのLaunchRequest
、SearchDishIntent
、SearchRecipeIntent
がインテント関数になります。
次にkuchimaneRunner
というインスタンスを、さきほどのintents
とKuchimane用の設定ファイル(Alexaのモデルへのパスなどを書く)から生成しています。
kuchimaneRunner
のtalkCheck
というメソッドがE2Eテスト用のメソッドになります。第1引数がユーザの発話、第2引数がチェック用の関数になります。
talkCheck
メソッドはユーザの発話を受け取ると、それを satori-flow に渡してインテント名に変換してもらいます。
そして、kuchimaneRunner
の生成時にもらったintents
の中から、インテント名にマッチする関数を取り出して実行し、Alexaのレスポンスをチェック用の関数に渡してテストを実行します。
最後にtalkCheck
メソッドは、Promiseを返しますので、then
で会話を繋げていきます。
一連の会話をテストで書けることがわかりますね! 便利ですね!!
おわりに
AlexaのE2Eテストのための Kuchimaneの紹介でした。
バグの多くは機能の組み合わせ部分に潜むと言われますが、実際私達も複数の会話、複数のインテントが絡む部分でよくエラーが起きていました。 Kuchimane以前は、このような部分をテストすることができなかったのですが、Kuchimaneのおかげで複数の会話が絡む部分をテストできるようになり 品質向上に一定の効果があるなと感じています。
ちなみに、まだまだKuchimaneの完成度は高くありません。例えばASK SDK v2 にも対応できていませんし、私達にとって必要な部分を優先的に実装しているため、フォローできていないケースもあります。これらの点については今後拡充していく予定です。
また現状ではGoogle Assistantに対応していませんが、こちらも今後対応する予定です!