Files
012-kaopeilian/backend/tests/test_courses.py
111 998211c483 feat: 初始化考培练系统项目
- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
2026-01-24 19:33:28 +08:00

285 lines
9.2 KiB
Python

"""
课程模块测试
"""
import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.course import Course, CourseStatus, CourseCategory
from app.services.course_service import course_service
class TestCourseAPI:
"""课程API测试类"""
@pytest.mark.asyncio
async def test_create_course_success(self, client: AsyncClient, admin_headers: dict):
"""测试成功创建课程"""
course_data = {
"name": "测试课程",
"description": "这是一个测试课程",
"category": "technology",
"difficulty_level": 3,
"tags": ["Python", "测试"]
}
response = await client.post(
"/api/v1/courses",
json=course_data,
headers=admin_headers
)
assert response.status_code == 201
data = response.json()
assert data["code"] == 200
assert data["message"] == "创建课程成功"
assert data["data"]["name"] == course_data["name"]
assert data["data"]["status"] == "draft"
@pytest.mark.asyncio
async def test_create_course_unauthorized(self, client: AsyncClient, user_headers: dict):
"""测试非管理员创建课程失败"""
course_data = {
"name": "测试课程",
"description": "这是一个测试课程"
}
response = await client.post(
"/api/v1/courses",
json=course_data,
headers=user_headers
)
assert response.status_code == 403
@pytest.mark.asyncio
async def test_get_courses_list(self, client: AsyncClient, user_headers: dict, db_session: AsyncSession):
"""测试获取课程列表"""
# 先创建几个测试课程
courses = [
Course(
name=f"测试课程{i}",
description=f"描述{i}",
category=CourseCategory.TECHNOLOGY if i % 2 == 0 else CourseCategory.BUSINESS,
status=CourseStatus.PUBLISHED if i < 2 else CourseStatus.DRAFT,
is_featured=i == 0
)
for i in range(3)
]
for course in courses:
db_session.add(course)
await db_session.commit()
# 测试获取所有课程
response = await client.get(
"/api/v1/courses",
headers=user_headers
)
assert response.status_code == 200
data = response.json()
assert data["code"] == 200
assert len(data["data"]["items"]) == 3
assert data["data"]["total"] == 3
# 测试筛选已发布课程
response = await client.get(
"/api/v1/courses?status=published",
headers=user_headers
)
assert response.status_code == 200
data = response.json()
assert len(data["data"]["items"]) == 2
# 测试分类筛选
response = await client.get(
"/api/v1/courses?category=technology",
headers=user_headers
)
assert response.status_code == 200
data = response.json()
assert len(data["data"]["items"]) == 2
@pytest.mark.asyncio
async def test_get_course_detail(self, client: AsyncClient, user_headers: dict, db_session: AsyncSession):
"""测试获取课程详情"""
# 创建测试课程
course = Course(
name="测试课程详情",
description="详细描述",
category=CourseCategory.TECHNOLOGY,
status=CourseStatus.PUBLISHED
)
db_session.add(course)
await db_session.commit()
await db_session.refresh(course)
# 获取课程详情
response = await client.get(
f"/api/v1/courses/{course.id}",
headers=user_headers
)
assert response.status_code == 200
data = response.json()
assert data["data"]["id"] == course.id
assert data["data"]["name"] == course.name
@pytest.mark.asyncio
async def test_get_course_not_found(self, client: AsyncClient, user_headers: dict):
"""测试获取不存在的课程"""
response = await client.get(
"/api/v1/courses/99999",
headers=user_headers
)
assert response.status_code == 404
@pytest.mark.asyncio
async def test_update_course(self, client: AsyncClient, admin_headers: dict, db_session: AsyncSession):
"""测试更新课程"""
# 创建测试课程
course = Course(
name="原始课程名",
description="原始描述",
category=CourseCategory.TECHNOLOGY,
status=CourseStatus.DRAFT
)
db_session.add(course)
await db_session.commit()
await db_session.refresh(course)
# 更新课程
update_data = {
"name": "更新后的课程名",
"status": "published"
}
response = await client.put(
f"/api/v1/courses/{course.id}",
json=update_data,
headers=admin_headers
)
assert response.status_code == 200
data = response.json()
assert data["data"]["name"] == update_data["name"]
assert data["data"]["status"] == "published"
assert data["data"]["published_at"] is not None
@pytest.mark.asyncio
async def test_delete_course(self, client: AsyncClient, admin_headers: dict, db_session: AsyncSession):
"""测试删除课程"""
# 创建测试课程
course = Course(
name="待删除课程",
description="这个课程将被删除",
category=CourseCategory.GENERAL,
status=CourseStatus.DRAFT
)
db_session.add(course)
await db_session.commit()
await db_session.refresh(course)
# 删除课程
response = await client.delete(
f"/api/v1/courses/{course.id}",
headers=admin_headers
)
assert response.status_code == 200
data = response.json()
assert data["data"] is True
# 验证软删除
deleted_course = await course_service.get_by_id(db_session, course.id)
assert deleted_course is None # 因为get_by_id会过滤掉软删除的记录
@pytest.mark.asyncio
async def test_delete_published_course_fail(self, client: AsyncClient, admin_headers: dict, db_session: AsyncSession):
"""测试删除已发布课程失败"""
# 创建已发布课程
course = Course(
name="已发布课程",
description="这是已发布的课程",
category=CourseCategory.TECHNOLOGY,
status=CourseStatus.PUBLISHED
)
db_session.add(course)
await db_session.commit()
await db_session.refresh(course)
# 尝试删除
response = await client.delete(
f"/api/v1/courses/{course.id}",
headers=admin_headers
)
assert response.status_code == 400
class TestKnowledgePointAPI:
"""知识点API测试类"""
@pytest.mark.asyncio
async def test_get_knowledge_points(self, client: AsyncClient, user_headers: dict, db_session: AsyncSession):
"""测试获取知识点列表"""
# 创建测试课程
course = Course(
name="测试课程",
description="包含知识点的课程",
category=CourseCategory.TECHNOLOGY,
status=CourseStatus.PUBLISHED
)
db_session.add(course)
await db_session.commit()
await db_session.refresh(course)
# 获取知识点(应该为空)
response = await client.get(
f"/api/v1/courses/{course.id}/knowledge-points",
headers=user_headers
)
assert response.status_code == 200
data = response.json()
assert data["data"] == []
@pytest.mark.asyncio
async def test_create_knowledge_point(self, client: AsyncClient, admin_headers: dict, db_session: AsyncSession):
"""测试创建知识点"""
# 创建测试课程
course = Course(
name="测试课程",
description="用于测试知识点",
category=CourseCategory.TECHNOLOGY,
status=CourseStatus.DRAFT
)
db_session.add(course)
await db_session.commit()
await db_session.refresh(course)
# 创建知识点
point_data = {
"name": "Python基础",
"description": "学习Python基础知识",
"weight": 2.0,
"estimated_hours": 10
}
response = await client.post(
f"/api/v1/courses/{course.id}/knowledge-points",
json=point_data,
headers=admin_headers
)
assert response.status_code == 201
data = response.json()
assert data["data"]["name"] == point_data["name"]
assert data["data"]["course_id"] == course.id
assert data["data"]["level"] == 1
assert data["data"]["parent_id"] is None