Lewati ke isi

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) Yaop.exam.attendees + fallback membership batch
independent /faculty/cbt/examsBuat 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 context independent

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, donebukan 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/health untuk scoladev).
  • Frontend deploy aktif pada origin yang sama dengan backend (https://dev.gcgscola.id).
  • Module scola_cbt sudah ter-upgrade tanpa error.
  • Feature flag/package scola_cbt aktif 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_id terisi).
  • 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-0508); proctor/export independent.

Acceptance gate:

  • Semua command exit 0 (kecuali Playwright test.skip dengan 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 draftscheduleheld
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:

  1. Buka menu Pengaturan CBT (/admin/cbt/settings atau route canonical di menu akademik).
  2. Pastikan retention default terlihat:
  3. attempts 365 hari,
  4. answers 365 hari,
  5. integrity flags 180 hari,
  6. audit logs 365 hari,
  7. exports 30 hari.
  8. Buat atau update policy dengan:
  9. show_score_immediately=false,
  10. auto_submit_on_timeout=false,
  11. grace_period_minutes=5,
  12. negative marking aktif,
  13. block_multi_login=true.
  14. Simpan settings.
  15. 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:

  1. Buat question set baru.
  2. Tambahkan soal mcq, mcq_multi, short_answer, dan essay.
  3. Isi metadata kurikulum bila tersedia (course/chapter, CP/TP, cognitive level).
  4. Tambahkan asset image dengan alt_text.
  5. Upload data URI/file valid sesuai tipe.
  6. Coba upload mismatch MIME.
  7. 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:

  1. Import CSV sample: examples/cbt-question-import-sample-all-types.csv
  2. Import CSV dengan row warning non-fatal.
  3. 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:

  1. Buat ujian dengan context learning (implicit di form ini).
  2. Pilih rombel wajib, mapel, question set, jadwal.
  3. Publish/transisi ke schedule lalu held.
  4. Login siswa rombel → /student/cbt.

Expected:

  • Attendee ter-seed otomatis (attendee_seed_count di API create).
  • Siswa melihat ujian di schedule.
  • question_count ujian = count question set (refresh detail ujian).

8B — Context independent (tryout — regresi keluhan user)

Login guru → /faculty/cbt/examsBuat Ujian.

Steps:

  1. Context: Independent — Try out, olimpiade, tes publik.
  2. Rombongan Belajar (Opsional): pilih rombel (mis. 7B) — ini tidak meng-enroll siswa.
  3. Pilih tipe ujian, question set (pastikan count ≥ 1), jadwal mulai/selesai, durasi.
  4. Buat → redirect ke detail ujian.
  5. Wajib: centang "Daftarkan semua siswa rombel sebagai peserta ujian" (default aktif jika rombel dipilih), atau tambah participant manual di detail ujian.
  6. Transisi status draftscheduleheld.
  7. Login siswa yang didaftarkan → /student/cbt.
  8. 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:

  1. Buat ujian independent di desktop.
  2. Di HP (viewport mobile), buka:
  3. /faculty/assignments?tab=exams → ujian tidak ada (expected).
  4. Menu Belajar Digital → Ujian CBT/faculty/cbt/exams → ujian ada.
  5. 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:

  1. Aktifkan blueprint coverage pada exam CBT.
  2. Tambahkan rule dengan coverage sengaja kurang.
  3. 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:

  1. Buka /student/cbt.
  2. Start exam status on_going.
  3. 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_token null).

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:

  1. Verifikasi ujian learning (enrollment rombel) dan independent (hanya jika participant).
  2. Status: not_started, on_going, finished sesuai jadwal server (UTC → timezone sekolah).

Login parent → schedule anak (portal parent / assignment view).

Expected:

  • Parent hanya melihat anak terkait.
  • Akses student_id di luar scope ditolak.

19. Admission/Public CBT

Login admission staff → /admin/spmb/cbt/exams atau staff admissions.

Steps:

  1. Buat exam context admission.
  2. Tautkan ke jadwal tes SPMB.
  3. Pendaftar start via flow SPMB.
  4. 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/exams vs 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:

  1. E2E independent + enroll batch saat create → student schedule (SM-CBT-003). 1b. E2E independent create tanpa enroll → enroll-batches post-create → schedule (SM-CBT-008).
  2. E2E negative independent tanpa enroll → schedule kosong (SM-CBT-004).
  3. E2E guru mobile /faculty/cbt/exams vs assignments tab (SM-CBT-005).
  4. Product fix: opsi Enroll semua siswa rombel saat create independent (BE enroll_batch_students, FE checkbox).
  5. E2E learning exam (assignments context) + student runner submit (SM-CBT-006).
  6. E2E independent full runner submit (SM-CBT-007).

UAT manual end-to-end:

Verifikasi server (2026-06-11): SM-CBT-003008 tersedia di cbt_independent_enrollment.spec.ts (E2E_ENV_FILE=.env.e2e.scoladev.example, Odoo :8074).