AWS Lambdaのための関数のローカル開発とテスト

  • 165
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

これは個人の意見/メモであり、所属する組織を代表するものではありません。

サマリ

AWS LambdaのLambda Funcitonをローカルで開発する環境について考えてみた。

なお、このポストの続きをAWS Lambdaの関数をnpmでパッケージ管理に書いています。

大まかな方法

Lambdaでは、例えば以下のような感じで関数を実装してアップロードする。

myFirstLambda.js

var AWS = require("aws-sdk");
var DOC = require("dynamodb-doc");

AWS.config.update({region: "us-west-2"});

exports.handler = function(event, context){
    this.docClient = new DOC.DynamoDB();

    //Do something with DynamoDB

    context.done();
}

で、実行の際にはmyFirstLambda.jsがrequireされてhandlerメソッド(メソッド名はLambdaの設定で変更可能)が呼ばれる、という非常に単純な話(少なくとも外から見る限り)なので、以下のようなドライバスクリプトを書いてあげればOK。

driver.js

//YOUR DATA TO BE PASSED TO LAMBDA FUNCTION.
var event = {
  "Records": [
    {
      "awsRegion": "us-west-2",
      "sequenceNumber": "196800000000000000000374",
      "partitionKey": "2efdb0ea22685b46993e42a67302a001",
      "eventSource": "aws:kinesis",
      "data": "SOME CUSTOM DATA 1"
    }
  ]
};

//BUILD STAB OF context OBJECT.
var context = {
    invokeid: 'invokeid',
    done: function(err,message){
        return;
    }
};


//RUN YOUR HANDLER
var lambda = require("../myFirstLambda");
lambda.handler(event,context);

handlerに渡ってくるeventとcontextというオブジェクトについての補足

  • event: 実際に渡ってくるイベントのデータ(S3のアップデートとかKinesisのレコードとか)。
  • context: Lambda functionの呼び出しコンテキスト。done()というAPIを呼び出すと関数が終了するのだが、コードをちょっと追いきれてないのでとりあえず単純にreturnするだけな感じにstub化。ちなみにcontextオブジェクトのダンプは以下のとおり。done()の中で呼び出されているpostDone()は後で追ってみる。

{
    invokeid: 'STRING', // Lambda functionの呼び出しIDのようなもの(恐らく呼び出しごとにユニーク)
    done: function (err, message) {
        if(doneStatus) {
            return;
        }
        doneStatus = true;
        var error = null;
        if(!(typeof err == "undefined" || (typeof err == "object" && !err))) {
            error = util.format(err);
            console.log(error);
        }
        /*
        * use a timeout to perform the operation once the user gives up control of the event thread
        * This is how HTTP handler works right now
        */
        setTimeout(function() {
            postDone(error, message);
       }, 0);
    }
}

というわけで、こんな感じにドライバスクリプトを準備してあげれば、コード書いてLambdaにアップしてSave & Invokeして・・・みたいなのを繰り返さずにもローカルで開発ができるよという話でした。

テストを書く

ドライバが書けたので、ちょっと手を加えればテストも書ける。

test/basic.js
var assert = require('assert');

//YOUR_EVENT_OBJECT
var data = {};

var context = {
    invokeid: 'invokeid',
    done: function(err,message){
        return;
    }
};

describe('myFirstLambda',function(){
    it('Should have docClient', function(){
        var lambda = require("../myFirstLambda");
        lambda.handler(data,context);
        assert(lambda.docClient);
    });
});

で、package.jsonにこんな感じにテスト実行と依存関係について定義しておけばLambda用の関数をnpmパッケージとして 管理できる・・・気がする。

package.json

{
  "name": "myFirstLambda",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "aws-sdk":"2.*",
    "dynamodb-doc":"1.*"
  },
  "devDependencies": {
    "mocha": "*",
    "eslint": "*",
    "istanbul": "*"
  },
  "scripts" : {
    "test" : "npm -s run-script lint && npm -s run-script unit",
    "unit" : "istanbul `[ $COVERAGE ] && echo 'cover _mocha' || echo 'test mocha'` -- test test/basic",
    "lint" : "eslint ./*.js"
  }
}

あとはscriptに

  • build: 必要なファイルをzipしてpkg/配下に吐き出す
  • deploy: AWS Lamdaにアップロードする

あたりを付け足してあげるとよりパッケージ管理が楽になりそうなんだけど、それはまた今度。

追記

続き書いた: AWS Lambdaの関数をnpmでパッケージ管理