- ### 개요: MSA 기반으로 각 기능을 수행하는 150 개의 람다를 테스트
* __DB에 저장된 값 까지 참조하여 테스트를 실행하는 코드가 있어서 각 람다마다 독립적인 DynamoDB가 필요했습니다.__
사용한 도커 이미지 주소: https://hub.docker.com/r/amazon/dynamodb-local
로컬에서 __"무료"__ 로 사용할 수 있는 DynamoDB 입니다.
## 소스코드
test-all-functions.yml
```
name: Test All functions
on:
pull_request:
branches:
- staging
- main
jobs:
lambda-function-test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
python-version: ["3.7"]
steps:
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.DEVELOP_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.DEVELOP_AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: |
npm install
- name: npm test
run: |
sudo timedatectl set-timezone Asia/Tokyo
date
python test.py
```
test.py
```
import multiprocessing
import os
import time
LOG_DIR = "log/test"
MAX_RETRY_CNT = 5
def test_process(lambda_func, region, failed_list):
global LOG_DIR
print("================================ {} Start! ===================================".format(lambda_func))
cmd = """cd functions/{lambda_func} ;
node ../../node_modules/cross-env/src/bin/cross-env.js \
endpoint=http://localhost:8000 region={region} \
NODE_PATH=../../node_modules:../../layers \
node ../../node_modules/jest/bin/jest.js > ../../{LOG_DIR}/{lambda_func}.log 2>&1
""".format(lambda_func=lambda_func, region=region, LOG_DIR=LOG_DIR)
exit_code = os.system(cmd)
if exit_code != 0:
failed_list.append(lambda_func)
cmd = """
grep 'Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout' \
{LOG_DIR}/{lambda_func}.log
""".format(lambda_func=lambda_func, region=region, LOG_DIR=LOG_DIR)
exit_code = os.system(cmd)
if exit_code == 0:
retry_test_process(lambda_func, region, failed_list)
else:
cmd = """
rm {LOG_DIR}/{lambda_func}.log
""".format(lambda_func=lambda_func, LOG_DIR=LOG_DIR)
os.system(cmd)
print("================================ {} Done! ===================================".format(lambda_func))
def retry_test_process (lambda_func, region, failed_list):
global LOG_DIR
global MAX_RETRY_CNT
for i in range(MAX_RETRY_CNT):
time.sleep(1)
cmd = """cd functions/{lambda_func} ;
node ../../node_modules/cross-env/src/bin/cross-env.js \
endpoint=http://localhost:8000 region={region} \
NODE_PATH=../../node_modules:../../layers \
node ../../node_modules/jest/bin/jest.js > ../../{LOG_DIR}/{lambda_func}.log 2>&1
""".format(lambda_func=lambda_func, region=region, LOG_DIR=LOG_DIR)
exit_code = os.system(cmd)
if exit_code == 0:
cmd = """
rm {LOG_DIR}/{lambda_func}.log
""".format(lambda_func=lambda_func, LOG_DIR=LOG_DIR)
os.system(cmd)
failed_list.remove(lambda_func)
break
else:
cmd = """
grep 'Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout' \
{LOG_DIR}/{lambda_func}.log
""".format(lambda_func=lambda_func, region=region, LOG_DIR=LOG_DIR)
exit_code = os.system(cmd)
if exit_code != 0:
break
if __name__ == '__main__':
cmd = """
if [ ! -d {LOG_DIR} ]; then mkdir -p {LOG_DIR}; fi ;
if [ \"`docker ps -q -f 'name=dynamodb'`\" != \"\" ]; then docker stop `docker ps -aq -f 'name=dynamodb'`; fi ;
if [ \"`docker ps -aq -f 'name=dynamodb'`\" != \"\" ]; then docker rm `docker ps -aq -f 'name=dynamodb'`; fi ;
docker run --cpus 2 -m 7000M --name dynamodb -d -p 8000:8000 amazon/dynamodb-local ;
""".format(LOG_DIR=LOG_DIR)
os.system(cmd)
test_list = next(os.walk("./functions"), (None, None, []))[1]
failed_list = multiprocessing.Manager().list([])
jobs = []
regions = ["us-east-1", "us-east-2", "us-west-1",
"us-west-2", "ap-east-1", "ap-northeast-3",
"ap-northeast-2", "ap-northeast-1", "ap-southeast-1", "ap-southeast-2"]
for i in range(len(test_list)):
p = multiprocessing.Process(target=test_process, args=(test_list[i], regions[i%len(regions)], failed_list))
jobs.append(p)
p.start()
if (i+1) == len(test_list) or ((i+1)%len(regions)) == 0:
# wait for all processing jobs to finish
for job in jobs:
job.join()
jobs = []
cmd = """
if [ \"`docker ps -q -f 'name=dynamodb'`\" != \"\" ]; then docker stop `docker ps -aq -f 'name=dynamodb'`; fi ;
if [ \"`docker ps -aq -f 'name=dynamodb'`\" != \"\" ]; then docker rm `docker ps -aq -f 'name=dynamodb'`; fi
"""
os.system(cmd)
print("Test Done!")
error_flag = False
for i in range(len(failed_list)):
error_flag = True
print(failed_list[i])
if error_flag:
raise Exception("Error in test processing.")
```