😉

VSCode×Pynamodb×DynamoDBローカル×pytestでテスト環境できたので備忘

2023/06/26に公開

はじめに


VSCode×Pynamodb×DynamoDBローカル×pytestでテスト環境できたのでビボ(備忘)ります。

動作環境

macOS Monterey 12.6.5

前提

前提条件、ちょっと粗々ですが、この記事を呼んでいる方は大方通っている内容かと思います。
その他、前提条件もしかしたらあるかもしれないです。

  • VSCodeのインストール、Python関連機能インストール
  • aws cliの導入
  • Pynamodbを用いたDynamoDBへのアクセス処理実装

DynamoDBローカル環境構築

デプロイ方法として以下3つあります。

  1. ローカルに.jar実行ファイルをダウンロードする方法
  2. Dockerイメージを使う方法
  3. Apache Maven リポジトリとしてデプロイする方法

今回は1番目の方法で行います。
概ね、デベロッパーガイド通りでできたのですが、わからないこともあったので、私の行った手順を記載します。

  1. デベロッパーガイドのダウンロードリンクから自身の環境にあったファイルをダウンロードします。今回は、リージョン:Asia Pacific (Tokyo) Region、ダウンロードリンク:.zipをダウンロードしました。
  2. ダウンロードしたdynamodb_local_latest.zipを解凍してできるdynamodb_local_latestディレクトリに移動します。中のディレクトリ・ファイルを確認すると、DynamoDBLocal.jarファイルがちゃんとありますね。
$ cd dynamodb_local_latest
$ ls -1
DynamoDBLocal.jar
DynamoDBLocal_lib
LICENSE.txt
README.txt
THIRD-PARTY-LICENSES.txt
shared-local-instance.db
table
  1. DynamoDBLocal.jar を抽出したディレクトリに移動した状態で、次のコマンドを入力します。
$ java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb

以下のように、localhostの8000番ポートでDynamoDBローカルが起動します。

Initializing DynamoDB Local with the following configuration:
Port:	8000
InMemory:	false
DbPath:	null
SharedDb:	true
shouldDelayTransientStatuses:	false
CorsParams:	null

このターミナルは一旦このままで次の手順からは別ターミナルで作業します。

AWS CLIのプロファイル追加

  1. AWS CLIを介してDynamoDBにアクセスする際に使用するAWS CLIのプロファイルを準備します。デベロッパーガイドに記載されている通り、フェイクのアクセスキーIDとシークレットアクセスキーを指定してプロファイルを作成してアプリケーションで認証が有効になるように認証情報を設定する必要があリます。のでプロファイル追加して、追加したプロファイルに切り替えて作業します。
AWS Access Key ID: "fakeMyKeyId"
AWS Secret Access Key: "fakeSecretAccessKey"

プロファイル追加

aws configure --profile dynamodblocal
AWS Access Key ID [None]: fakeMyKeyId
AWS Secret Access Key [None]: fakeSecretAccessKey
Default region name [None]: ap-northeast-1
Default output format [None]: json

プロファイルリスト確認

$ aws configure list-profiles
aws_cxxxxxxxxx
xxxxx_profile
default
sysxxxxxxxxxxx
dynamodblocal

DynaoDBテーブルの作成&アイテム追加

  1. 上記手順で作成したプロファイルに切り替えます。
$ export AWS_PROFILE=dynamodblocal
$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile            dynamodblocal              env    ['AWS_PROFILE', 'AWS_DEFAULT_PROFILE']
access_key     ****************list shared-credentials-file    
secret_key     ****************ials shared-credentials-file    
    region        cat ~/.aws/config      config-file    ~/.aws/config
  1. テーブル追加します。
$ aws dynamodb create-table --endpoint-url http://127.0.0.1:8000 --region ap-northeast-1 --billing-mode PAY_PER_REQUEST \
--table-name 'todo' \
--attribute-definitions '[{ "AttributeName": "userid", "AttributeType": "S"}, { "AttributeName": "todoid", "AttributeType": "S" }]' \
--key-schema '[{ "AttributeName": "userid", "KeyType": "HASH" }, { "AttributeName": "todoid", "KeyType": "RANGE" }]'

できると、ずらっとTableDescriptionが出力されます。

{
    "TableDescription": {
        "AttributeDefinitions": [
            {
                "AttributeName": "userid",
                "AttributeType": "S"
            },
            {
                "AttributeName": "todoid",
                "AttributeType": "S"
            }
        ],
        "TableName": "todo",
        "KeySchema": [
            {
                "AttributeName": "userid",
                "KeyType": "HASH"
            },
            {
                "AttributeName": "todoid",
                "KeyType": "RANGE"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": "2023-06-25T20:51:34.213000+09:00",
        "ProvisionedThroughput": {
            "LastIncreaseDateTime": "1970-01-01T09:00:00+09:00",
            "LastDecreaseDateTime": "1970-01-01T09:00:00+09:00",
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 0,
            "WriteCapacityUnits": 0
        },
        "TableSizeBytes": 0,
        "ItemCount": 0,
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/todo",
        "BillingModeSummary": {
            "BillingMode": "PAY_PER_REQUEST",
            "LastUpdateToPayPerRequestDateTime": "2023-06-25T20:51:34.213000+09:00"
        }
    }
}
  1. テーブル詳細確認
$ aws dynamodb describe-table --table-name todo --endpoint-url http://localhost:8000 --region ap-northeast-1
{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "userid",
                "AttributeType": "S"
            },
            {
                "AttributeName": "todoid",
                "AttributeType": "S"
            }
        ],
        "TableName": "todo",
        "KeySchema": [
            {
                "AttributeName": "userid",
                "KeyType": "HASH"
            },
            {
                "AttributeName": "todoid",
                "KeyType": "RANGE"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": "2023-06-25T20:51:34.213000+09:00",
        "ProvisionedThroughput": {
            "LastIncreaseDateTime": "1970-01-01T09:00:00+09:00",
            "LastDecreaseDateTime": "1970-01-01T09:00:00+09:00",
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 0,
            "WriteCapacityUnits": 0
        },
        "TableSizeBytes": 38,
        "ItemCount": 2,
        "TableArn": "arn:aws:dynamodb:ddblocal:000000000000:table/todo",
        "BillingModeSummary": {
            "BillingMode": "PAY_PER_REQUEST",
            "LastUpdateToPayPerRequestDateTime": "2023-06-25T20:51:34.213000+09:00"
        }
    }
}
  1. アイテムを2つ追加してみます。
$ aws dynamodb put-item --endpoint-url http://localhost:8000 --table-name todo --item '{"userid":{"S":"A01"}, "todoid":{"S":"1234"}}'
$ aws dynamodb put-item --endpoint-url http://localhost:8000 --table-name todo --item '{"userid":{"S":"A02"}, "todoid":{"S":"5678"}}'
  1. スキャンしてみます。
$ aws dynamodb scan --endpoint-url http://localhost:8000 --table-name todo
{
    "Items": [
        {
            "todoid": {
                "S": "1234"
            },
            "userid": {
                "S": "A01"
            }
        },
        {
            "todoid": {
                "S": "5678"
            },
            "userid": {
                "S": "A02"
            }
        }
    ],
    "Count": 2,
    "ScannedCount": 2,
    "ConsumedCapacity": null
}

追加できました。OK!

PynamoDBを用いたDynamoDBへのアクセス処理修正

それでは、PynamoDBを用いたDynamoDBへのアクセス処理修正します。
修正すると言っても、以下のMetaクラスにホスト指定を追記するだけです。
そもそもテスト用なので、本番コードに手が入っちゃだめ。

class ToDoModel(Model):
    class Meta:
        table_name = "todo"
        region = "ap-northeast-1"
        host = "http://localhost:8000" # この行を追加
    userid = UnicodeAttribute(hash_key=True)
    todoid = UnicodeAttribute(range_key=True)

pytestでローカルでユニットテスト実行

VSCodeでpytestを使用する設定等は溢れているので、問題なく使えるようになるかと思います。
VSCodeのターミナルでの、プロファイルの切り替えを忘れずに

以下は、pytestでテスト実行され、呼び出されたクエリ処理になりますが、指定した条件(userid="A01")で無事に上記で追加したアイテムが取れてます。OK!

このあとどうする?

このホスト指定はテスト環境のみ必要なのですが、pytest実行時のみ指定できるようにしなければいけません。どうすればいいんだろう。pytestも使い慣れていないので試行錯誤してみます。

class ToDoModel(Model):
    class Meta:
        table_name = "todo"
        region = "ap-northeast-1"
        host = "http://localhost:8000" # この行を追加
    userid = UnicodeAttribute(hash_key=True)
    todoid = UnicodeAttribute(range_key=True)

まとめ

Pynamodbはだいぶ使いやすいのですが、実例含めた情報が少ないので困りますよね。
やったことはなるべく書き残したいと思っています。

参考

Discussion