CircleCI上でdynamodb-localを使ったgo testを実行する
はじめに
本当は、dynamodbを呼び出す箇所をinterface化してgolang/mockとかでmockしてtestするほうが良い思います。
ただ、そうもいかない状況とかもあるのでdynamodb-localでtest用のregionを使ってtestする方法を紹介したいと思います。
例)とあるテーブルにupdateとgetするコード
以下の updateExampleData
と fetchExampleData
をテストしたいという状況。
package main import ( "fmt" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/guregu/dynamo" "github.com/labstack/gommon/log" ) const ( region = "us-west-2" endpoint = "http://127.0.0.1:7777" tableName = "example-table" ) var ( dyn *dynamo.DB ) type exampleDynamoTable struct { ID int `dynamo:"ID,hash"` Count int Message string } func main() { dyn = dynamo.New(session.New(), &aws.Config{ Region: aws.String(region), Endpoint: aws.String(endpoint), }) if err := dyn.CreateTable(tableName, exampleDynamoTable{}).Run(); err != nil { fmt.Println() // 二度目のtable作成は雑にスルーしてる } // tableのデータを更新 id := 1 if err := updateExampleData(id, 100, "test"); err != nil { log.Fatal(err) } // 更新したデータを取得 exampleData, err := fetchExampleData(id) if err != nil { log.Fatal(err) } fmt.Printf("%#v\n", exampleData) } func updateExampleData(id int, count int, message string) error { updater := dyn.Table(tableName).Update("ID", id) updater.Set("Count", count) updater.Set("Message", message) return updater.Run() } func fetchExampleData(id int) (exampleDynamoTable, error) { var e exampleDynamoTable return e, dyn.Table(tableName).Get("ID", id).One(&e) }
testコード
package main import ( "fmt" "testing" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/guregu/dynamo" "github.com/stretchr/testify/assert" ) func TestExampleData(t *testing.T) { as := assert.New(t) dyn = dynamo.New(session.New(), &aws.Config{ Region: aws.String("test-region"), Endpoint: aws.String(endpoint), }) // 前回のデータを雑に削除 if err := dyn.Table(tableName).DeleteTable().Run(); err != nil { fmt.Println() } // テーブルを雑に作成 if err := dyn.CreateTable(tableName, exampleDynamoTable{}).Run(); err != nil { fmt.Println() } testCase := exampleDynamoTable{ ID: 2, Count: 300, Message: "hoge", } as.NoError(updateExampleData(testCase.ID, testCase.Count, testCase.Message)) exampleData, err := fetchExampleData(testCase.ID) as.NoError(err) as.EqualValues(exampleData, testCase) }
ローカル環境でのtest
以下のようなdocker-compose.ymlを用意して、dockerでdynamodb-localを立ち上げてtestを実行すればOKです。 (別にbrewとかで入れても良いです)
version: '2' services: dynamodb: image: tray/dynamodb-local command: tray/dynamodb-local -port 7777 ports: - "7777:7777"
test実行
$ go test . -v === RUN TestExampleData { ExpressionAttributeNames: { #sQ291bnQ: "Count" }, ExpressionAttributeValues: { :v0: { N: "300" }, :v1: { S: "hoge" } }, Key: { ID: { N: "2" } }, ReturnValues: "NONE", TableName: "example-table", UpdateExpression: "SET #sQ291bnQ = :v0, Message = :v1" } --- PASS: TestExampleData (0.21s) PASS ok github.com/kyokomi/example-circleci-dynamodb-go 0.235s
CircleCIの設定
circle.yml
# dynamodb-local # https://discuss.circleci.com/t/how-to-install-dynamodb-local/2018/2 machine: environment: _JAVA_OPTIONS: "-Xms512m -Xmx1024m" java: version: openjdk7 post: - curl -k -L -o dynamodb-local.tgz http://dynamodb-local.s3-website-us-west-2.amazonaws.com/dynamodb_local_latest.tar.gz - tar -xzf dynamodb-local.tgz - java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -port 7777: background: true checkout: pre: - go env - go version
コンソールからは、 AWS permission
だけ設定しておきましょう
awsのライブラリとdynamodb-localが作成するDBの名前とかに使うだけなので、上記のような適当な値でOKです。
実行結果
https://circleci.com/gh/kyokomi/example-circleci-dynamodb-go/2
ライブラリ
ちなみにdynamodbのライブラリはこちらを使ってます。mgoっぽく使えて使いやすくて便利です。
サンプルコード
サンプルコードはすべて、こちらに上げておきましたので宜しければご覧ください。