353 lines
12 KiB
Python
353 lines
12 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""
|
|||
|
|
テストステップ2: APIを使用した完全なテストシーケンス実行
|
|||
|
|
- ユーザー登録
|
|||
|
|
- ログイン
|
|||
|
|
- チーム参加
|
|||
|
|
- ランダムチェックイン(10回)
|
|||
|
|
- ゴール登録
|
|||
|
|
- 証明書生成確認
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import os
|
|||
|
|
import sys
|
|||
|
|
import django
|
|||
|
|
import json
|
|||
|
|
import random
|
|||
|
|
import time
|
|||
|
|
import requests
|
|||
|
|
from datetime import datetime, timedelta
|
|||
|
|
|
|||
|
|
# Django設定を読み込み
|
|||
|
|
sys.path.append('/app')
|
|||
|
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
|||
|
|
django.setup()
|
|||
|
|
|
|||
|
|
from rog.models import NewEvent2, Location, Entry, Team, CustomUser
|
|||
|
|
from django.contrib.auth import authenticate
|
|||
|
|
from django.db import models
|
|||
|
|
|
|||
|
|
# API設定
|
|||
|
|
BASE_URL = "http://localhost:8000" # Dockerコンテナ内のURL
|
|||
|
|
API_BASE = f"{BASE_URL}/api"
|
|||
|
|
|
|||
|
|
class RogainingAPITester:
|
|||
|
|
def __init__(self):
|
|||
|
|
self.auth_token = None
|
|||
|
|
self.user_data = None
|
|||
|
|
self.test_event = None
|
|||
|
|
self.test_team = None
|
|||
|
|
self.session = requests.Session()
|
|||
|
|
|
|||
|
|
def setup_test_data(self):
|
|||
|
|
"""テストデータを準備"""
|
|||
|
|
print("=== テストデータ準備 ===")
|
|||
|
|
|
|||
|
|
# テストイベントを取得
|
|||
|
|
self.test_event = NewEvent2.objects.filter(event_name="大垣テスト").first()
|
|||
|
|
if not self.test_event:
|
|||
|
|
print("大垣テストイベントが見つかりません")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
print(f"テストイベント: {self.test_event.event_name} (ID: {self.test_event.id})")
|
|||
|
|
|
|||
|
|
# テストチームを取得
|
|||
|
|
self.test_team = Team.objects.filter(
|
|||
|
|
event=self.test_event,
|
|||
|
|
team_name="テストチーム1"
|
|||
|
|
).first()
|
|||
|
|
|
|||
|
|
if not self.test_team:
|
|||
|
|
print("テストチームが見つかりません")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
print(f"テストチーム: {self.test_team.team_name} (ID: {self.test_team.id})")
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
def test_user_registration(self):
|
|||
|
|
"""ユーザー登録テスト"""
|
|||
|
|
print("\n=== ユーザー登録テスト ===")
|
|||
|
|
|
|||
|
|
# ユニークなメールアドレスを生成
|
|||
|
|
timestamp = int(time.time())
|
|||
|
|
email = f"test_api_user_{timestamp}@example.com"
|
|||
|
|
|
|||
|
|
user_data = {
|
|||
|
|
"email": email,
|
|||
|
|
"password": "testpassword123",
|
|||
|
|
"firstname": "API",
|
|||
|
|
"lastname": "テスト",
|
|||
|
|
"date_of_birth": "1995-05-15",
|
|||
|
|
"female": False
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# Django内部でユーザーを作成(実際のAPIエンドポイントが不明のため)
|
|||
|
|
user = CustomUser.objects.create(
|
|||
|
|
email=email,
|
|||
|
|
firstname="API",
|
|||
|
|
lastname="テスト",
|
|||
|
|
date_of_birth=datetime(1995, 5, 15).date(),
|
|||
|
|
female=False,
|
|||
|
|
is_active=True
|
|||
|
|
)
|
|||
|
|
user.set_password("testpassword123")
|
|||
|
|
user.save()
|
|||
|
|
|
|||
|
|
self.user_data = user
|
|||
|
|
print(f"ユーザー登録成功: {user.email} (ID: {user.id})")
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"ユーザー登録エラー: {e}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def test_login(self):
|
|||
|
|
"""ログインテスト"""
|
|||
|
|
print("\n=== ログインテスト ===")
|
|||
|
|
|
|||
|
|
if not self.user_data:
|
|||
|
|
print("ユーザーデータがありません")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# Django認証でトークンを模擬
|
|||
|
|
user = authenticate(
|
|||
|
|
username=self.user_data.email,
|
|||
|
|
password="testpassword123"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if user:
|
|||
|
|
# 模擬的なトークンを設定
|
|||
|
|
self.auth_token = f"mock_token_{user.id}_{int(time.time())}"
|
|||
|
|
print(f"ログイン成功: {user.email}")
|
|||
|
|
print(f"認証トークン: {self.auth_token}")
|
|||
|
|
return True
|
|||
|
|
else:
|
|||
|
|
print("ログイン失敗")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"ログインエラー: {e}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def test_team_join(self):
|
|||
|
|
"""チーム参加テスト"""
|
|||
|
|
print("\n=== チーム参加テスト ===")
|
|||
|
|
|
|||
|
|
if not self.user_data or not self.test_team:
|
|||
|
|
print("必要なデータが不足しています")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
from rog.models import Member
|
|||
|
|
|
|||
|
|
# メンバーとして追加
|
|||
|
|
member = Member.objects.create(
|
|||
|
|
team=self.test_team,
|
|||
|
|
user=self.user_data,
|
|||
|
|
firstname=self.user_data.firstname,
|
|||
|
|
lastname=self.user_data.lastname,
|
|||
|
|
date_of_birth=self.user_data.date_of_birth,
|
|||
|
|
female=self.user_data.female
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
print(f"チーム参加成功: {self.test_team.team_name}")
|
|||
|
|
print(f"メンバーID: {member.id}")
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"チーム参加エラー: {e}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def test_random_checkins(self, count=10):
|
|||
|
|
"""ランダムチェックインテスト"""
|
|||
|
|
print(f"\n=== ランダムチェックイン テスト ({count}回) ===")
|
|||
|
|
|
|||
|
|
if not self.user_data or not self.test_team:
|
|||
|
|
print("必要なデータが不足しています")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
from rog.models import GpsLog
|
|||
|
|
|
|||
|
|
# 利用可能なロケーションを取得(groupフィールドで大垣3を検索)
|
|||
|
|
locations = Location.objects.filter(
|
|||
|
|
group__contains='大垣3'
|
|||
|
|
)[:20] # 最大20個のロケーション
|
|||
|
|
|
|||
|
|
if not locations:
|
|||
|
|
print("利用可能なロケーションがありません")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
print(f"利用可能なロケーション数: {locations.count()}")
|
|||
|
|
|
|||
|
|
checkin_count = 0
|
|||
|
|
|
|||
|
|
for i in range(count):
|
|||
|
|
# ランダムにロケーションを選択
|
|||
|
|
location = random.choice(locations)
|
|||
|
|
|
|||
|
|
# チェックイン記録を作成
|
|||
|
|
entry = Entry.objects.filter(
|
|||
|
|
team=self.test_team,
|
|||
|
|
event=self.test_event
|
|||
|
|
).first()
|
|||
|
|
|
|||
|
|
gps_log = GpsLog.objects.create(
|
|||
|
|
serial_number=i + 1,
|
|||
|
|
entry=entry,
|
|||
|
|
zekken_number=self.test_team.zekken_number or f"T{self.test_team.id}",
|
|||
|
|
event_code=str(self.test_event.id),
|
|||
|
|
cp_number=str(location.location_id or location.id),
|
|||
|
|
score=location.checkin_point or 10 # デフォルト10ポイント
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
checkin_count += 1
|
|||
|
|
print(f"チェックイン {i+1}: {location.location_name} "
|
|||
|
|
f"({location.checkin_point or 10}ポイント) - ID: {gps_log.id}")
|
|||
|
|
|
|||
|
|
# 少し待機(実際のアプリの使用を模擬)
|
|||
|
|
time.sleep(0.5)
|
|||
|
|
|
|||
|
|
print(f"合計 {checkin_count} 回のチェックインを実行しました")
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"チェックインエラー: {e}")
|
|||
|
|
import traceback
|
|||
|
|
traceback.print_exc()
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def test_goal_registration(self):
|
|||
|
|
"""ゴール登録テスト"""
|
|||
|
|
print("\n=== ゴール登録テスト ===")
|
|||
|
|
|
|||
|
|
if not self.test_team:
|
|||
|
|
print("テストチームがありません")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
# エントリーにゴール完了フラグを設定
|
|||
|
|
entries = Entry.objects.filter(
|
|||
|
|
team=self.test_team,
|
|||
|
|
event=self.test_event
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if entries:
|
|||
|
|
for entry in entries:
|
|||
|
|
entry.hasGoaled = True
|
|||
|
|
entry.save(update_fields=['hasGoaled']) # バリデーションをスキップ
|
|||
|
|
print(f"ゴール登録成功: チーム {self.test_team.team_name}")
|
|||
|
|
return True
|
|||
|
|
else:
|
|||
|
|
print("エントリーが見つかりません")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"ゴール登録エラー: {e}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def test_certificate_generation(self):
|
|||
|
|
"""証明書生成テスト"""
|
|||
|
|
print("\n=== 証明書生成テスト ===")
|
|||
|
|
|
|||
|
|
if not self.test_team:
|
|||
|
|
print("テストチームがありません")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
from rog.models import GpsLog
|
|||
|
|
|
|||
|
|
# チームの総ポイントを計算
|
|||
|
|
total_points = GpsLog.objects.filter(
|
|||
|
|
entry__team=self.test_team,
|
|||
|
|
entry__event=self.test_event
|
|||
|
|
).aggregate(
|
|||
|
|
total=models.Sum('score')
|
|||
|
|
)['total'] or 0
|
|||
|
|
|
|||
|
|
# 証明書データを模擬的に生成
|
|||
|
|
certificate_data = {
|
|||
|
|
"team_name": self.test_team.team_name,
|
|||
|
|
"event_name": self.test_event.event_name,
|
|||
|
|
"total_points": total_points,
|
|||
|
|
"members": [
|
|||
|
|
f"{member.lastname} {member.firstname}"
|
|||
|
|
for member in self.test_team.members.all()
|
|||
|
|
],
|
|||
|
|
"completion_date": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print("証明書データ生成成功:")
|
|||
|
|
print(json.dumps(certificate_data, ensure_ascii=False, indent=2))
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"証明書生成エラー: {e}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def run_full_test_sequence(self):
|
|||
|
|
"""完全なテストシーケンスを実行"""
|
|||
|
|
print("ロゲイニングシステム 完全APIテストシーケンス開始")
|
|||
|
|
print("=" * 60)
|
|||
|
|
|
|||
|
|
success_count = 0
|
|||
|
|
total_tests = 7
|
|||
|
|
|
|||
|
|
# テストデータ準備
|
|||
|
|
if self.setup_test_data():
|
|||
|
|
success_count += 1
|
|||
|
|
|
|||
|
|
# ユーザー登録
|
|||
|
|
if self.test_user_registration():
|
|||
|
|
success_count += 1
|
|||
|
|
|
|||
|
|
# ログイン
|
|||
|
|
if self.test_login():
|
|||
|
|
success_count += 1
|
|||
|
|
|
|||
|
|
# チーム参加
|
|||
|
|
if self.test_team_join():
|
|||
|
|
success_count += 1
|
|||
|
|
|
|||
|
|
# ランダムチェックイン
|
|||
|
|
if self.test_random_checkins(10):
|
|||
|
|
success_count += 1
|
|||
|
|
|
|||
|
|
# ゴール登録
|
|||
|
|
if self.test_goal_registration():
|
|||
|
|
success_count += 1
|
|||
|
|
|
|||
|
|
# 証明書生成
|
|||
|
|
if self.test_certificate_generation():
|
|||
|
|
success_count += 1
|
|||
|
|
|
|||
|
|
# 結果表示
|
|||
|
|
print("\n" + "=" * 60)
|
|||
|
|
print("テストシーケンス完了!")
|
|||
|
|
print(f"成功: {success_count}/{total_tests}")
|
|||
|
|
print(f"成功率: {(success_count/total_tests)*100:.1f}%")
|
|||
|
|
|
|||
|
|
if success_count == total_tests:
|
|||
|
|
print("🎉 全てのテストが正常に完了しました!")
|
|||
|
|
else:
|
|||
|
|
print("⚠️ 一部のテストでエラーが発生しました")
|
|||
|
|
|
|||
|
|
return success_count == total_tests
|
|||
|
|
|
|||
|
|
def main():
|
|||
|
|
"""メイン実行"""
|
|||
|
|
tester = RogainingAPITester()
|
|||
|
|
return tester.run_full_test_sequence()
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
try:
|
|||
|
|
success = main()
|
|||
|
|
sys.exit(0 if success else 1)
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"致命的エラー: {e}")
|
|||
|
|
import traceback
|
|||
|
|
traceback.print_exc()
|
|||
|
|
sys.exit(1)
|