Local Test Runner

Load tests (JSON/ZIP), manage multiple tests, randomize questions/options, and save progress.

Ready
Load a test to begin
Time left: --:--:--
Status: idle
No test loaded
Test Library

All tests added to your library

Active Tests

Tests in progress that can be resumed

Submitted Results

Previously submitted test results


JSON Schema (brief)
{
  "title": "Test title",
  "description": "optional description",
  "time_seconds": 3600,           // optional default test duration
  "allow_time_override": true,    // user can override at start
  "randomize_questions": false,   // default setting for question randomization
  "randomize_choices": true,      // default setting for choice randomization
  "questions": [
    // Multiple Choice (Single Answer)
    {
      "id": "q1",
      "type": "mcq_single",
      "prompt": "What is 2+2?",
      "image": "question_image.jpg",  // optional: URL or filename (for ZIP)
      "choices": [
        "3",
        "4",
        {"text": "Five", "image": "five.png"},  // optional: image choices
        "5"
      ],
      "correct": "4",              // single value for mcq_single
      "points": 1
    },
    // Multiple Choice (Multiple Answers)
    {
      "id": "q2",
      "type": "mcq_multi",
      "prompt": "Select prime numbers",
      "choices": ["2", "3", "4", "6"],
      "correct": ["2", "3"],       // ARRAY of values for mcq_multi
      "points": 2
    },
    // True/False
    {
      "id": "q3",
      "type": "true_false",
      "prompt": "The sky is green.",
      "correct": false,            // boolean value
      "points": 1
    },
    // Short Answer
    {
      "id": "q4",
      "type": "short_answer",
      "prompt": "Name the capital of France.",
      "correct": "paris",          // string (case-insensitive)
      "points": 2
    },
    // Numeric
    {
      "id": "q5",
      "type": "numeric",
      "prompt": "Compute 7 * 6.",
      "correct": 42,               // number
      "tolerance": 0,              // optional: acceptable range
      "points": 1
    },
    // Matching
    {
      "id": "q6",
      "type": "matching",
      "prompt": "Match country to capital.",
      "match_pairs": [             // ARRAY of [left, right] pairs
        ["France", "Paris"],
        ["Germany", "Berlin"],
        ["Spain", "Madrid"]
      ],
      "points": 3
    },
    // Ordering
    {
      "id": "q7",
      "type": "ordering",
      "prompt": "Order these numbers ascending.",
      "items": ["3", "1", "2"],   // items to be ordered
      "correct": ["1", "2", "3"], // ARRAY in correct order
      "points": 2
    },
    // Fill in the Blank
    {
      "id": "q8",
      "type": "fill_blank",
      "prompt": "The quick __ fox jumps over the __ dog.",  // use __ for blanks. only two underlines per blank otherwise you're going to add more blanks
      "correct": ["brown", "lazy"],  // ARRAY of correct answers
      "points": 2
    },
    // Essay
    {
      "id": "q9",
      "type": "essay",
      "prompt": "Explain why 1+1=2.",
      "points": 5                  // manual grading (always scores 0 auto)
    }
  ]
}

ZIP Support:
- Create a ZIP file with index.json at the root
- Include image files (jpg, png, gif, svg, etc.)
- Reference images by filename in JSON (e.g., "image": "myimage.png")
- Images are cached and loaded with the test
  

Features: Load tests from JSON or ZIP files, randomize questions/choices, pause to blank questions, manage multiple tests, save progress, view results history, and dark mode support.

Edit Test JSON