From 1bbf928b6ac0fcac99779db4c72b0f7390a5b5c9 Mon Sep 17 00:00:00 2001 From: RG756 Date: Sun, 6 Sep 2026 15:14:55 +0900 Subject: [PATCH 1/5] feat: add GitHub Actions CI pipeline and unit tests --- .github/workflows/ci.yml | 29 +++++++++++++++++++ project-d-serverless-api/tests/__init__.py | 0 project-d-serverless-api/tests/test_lambda.py | 22 ++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 project-d-serverless-api/tests/__init__.py create mode 100644 project-d-serverless-api/tests/test_lambda.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5521923 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: CI Pipeline + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + name: Lint & Unit Test + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install dependencies + run: | + pip install pytest boto3 + + - name: Run unit tests + run: | + pytest project-d-serverless-api/tests/ -v \ No newline at end of file diff --git a/project-d-serverless-api/tests/__init__.py b/project-d-serverless-api/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/project-d-serverless-api/tests/test_lambda.py b/project-d-serverless-api/tests/test_lambda.py new file mode 100644 index 0000000..559a1b5 --- /dev/null +++ b/project-d-serverless-api/tests/test_lambda.py @@ -0,0 +1,22 @@ +import json +import sys +import os + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'lambda')) + +import index + +def test_get_items_returns_200(): + event = {"httpMethod": "GET", "pathParameters": None, "body": None} + response = index.lambda_handler(event, {}) + assert response["statusCode"] == 200 + +def test_response_has_cors_header(): + event = {"httpMethod": "GET", "pathParameters": None, "body": None} + response = index.lambda_handler(event, {}) + assert "Access-Control-Allow-Origin" in response["headers"] + +def test_invalid_method_returns_400(): + event = {"httpMethod": "PATCH", "pathParameters": None, "body": None} + response = index.lambda_handler(event, {}) + assert response["statusCode"] == 400 \ No newline at end of file From 6ca990b77a8aa657658ce95183b23ab1ae1ec8e9 Mon Sep 17 00:00:00 2001 From: RG756 Date: Sun, 6 Sep 2026 15:36:22 +0900 Subject: [PATCH 2/5] fix: use mock for boto3 in unit tests --- project-d-serverless-api/tests/test_lambda.py | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/project-d-serverless-api/tests/test_lambda.py b/project-d-serverless-api/tests/test_lambda.py index 559a1b5..4dbfbe1 100644 --- a/project-d-serverless-api/tests/test_lambda.py +++ b/project-d-serverless-api/tests/test_lambda.py @@ -1,22 +1,36 @@ import json import sys import os +from unittest.mock import patch, MagicMock sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'lambda')) -import index +# boto3のDynamoDB接続をモックに差し替え +@patch('boto3.resource') +def test_get_items_returns_200(mock_boto): + mock_table = MagicMock() + mock_table.scan.return_value = {'Items': []} + mock_boto.return_value.Table.return_value = mock_table -def test_get_items_returns_200(): + import index event = {"httpMethod": "GET", "pathParameters": None, "body": None} response = index.lambda_handler(event, {}) assert response["statusCode"] == 200 -def test_response_has_cors_header(): +@patch('boto3.resource') +def test_response_has_cors_header(mock_boto): + mock_table = MagicMock() + mock_table.scan.return_value = {'Items': []} + mock_boto.return_value.Table.return_value = mock_table + + import index event = {"httpMethod": "GET", "pathParameters": None, "body": None} response = index.lambda_handler(event, {}) assert "Access-Control-Allow-Origin" in response["headers"] -def test_invalid_method_returns_400(): +@patch('boto3.resource') +def test_invalid_method_returns_400(mock_boto): + import index event = {"httpMethod": "PATCH", "pathParameters": None, "body": None} response = index.lambda_handler(event, {}) assert response["statusCode"] == 400 \ No newline at end of file From fc0c2061b1f14bb33bd434ee3851512d616d5d6e Mon Sep 17 00:00:00 2001 From: RG756 Date: Sun, 6 Sep 2026 15:57:03 +0900 Subject: [PATCH 3/5] fix: add TABLE_NAME env var for unit tests --- project-d-serverless-api/tests/test_lambda.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/project-d-serverless-api/tests/test_lambda.py b/project-d-serverless-api/tests/test_lambda.py index 4dbfbe1..9abd956 100644 --- a/project-d-serverless-api/tests/test_lambda.py +++ b/project-d-serverless-api/tests/test_lambda.py @@ -3,6 +3,9 @@ import os from unittest.mock import patch, MagicMock +# テスト用環境変数を設定 +os.environ['TABLE_NAME'] = 'test-table' + sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'lambda')) # boto3のDynamoDB接続をモックに差し替え From 8282d6488642f8aff28c45775311f9236a1f5cc8 Mon Sep 17 00:00:00 2001 From: RG756 Date: Sun, 6 Sep 2026 16:18:18 +0900 Subject: [PATCH 4/5] fix: refactor test to use patch.object for table mock --- project-d-serverless-api/tests/test_lambda.py | 46 ++++++++----------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/project-d-serverless-api/tests/test_lambda.py b/project-d-serverless-api/tests/test_lambda.py index 9abd956..e5c5da9 100644 --- a/project-d-serverless-api/tests/test_lambda.py +++ b/project-d-serverless-api/tests/test_lambda.py @@ -3,37 +3,29 @@ import os from unittest.mock import patch, MagicMock -# テスト用環境変数を設定 os.environ['TABLE_NAME'] = 'test-table' +os.environ['AWS_DEFAULT_REGION'] = 'ap-northeast-1' sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'lambda')) -# boto3のDynamoDB接続をモックに差し替え -@patch('boto3.resource') -def test_get_items_returns_200(mock_boto): - mock_table = MagicMock() - mock_table.scan.return_value = {'Items': []} - mock_boto.return_value.Table.return_value = mock_table +import index - import index - event = {"httpMethod": "GET", "pathParameters": None, "body": None} - response = index.lambda_handler(event, {}) - assert response["statusCode"] == 200 +def test_get_items_returns_200(): + with patch.object(index, 'table') as mock_table: + mock_table.scan.return_value = {'Items': []} + event = {"httpMethod": "GET", "pathParameters": None, "body": None} + response = index.lambda_handler(event, {}) + assert response["statusCode"] == 200 -@patch('boto3.resource') -def test_response_has_cors_header(mock_boto): - mock_table = MagicMock() - mock_table.scan.return_value = {'Items': []} - mock_boto.return_value.Table.return_value = mock_table +def test_response_has_cors_header(): + with patch.object(index, 'table') as mock_table: + mock_table.scan.return_value = {'Items': []} + event = {"httpMethod": "GET", "pathParameters": None, "body": None} + response = index.lambda_handler(event, {}) + assert "Access-Control-Allow-Origin" in response["headers"] - import index - event = {"httpMethod": "GET", "pathParameters": None, "body": None} - response = index.lambda_handler(event, {}) - assert "Access-Control-Allow-Origin" in response["headers"] - -@patch('boto3.resource') -def test_invalid_method_returns_400(mock_boto): - import index - event = {"httpMethod": "PATCH", "pathParameters": None, "body": None} - response = index.lambda_handler(event, {}) - assert response["statusCode"] == 400 \ No newline at end of file +def test_invalid_method_returns_400(): + with patch.object(index, 'table') as mock_table: + event = {"httpMethod": "PATCH", "pathParameters": None, "body": None} + response = index.lambda_handler(event, {}) + assert response["statusCode"] == 400 \ No newline at end of file From 1182e0a15f27b90b5a5e141c6c5673bf5fb012e7 Mon Sep 17 00:00:00 2001 From: RG756 Date: Sun, 6 Sep 2026 17:06:44 +0900 Subject: [PATCH 5/5] fix: correct handler function name in tests --- project-d-serverless-api/tests/test_lambda.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/project-d-serverless-api/tests/test_lambda.py b/project-d-serverless-api/tests/test_lambda.py index e5c5da9..d1c0686 100644 --- a/project-d-serverless-api/tests/test_lambda.py +++ b/project-d-serverless-api/tests/test_lambda.py @@ -14,18 +14,18 @@ def test_get_items_returns_200(): with patch.object(index, 'table') as mock_table: mock_table.scan.return_value = {'Items': []} event = {"httpMethod": "GET", "pathParameters": None, "body": None} - response = index.lambda_handler(event, {}) + response = index.handler(event, {}) # ← handler に変更 assert response["statusCode"] == 200 def test_response_has_cors_header(): with patch.object(index, 'table') as mock_table: mock_table.scan.return_value = {'Items': []} event = {"httpMethod": "GET", "pathParameters": None, "body": None} - response = index.lambda_handler(event, {}) + response = index.handler(event, {}) # ← handler に変更 assert "Access-Control-Allow-Origin" in response["headers"] def test_invalid_method_returns_400(): with patch.object(index, 'table') as mock_table: event = {"httpMethod": "PATCH", "pathParameters": None, "body": None} - response = index.lambda_handler(event, {}) + response = index.handler(event, {}) # ← handler に変更 assert response["statusCode"] == 400 \ No newline at end of file