17
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Livesense - 自Advent Calendar 2017

Day 19

Amazon Echoを使って、Ghost Inspectorのテストを自動化する

Last updated at Posted at 2017-12-18

この記事は Livesense - 自 Advent Calendar 2017 19日目の記事です。

皆様、こんにちは。
インフラストラクチャーグループの @takemotto です。
お酒の場だけは、本当の自分を出せている気がします。普段から明るくいきたいものです。

今回のテーマは、「自」ということで、**「自動化」**について書きたいと思います。
よろしくお付き合いください。

何を自動化したか?

アプリケーションデプロイ後のブラウザ確認は、どのようにやってますでしょうか?
各自がサービスにアクセスして動作確認をやってしまうと、属人化確認漏れが発生しそうです。
私が関わっているDOOR賃貸では、Ghost Inspector(以下、GI)というクラウド型のテストサービスを導入してみました。
GIを導入した理由は以下の通りです。

  • 当初はrails5.1から使用できるSystemTestCaseを使用しようとしたが、rails5.0であったため断念。
  • SasSなので、基本テストコード以外はメンテしなくて良い
  • Chromeの拡張で画面操作で簡単にテストを登録できるため、ディレクターさんでもテスト登録できる
  • APIでもGIのテスト叩けるため、自動化との相性が良さそう
  • (頑張れば)Google Spreadsheetと連携できそう

以下のような構成にしました。

AWS Design (1).png

これにより

  • CodeDeployの「DeploymentSuccess」イベントをフックして、自動でテストを走らせる
  • (別途実装が必要ですが)chatopsでテストを走らせる

といったことが可能となりました。

今回は、上記の仕組みに加えて、Amazon Echo(Alexa)からGIのテストを実行させてみたいと思います。 ※赤枠部分を追加

AWS Design.png

参考にした情報

Alexaスキル開発トレーニングを参考にしました。クラスメソッドさん、いつも大変お世話なっております。
Alexaで出てくるインテントスロットといった用語が丁寧に解説されています。まずはこちらに目を通して頂けると理解しやくなると思います。非常に分かりやすい資料でした。

今回使用した設定は、

をやればカバーできると思います。

事前準備

事前に以下のアカウント作成します。

設定

大まかな処理の流れは、
ユーザ ⇔ Amazon Echo ↔ Alexaサービス ⇔ Lambda ⇔ GI
となっています。
GI、Lambda、Alexaの順で設定していきます。
それではさっそく設定してみましょう。

Ghost Inspectorの設定

Suiteの作成

GIにログイン後、Suite(テストをまとめる単位)を作成します。
今回は、本番環境とステージング環境を分けてテストしたいので、productionstagingというSuiteを作成しました。

テストの作成

作成したSuites毎にテストを登録します。
テストの登録は、Chromeの方であれば こちらの拡張機能 を使用すれば、簡単にテスト登録が可能です。
拡張ツールを有効後、メニューバーにあるスクリーンショット 2017-12-13 16.57.38.pngをクリックし、
「Start Recordig」ボタンをクリックすればテスト登録を開始できます。

例)テスト登録画面
スクリーンショット 2017-12-13 16.56.38.png

Suite IDとAPI Keyを控える

APIの実行に必要なSuite IDAPI Keyを控えます。この後、Lambdaの環境変数として設定します。
Suite IDは、各Suiteページの画面右上Settingsから確認できます。
API Keyは、画面右上のアカウント名を選択すると表示されるAccount Settingsから確認できます。

AWS Lambdaの作成の設定

関数の作成

次に、Lambdaを作成していきます。以下の条件で関数を作成します。

設定項目 補足
設計図 alexa-skill-kit-sdk-factskill nodejsのみです
名前* 任意
ロール 既存のロール
カスタムロールの作成 任意 AWSLambdaFullAccessを付与します。

関数のコード

以下のコードを設定します。
注意点としては、Node.jsが非同期であるため、Callback関数を使用してAPIをたたく必要があるようです。

Stack Overflowのこちらの投稿を参考にしました。

"use strict";

var Alexa = require('alexa-sdk');
var https = require('https');
// var qs = require('qs');

// Lambda関数のメイン処理
exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context); // Alexa SDKのインスタンス生成
    // alexa.appId = process.env.ALEXA_APPLICATION_ID;
    alexa.registerHandlers(handlers); // ハンドラの登録
    alexa.execute();                  // インスタンスの実行
};

var handlers = {
    // インテントに紐付かないリクエスト
    'LaunchRequest': function () {
    this.emit('AMAZON.HelpIntent'); // AMAZON.HelpIntentの呼び出し
    },
    // スキルの使い方を尋ねるインテント
    'AMAZON.HelpIntent': function () {
        this.emit(':tell', 'ゴーストインスペクターを実行します。' +
            'たとえば、ステージングをテストしてといってください。');
    },
    // 対話モデルで定義した、ゴーストインスペクターを実行するインテント
    'Ghostinspector': function () {
        var slot_env = this.event.request.intent.slots.Env.value; // スロットEnvを参照
        
        if(slot_env === 'ステージング'){
            console.log(slot_env);
            var suitesid = process.env.GI_SUITES_STG;
            var starturl = process.env.START_URL_STG;
        } else if (slot_env === 'プロダクション') {
            console.log(slot_env);
            var suitesid = process.env.GI_SUITES_PRD;
            var starturl = process.env.START_URL_PRD;
        } else {
            var error_message = slot_env + 'という環境はありません。';
            this.emit(':tell', error_message); // レスポンスの生成
        }
        var response = '';
        var self = this;
        var gi_api_key = process.env.GI_API_KEY;
        var paths = '/v1/suites/' + suitesid + '/execute/';
        var query = '?apiKey=' + gi_api_key + '&startUrl=' + starturl;
        var options = {
            protocol: 'https:',
            host: 'api.ghostinspector.com',
            path: paths + query,
            method: 'GET',
        };
        getHttps(options, function (response){
            var response = response;
            if (/SUCCESS/.test(response)) {
                self.emit(':tell', 'おめでとうございます。ゴーストインスペクターのテストは成功しました');
            } else {
                self.emit(':tell', 'ゴーストインスペクターのテストは失敗しました。詳細はヒップチャットを確認してください。');
            }
            
        }
    )},
};

function getHttps(options, callback){
    var text = '';
    https.get(options, function(res) {
        console.error("Got response: " + res.statusCode);
        res.on("data", function(chunk) {
        console.error("BODY: " + chunk);
        text = '' + chunk;
        return callback(text);
    });
    }).on('error', function(e) {
        text = 'error' + e.message;
        console.error("Got error: " + e.message);
    });
}

環境変数

さきほど控えたGIのSuite IDAPI keyをLambdaの環境変数に設定します

キー バリュー
START_URL_STG ステージングのURL
START_URL_PRD プロダクションのURL
GI_API_KEY さきほど控えたGIのAPI Key
GI_SUITES_STG さきほど控えたステージング用Suite ID
GI_SUITES_PRD さきほど控えたプロダクション用Suite ID

その他Lambda設定

設定項目
トリガー Alexa Skills Kit
ランタイム Node.js 6.10
タイムアウト 5分

Lambda関数を作成後、画面右上あるARNを控えてください。
Alexaの設定で使用します。

Amazon Developer Servicesの設定

次にAmazon Developer Services の設定を行います。
ログイン後、画面右上のDevelopers ConsoleAlexaタブ→Alexa Skills Kitから任意のスキルを作成します。 指定値以外はデフォルト値です。

スキル情報

設定項目
スキル名 Ghost Inspector
呼び出し名 ゴーストインスペクター

対話モデル

インテントスキーマ

インテントは、音声に対応する処理を定義します。
AMAZON.* というインテントは、デフォルトで用意されているビルトインインテントです。スキルが最低限応えるべきインテントや、定番のインテントがあります。
今回は、別途Ghostinspectorというインテントを用意しました。

{
  "intents": [
    {
      "slots": [
        {
          "name": "Env",
          "type": "ListOfEnv"
        }
      ],
      "intent": "Ghostinspector"
    },
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    },
    {
      "intent": "AMAZON.CancelIntent"
    }
  ]
}

カスタムスロットタイプ

スロットとは、変数のようなものという説明がありました。
今回は、ステージングプロダクションというスロットを定義しました。

設定項目
タイプを入力 ListOfEnv
タイプ ステージング
プロダクション

サンプル発話

サンプルの発話を登録します。
Envには、さきほど定義したスロット(ステージング or プロダクション)が入ります。

Ghostinspector {Env} を テストして
Ghostinspector {Env} を テスト
Ghostinspector {Env} で テスト
Ghostinspector {Env} で テストして
Ghostinspector {Env}

設定

作成したLambdaを呼び出すよう設定します。

設定項目
サービスエンドポイントのタイプ AWS Lambda の ARN (Amazonリソースネーム)
デフォルト さきほど控えたLambdaのArn

テストツールを使って、Alexa経由でGIを実行してみよう

それでは、さっそくテストを実行してみます。
Amazon Developer Servicesで作成したスキルのテストページに移動します。
発話を入力してくださいのところで、プロダクションをテストと入力し、Ghost Inspectorを呼び出すボタンをクリックしましょう。
例)発話テスト画面
スクリーンショット 2017-12-13 18.03.44.png

すると処理が開始され、応答待ち(GIのテスト完了待ち)となります。
例)応答待ち画面
スクリーンショット 2017-12-17 11.21.35.png

テストが成功すると以下のようなレスポンスが返ってきます。
例)発話テストの成功画面
スクリーンショット 2017-12-17 11.22.24.png

GIにログインし、productionSuiteの Suite Run History からテストの実行結果が確認できると思います。
これで準備は整いました。

スキルをベータ版として登録する

Echoからテスト実行するためには、Amazon Developer Servicesから作成したスキルをベータ版として登録する必要があります。
そのためには、作成したスキルの左側の6つのタブすべてが記入されていないと、スキルのベータテストが登録できません。現状だと、公開情報プライバシーとコンプライアンスが残っているので登録していきます。

公開情報

設定項目 補足
カテゴリー Productivity
サブカテゴリー Organizers & Assistants
テストの手順 任意
国と地域を選択する: Japna 日本だけに配信としました。
スキルの簡単な説明 任意
スキルの詳細な説明 任意
サンプルフレーズ アレクサ、ゴーストインスペクターでプロダクションをテストして
アレクサ、ゴーストインスペクターでプロダクションをテスト
キーワード ゴーストインスペクター
画像 任意 小、大アイコンを指定されたサイズで両方登録しないといけません

プライバシーとコンプライアンス

設定項目 補足
このスキルを使って何かを購入をしたり、実際にお金を支払うことができますか? いいえ
このスキルはユーザーの個人情報を収集しますか? いいえ
このスキルは13歳未満の子供を対象にしていますか? いいえ
輸出コンプライアンス ✓する
このスキルは広告を含みますか? いいえ

すべての登録が終わるとSkills Beta Testingで登録が可能となります
以下のように招待したいAmazonアカウントを入れてテスターを追加し、テストを開始ボタンをクリックするとメールが飛んできます。

例)Skills Beta Testing画面
Skill Beta Testing.png

スマホの場合、送られた来たメールのリンクにアクセスすると、インストールしているAmazon Alexaアプリが起動します。
スキルを有効にするかどうか聞いてきるので有効にします。

例) スキルの有効化
unnamed.jpg

ようやく準備整いました。

Amazon Echoから実行してみよう

Amazon Echoに「アレクサ、ゴーストインスペクターでプロダクションをテストして」と話しかけてみてください。がんばってくれるでしょう。

まとめ

  • ある程度予想はしてましたが、chatopsで十分だと思います。

最後に

明日は、 @hotatesan さんです。お楽しみに!

17
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?