test: add end to end coverage
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy import select
|
||||
|
||||
from wisegrade.db import get_db
|
||||
from wisegrade.main import app
|
||||
from wisegrade.models import CourseVersion, CriterionScore, Project, RubricVersion, Student
|
||||
from wisegrade.scoring import run_batch
|
||||
|
||||
|
||||
def client_for(session_factory):
|
||||
def override_db():
|
||||
with session_factory() as db:
|
||||
yield db
|
||||
app.dependency_overrides[get_db] = override_db
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
def test_course_and_rubric_versions_are_immutable(session_factory):
|
||||
client = client_for(session_factory)
|
||||
try:
|
||||
new = client.post("/api/courses/1/versions", json={"title": "新学期规则", "source_version_id": 1})
|
||||
assert new.status_code == 200
|
||||
version = new.json()
|
||||
version["objectives"][0]["name"] = "修订后的目标"
|
||||
edited = client.put(f"/api/course-versions/{version['id']}", json={key: version[key] for key in
|
||||
("title", "objectives", "indicators", "directions", "prompts", "templates")})
|
||||
assert edited.status_code == 200
|
||||
assert client.post(f"/api/course-versions/{version['id']}/publish").status_code == 200
|
||||
assert client.put(f"/api/course-versions/{version['id']}", json={key: version[key] for key in
|
||||
("title", "objectives", "indicators", "directions", "prompts", "templates")}).status_code == 409
|
||||
rubric = client.get(f"/api/course-versions/{version['id']}/rubrics").json()[0]
|
||||
rubric["criteria"][0]["name"] = "修订后的评分项"
|
||||
assert client.put(f"/api/rubrics/{rubric['id']}", json={"criteria": rubric["criteria"], "weights": rubric["weights"]}).status_code == 200
|
||||
assert client.post(f"/api/rubrics/{rubric['id']}/publish").status_code == 200
|
||||
batch = client.post("/api/scoring-batches", json={"course_version_id": version["id"], "rubric_version_id": rubric["id"]})
|
||||
assert batch.status_code == 200
|
||||
with session_factory() as db:
|
||||
from wisegrade.models import ScoringBatch
|
||||
snapshot = db.get(ScoringBatch, batch.json()["id"])
|
||||
assert snapshot.course_snapshot["objectives"][0]["name"] == "修订后的目标"
|
||||
assert snapshot.rubric_snapshot["criteria"][0]["name"] == "修订后的评分项"
|
||||
assert db.get(CourseVersion, 1).objectives[0]["name"] != "修订后的目标"
|
||||
assert db.get(RubricVersion, 1).criteria[0]["name"] != "修订后的评分项"
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
def test_missing_material_is_explicit_and_reviewable(session_factory):
|
||||
with session_factory() as db:
|
||||
student = Student(student_no="1023009007", name="测试学生")
|
||||
db.add(student)
|
||||
db.flush()
|
||||
db.add(Project(course_version_id=1, student_id=student.id, topic="没有材料", source_dir="empty/student"))
|
||||
db.commit()
|
||||
client = client_for(session_factory)
|
||||
try:
|
||||
batch_id = client.post("/api/scoring-batches", json={"course_version_id": 1, "rubric_version_id": 1}).json()["id"]
|
||||
run_batch(batch_id, session_factory=session_factory, client_factory=lambda db, batch: object())
|
||||
status = client.get(f"/api/scoring-batches/{batch_id}/progress").json()
|
||||
assert status["status"] == "partial" and status["progress_done"] == status["progress_total"] == 22
|
||||
result = client.get(f"/api/scoring-batches/{batch_id}/scores").json()[0]
|
||||
assert result["totals"]["overall"] is None
|
||||
assert all(row["status"] == "unscorable" and row["error"] for row in result["rows"])
|
||||
first_id = result["rows"][0]["score_id"]
|
||||
response = client.put(f"/api/criterion-scores/{first_id}/review", json={"score": 3, "comment": "人工核定", "reason": "教师确认"})
|
||||
assert response.status_code == 200 and response.json()["model_score"] is None
|
||||
with session_factory() as db:
|
||||
score = db.get(CriterionScore, first_id)
|
||||
assert score.teacher_score == 3 and score.model_score is None
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
Reference in New Issue
Block a user