CBT QA Runbook¶
Last verified: 2026-06-13
Mode: server · Workspace: /home/scola/odoo
SSOT terkait: docs/domains/cbt/README.md · docs/user-guide/quick-start/buat-ujian-cbt.md · docs/qa/cbt-question-sync-uat-checklist.md
Runbook ini dipakai untuk sign-off manual fitur CBT setelah automated QC lulus. Jalankan di server dev/staging yang representatif, dengan backend Odoo dan frontend build/deploy yang mengarah ke origin yang sama (https://dev.gcgscola.id → proxy ke Odoo dev).
0. Model Context Ujian (Wajib Pahami Sebelum UAT)¶
Scola memisahkan tiga context ujian. Salah pilih context = siswa tidak melihat ujian meskipun rombel sudah dipilih.
| Context | Route guru (buat/kelola) | Peserta siswa | Auto-enroll dari rombel? |
|---|---|---|---|
learning |
/faculty/assignments → tab Ulangan atau /faculty/assignments/exam-create |
/student/cbt (schedule API) |
Ya — op.exam.attendees + fallback membership batch |
independent |
/faculty/cbt/exams → Buat Ujian |
/student/cbt hanya jika ada scola.cbt.participant |
Tidak — wajib tambah participant manual/import di detail ujian |
admission |
/admin/spmb/cbt/exams atau /admin-staff/admissions/cbt/exams |
Flow SPMB /spmb/... |
Dari jadwal/slot SPMB, bukan dari rombel sekolah |
Label UI saat buat ujian non-kelas (CBTExamList.vue):
- Context: Independent — try out, olimpiade, tes publik
- Context: Admission — tes SPMB
- Field Rombongan Belajar (Opsional): hanya mengikat session (
op.exam.session), bukan daftar peserta siswa untuk contextindependent
Nama session backend: {nama_rombel} ({Independent|Learning|Admission}) — contoh 7B (Independent). Bukan bug jika guru melihat kombinasi rombel + context di metadata session.
0.1 Playbook Investigasi Keluhan Umum¶
Keluhan: "Soal/ujian tidak muncul di siswa"¶
Checklist diagnosa (urutkan dari paling sering):
| # | Cek | Expected jika benar | Temuan tipikal |
|---|---|---|---|
| 1 | Context ujian apa? | learning vs independent menentukan mekanisme visibility |
Guru pilih Independent + rombel → siswa tidak auto-enroll |
| 2 | Apakah siswa sudah jadi participant? | Detail ujian → section Participant → minimal 1 siswa identity_type=student, state Aktif |
Kosong → schedule siswa kosong (by design BE student_schedule.py) |
| 3 | Status ujian | Siswa hanya melihat state schedule, held, result_in_progress, done — bukan draft |
Ujian masih draft |
| 4 | Jendela waktu | start_time / end_time memengaruhi status not_started / on_going |
Di luar jadwal → kartu ada tapi tidak bisa start |
| 5 | Jumlah soal di ujian | question_count computed dari question_set_id (live sync) |
Bank soal diupdate tapi ujian pakai set lain / set kosong saat create |
| 6 | Feature flag | Tenant aktif scola_cbt |
Menu/runner tidak muncul |
Verdict keluhan contoh (Independent + rombel 7B): bukan bug sync soal — gap operasional/UX. Guru mengira pilih rombel = siswa otomatis ikut; untuk independent wajib langkah participant (lihat §8B).
Keluhan: "Ujian muncul di laptop guru, tidak di HP"¶
| # | Cek | Penjelasan |
|---|---|---|
| 1 | Halaman yang dibuka | Ulangan kelas (/faculty/assignments?tab=exams) hanya list context learning. Ujian Independent/Admission hanya di /faculty/cbt/exams (menu Ujian CBT). |
| 2 | Hard refresh / cache | HP bisa masih cache bundle lama — Ctrl+Shift+R atau tab private |
| 3 | Akun sama? | Pastikan login user yang sama; filter/search kosong |
| 4 | Pagination | List CBT non-kelas page size 12 — ujian baru bisa di halaman 1 setelah sort terbaru; scroll ke atas setelah create |
Verdict: sering salah halaman/menu, bukan data hilang di mobile.
1. Scope¶
Workflow yang diuji:
- Admin CBT settings dan policy.
- Faculty question bank, import, exam authoring (learning / independent / admission), publish, proctoring, grading, analytics, report/export.
- Student runner untuk ujian learning dan independent (dengan participant).
- Admission/public CBT runner untuk SPMB.
- Parent/student schedule visibility.
- Security, accessibility, timeout, session lock, SEB, retention, dan audit log.
Role yang terlibat:
- System/Admin sekolah.
- Faculty/Teacher.
- Student.
- Parent.
- Admission staff/panitia SPMB.
- Proctor/monitor read-only.
2. Preconditions¶
- Backend Odoo dev/staging aktif dan health check pass (
curl -sf http://127.0.0.1:8074/web/healthuntukscoladev). - Frontend deploy aktif pada origin yang sama dengan backend (
https://dev.gcgscola.id). - Module
scola_cbtsudah ter-upgrade tanpa error. - Feature flag/package
scola_cbtaktif untuk tenant. - Seed minimal tersedia:
- 1 admin.
- 1 teacher/faculty dengan capability
academics.cbt_exams.manage. - 2 student aktif pada rombel yang sama (
current_batch_idterisi). - 1 parent terkait student.
- 1 admission staff dan 1 pendaftar SPMB jika menguji admission.
- Browser yang diuji:
- Chromium/Chrome desktop.
- Mobile viewport (375×812) untuk navigasi menu guru dan student schedule/runner.
- Jangan commit screenshot atau artefak
.qa_backups/kecuali diminta eksplisit.
3. Automated Gate Sebelum Manual Smoke¶
Jalankan dari /home/scola/odoo.
Backend¶
python3 -m unittest discover /home/scola/odoo/custom_addons_scola/gcgscola/scola_cbt/tests
/home/scola/odoo/odoo17-venv/bin/python3 /home/scola/odoo/odoo-bin -c /home/scola/odoo/odoo-devscola.conf -d scoladev -u scola_cbt --stop-after-init --without-demo=all
curl -sf http://127.0.0.1:8074/web/health
Frontend (contract + menu CBT)¶
cd /home/scola/odoo/scola-fe-v2
npx vitest run \
tests/menu/cbtMenuRouteRbacSync.spec.js \
tests/menu/teacherCbtFeatureFlag.spec.js \
tests/menu/routerFeatureFlagGuard.spec.js \
tests/unit/services/cbtRunnerService.spec.js \
tests/unit/services/cbtExam.service.spec.js \
tests/unit/services/studentExamSchedule.service.spec.js \
tests/unit/cbtRunnerAccessibilityContract.spec.js \
tests/unit/cbtQuestionImportTemplateContract.spec.js \
tests/unit/services/spmbCbtFlow.contract.spec.js \
--reporter=verbose
git diff --check
E2E smoke (Playwright — butuh env seeded + E2E_ODOO_URL jika lokal)¶
cd /home/scola/odoo/scola-fe-v2
npx playwright test tests/e2e/smoke/cbt_smoke.spec.ts tests/e2e/smoke/exam_roles_smoke.spec.ts tests/e2e/smoke/cbt_independent_enrollment.spec.ts tests/e2e/smoke/cbt_runner_flow.spec.ts --workers=1
Cakupan smoke saat ini (2026-06-11):
| Test | Apa yang diverifikasi |
|---|---|
SM-CBT-001 |
Guru akses /faculty/cbt/exams |
SM-CBT-002 |
Kontrak API student schedule |
SM-CBT-003 |
Independent enroll rombel saat create → siswa lihat schedule |
SM-CBT-004 |
Independent tanpa enroll → schedule kosong |
SM-CBT-005 |
Independent di CBT workspace, bukan tab assignments |
SM-CBT-006 |
Learning (assignments) + runner submit + UI tab Ulangan |
SM-CBT-007 |
Independent full runner submit |
SM-CBT-008 |
Create tanpa enroll → enroll-batches multi-rombel → siswa lihat schedule |
UAT manual per context:
| Context | Dokumen UAT linear |
|---|---|
| Learning → e-Rapor | cbt-eraport-uat-end-to-end.md |
| Independent & Admission | cbt-independent-admission-uat-end-to-end.md |
Gap E2E terbuka: SPMB admission sync nilai + ranking (ADM-UAT-05–08); proctor/export independent.
Acceptance gate:
- Semua command exit 0 (kecuali Playwright
test.skipdengan alasan seed — catat di matrix). - Tidak ada regression baru pada route/menu/contract CBT.
4. Audit E2E vs Best Practice¶
Referensi: testing-guidelines.md, cbt-e2e-hardening-implementation-plan.md.
| Best practice | Status Scola | Rekomendasi QA |
|---|---|---|
| API login > UI login untuk setup | ✅ Dipakai di smoke helpers | Terapkan di UAT manual jika UI login flaky |
| Inspect router sebelum asumsi URL | ✅ Ada spec menu/route | UAT: cek /faculty/cbt/exams vs /faculty/assignments |
| Test happy path per context | ⚠️ Partial (API contract saja) | Manual wajib §8A + §8B + §19 |
| Negative test (participant kosong) | ❌ Belum E2E | Manual §8B step "tanpa participant" → expect kosong di siswa |
| Mobile viewport guru | ❌ Belum E2E | Manual §8C |
| Question sync set → exam count | ⚠️ Unit BE compute | Manual cbt-question-sync-uat-checklist.md |
| Publish/state transition | ❌ Belum E2E | Manual §8 — transisi draft → schedule → held |
| Skip > fail jika env incomplete | ✅ Smoke skip dengan pesan | Jangan klaim PASS jika seed tidak ada |
5. Admin Settings And Policy¶
Login sebagai admin.
Steps:
- Buka menu Pengaturan CBT (
/admin/cbt/settingsatau route canonical di menu akademik). - Pastikan retention default terlihat:
- attempts 365 hari,
- answers 365 hari,
- integrity flags 180 hari,
- audit logs 365 hari,
- exports 30 hari.
- Buat atau update policy dengan:
show_score_immediately=false,auto_submit_on_timeout=false,grace_period_minutes=5,- negative marking aktif,
block_multi_login=true.- Simpan settings.
- Reload halaman dan pastikan nilai tetap tersimpan.
Expected:
- Save berhasil tanpa error.
- Payload policy dipakai oleh exam/runner (beberapa field masih partial — lihat recon §2 di README domain).
- Tidak ada exposure token/session secret di UI settings.
6. Question Bank Authoring¶
Login sebagai teacher/faculty → /faculty/question-bank.
Steps:
- Buat question set baru.
- Tambahkan soal
mcq,mcq_multi,short_answer, danessay. - Isi metadata kurikulum bila tersedia (course/chapter, CP/TP, cognitive level).
- Tambahkan asset image dengan
alt_text. - Upload data URI/file valid sesuai tipe.
- Coba upload mismatch MIME.
- Simpan question set — catat
question_count.
Expected:
- Soal valid tersimpan; count konsisten saat buka ulang detail set.
- Upload mismatch MIME ditolak dengan validasi server.
7. CSV Import¶
Login sebagai teacher/faculty.
Steps:
- Import CSV sample: examples/cbt-question-import-sample-all-types.csv
- Import CSV dengan row warning non-fatal.
- Import CSV invalid.
Expected:
- Import valid menghasilkan question sesuai tipe.
- Warning ditampilkan tanpa menggagalkan seluruh import jika row lain valid.
- Error fatal menolak import dan menjelaskan row/field bermasalah.
8. Exam Authoring And Publish¶
8A — Context learning (ulangan kelas — alur sehari-hari)¶
Login guru → /faculty/assignments/exam-create atau tab Ulangan.
Steps:
- Buat ujian dengan context
learning(implicit di form ini). - Pilih rombel wajib, mapel, question set, jadwal.
- Publish/transisi ke
schedulelaluheld. - Login siswa rombel →
/student/cbt.
Expected:
- Attendee ter-seed otomatis (
attendee_seed_countdi API create). - Siswa melihat ujian di schedule.
question_countujian = count question set (refresh detail ujian).
8B — Context independent (tryout — regresi keluhan user)¶
Login guru → /faculty/cbt/exams → Buat Ujian.
Steps:
- Context: Independent — Try out, olimpiade, tes publik.
- Rombongan Belajar (Opsional): pilih rombel (mis. 7B) — ini tidak meng-enroll siswa.
- Pilih tipe ujian, question set (pastikan count ≥ 1), jadwal mulai/selesai, durasi.
- Buat → redirect ke detail ujian.
- Wajib: centang "Daftarkan semua siswa rombel sebagai peserta ujian" (default aktif jika rombel dipilih), atau tambah participant manual di detail ujian.
- Transisi status
draft→schedule→held. - Login siswa yang didaftarkan →
/student/cbt. - Negative test: buat ujian dengan opsi enroll mati → siswa rombel tidak melihat ujian.
Expected:
- Guru melihat badge Independent + metadata rombel di session.
- Hanya siswa participant yang melihat ujian.
- Tanpa step 5 → FAIL operasional (bukan bug) — siswa kosong.
API verifikasi opsional:
# Login siswa, lalu POST /api/scola_cbt/student/schedule — exam_id harus ada hanya jika participant aktif
8C — Visibility guru desktop vs mobile¶
Steps:
- Buat ujian independent di desktop.
- Di HP (viewport mobile), buka:
/faculty/assignments?tab=exams→ ujian tidak ada (expected).- Menu Belajar Digital → Ujian CBT →
/faculty/cbt/exams→ ujian ada. - Ulangi untuk ujian learning — harus muncul di Tugas & Ulangan → Ulangan, tidak wajib di
/faculty/cbt/exams.
Expected:
- Tidak ada perbedaan data antara desktop/mobile pada route yang sama.
- Perbedaan hanya karena route berbeda (learning vs independent).
8D — Blueprint & publish warning¶
Steps:
- Aktifkan blueprint coverage pada exam CBT.
- Tambahkan rule dengan coverage sengaja kurang.
- Publish/transition — perhatikan warning di detail ujian.
Expected:
- Warning terlihat sebelum held.
- Exam tanpa blueprint tetap bisa berjalan.
9. Student Runner Basic Flow¶
Login sebagai student dengan participant/attendee valid.
Steps:
- Buka
/student/cbt. - Start exam status
on_going. - Jawab berbagai tipe soal; navigasi nomor; tunggu autosave; refresh; submit.
Expected:
- Runner menampilkan sisa waktu.
- Autosave status saved setelah sync.
- Refresh tidak menghapus jawaban.
- Submit berhasil.
- Token ujian tidak exposed di schedule API (
cbt_tokennull).
10. Timeout Policy¶
Scenario A: auto_submit_on_timeout=true — attempt auto-submit saat waktu habis.
Scenario B: auto_submit_on_timeout=false — runner expired, backend menolak save/submit setelah timeout.
11. Session Lock And Multi Login¶
Dua browser siswa, exam yang sama — verifikasi session conflict dan proctor signal.
12. SEB Required¶
Exam dengan cbt_seb_required — tanpa header SEB: instruksi jelas, bukan error mentah.
13. Accessibility And Accommodation¶
Extra time, screen reader mode, keyboard navigation, reduced motion.
14. Proctor Dashboard¶
Login proctor → /faculty/cbt/proctor — monitor attempt, force submit (role berwenang), audit.
15. Grading¶
Workspace grading — auto-grade MCQ/multi/short/essay; override manual; negative marking.
16. Analytics And Item Lifecycle¶
Item analysis — sample kecil vs cukup; distractor; lifecycle question.
17. Audit Log And Export¶
Filter audit; export; sanitasi formula injection.
18. Student And Parent Schedule¶
Login student → /student/cbt.
Steps:
- Verifikasi ujian learning (enrollment rombel) dan independent (hanya jika participant).
- Status:
not_started,on_going,finishedsesuai jadwal server (UTC → timezone sekolah).
Login parent → schedule anak (portal parent / assignment view).
Expected:
- Parent hanya melihat anak terkait.
- Akses
student_iddi luar scope ditolak.
19. Admission/Public CBT¶
Login admission staff → /admin/spmb/cbt/exams atau staff admissions.
Steps:
- Buat exam context admission.
- Tautkan ke jadwal tes SPMB.
- Pendaftar start via flow SPMB.
- Faculty generic tidak bisa create admission context (403/validation).
Expected:
- Peserta dari slot SPMB, bukan rombel manual.
- Route SPMB non-CBT tidak terblokir flag CBT.
20. Regression Matrix¶
Catat hasil setiap skenario:
Date:
Environment:
Backend commit:
Frontend commit:
Tester:
Role:
Scenario:
Result: PASS/FAIL/SKIP
Evidence:
Notes:
Minimum sign-off:
- Admin settings/policy: PASS.
- Learning authoring + siswa schedule: PASS.
- Independent authoring + participant + siswa schedule: PASS.
- Independent tanpa participant → siswa kosong (negative): PASS (expected behavior).
- Guru mobile
/faculty/cbt/examsvs assignments: PASS. - Student runner/autosave/submit: PASS.
- Timeout, session lock, grading, analytics, audit: PASS.
- Admission CBT: PASS atau SKIP dengan alasan tenant.
21. Failure Handling¶
- Environment mati → stop manual smoke, perbaiki dulu.
- Seed tidak ada → SKIP, jangan klaim PASS.
- UI incomplete tapi API lulus → FAIL untuk workflow UI terkait.
- Automated gate gagal → jangan lanjut sign-off.
- Keluhan "siswa tidak lihat ujian" → jalankan §0.1 sebelum laporkan bug ke engineering.
22. Backlog E2E (Post-Audit 2026-06-13)¶
Selesai:
- E2E independent + enroll batch saat create → student schedule (
SM-CBT-003). 1b. E2E independent create tanpa enroll →enroll-batchespost-create → schedule (SM-CBT-008). - E2E negative independent tanpa enroll → schedule kosong (
SM-CBT-004). - E2E guru mobile
/faculty/cbt/examsvs assignments tab (SM-CBT-005). - Product fix: opsi Enroll semua siswa rombel saat create independent (BE
enroll_batch_students, FE checkbox). - E2E learning exam (assignments context) + student runner submit (
SM-CBT-006). - E2E independent full runner submit (
SM-CBT-007).
UAT manual end-to-end:
- Learning → e-Rapor: cbt-eraport-uat-end-to-end.md
- Independent & Admission: cbt-independent-admission-uat-end-to-end.md
Verifikasi server (2026-06-11): SM-CBT-003–008 tersedia di cbt_independent_enrollment.spec.ts (E2E_ENV_FILE=.env.e2e.scoladev.example, Odoo :8074).