A modern web-based quiz and testing system built with Python and aiohttp that allows users to take multiple-choice tests with real-time answer validation and performance tracking.
- Multi-Quiz System: Questions loaded from
quizzes/directory with multiple YAML files - Admin Interface: Web-based admin panel with master key authentication for quiz management
- Registration Approval: Optional admin approval workflow for new registrations with real-time notifications
- Question Randomization: Configurable per-student question order randomization for fair testing
- Dynamic Answer Visibility: Optional delayed answer reveal - show correct answers only after all students complete
- Dynamic Quiz Switching: Real-time quiz switching with automatic server state reset
- Config File Editor: Web-based configuration editor with real-time validation
- Live Statistics: Real-time WebSocket-powered dashboard showing user progress
- Real-time Validation: Server-side answer checking with immediate feedback
- Session Persistence: Cookie-based user sessions for seamless experience
- Performance Tracking: Server-side timing for accurate response measurement
- Data Export: Automatic CSV export with quiz-prefixed filenames and unique suffixes
- Responsive UI: Clean web interface with dark/light theme support
- Binary Distribution: Standalone PyInstaller executable with auto-configuration
- Comprehensive Testing: 222+ tests covering all functionality with CI/CD pipeline
- Flexible File Paths: Configurable paths for quizzes, logs, CSV, and static files
- Python 3.9-3.14 (required by aiohttp)
- Poetry (recommended) or pip
- Git
-
Clone the repository
git clone [email protected]:oduvan/webquiz.git cd webquiz
-
Install with Poetry
poetry install
-
Run the server
webquiz # Foreground mode webquiz -d # Daemon mode
-
Open your browser
http://localhost:8080
The server will automatically create necessary directories and files on first run.
-
Clone and set up virtual environment
git clone [email protected]:oduvan/webquiz.git cd webquiz python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install dependencies
pip install -r requirements.txt
-
Run the server
python -m webquiz.cli
The server will automatically create necessary directories and files on first run.
webquiz/
βββ pyproject.toml # Poetry configuration and dependencies
βββ requirements.txt # Legacy pip dependencies
βββ .gitignore # Git ignore rules
βββ CLAUDE.md # Project documentation
βββ README.md # This file
βββ webquiz/ # Main package
β βββ __init__.py # Package initialization
β βββ cli.py # CLI entry point (webquiz command)
β βββ server.py # Main application server
β βββ build.py # PyInstaller binary build script
β βββ binary_entry.py # Binary executable entry point
β βββ version_check.py # Version update checking
β βββ server_config.yaml.example # Configuration example
β βββ templates/ # HTML templates
β βββ index.html # Main quiz interface
β βββ admin.html # Admin management panel
β βββ files.html # File manager interface
β βββ live_stats.html # Live statistics dashboard
β βββ quiz_selection_required.html # Quiz selection prompt
β βββ template_error.html # Error page template
βββ tests/ # Test suite (14 test files)
β βββ conftest.py # Test fixtures and configuration
β βββ test_cli_directory_creation.py # CLI and directory tests
β βββ test_admin_api.py # Admin API tests
β βββ test_admin_quiz_management.py # Quiz management tests
β βββ test_config_management.py # Config editor tests
β βββ test_registration_approval.py # Registration approval tests
β βββ test_registration_fields.py # Registration fields tests
β βββ test_index_generation.py # Template generation tests
β βββ test_files_management.py # File manager tests
β βββ test_integration_multiple_choice.py # Multiple choice integration tests
β βββ test_multiple_answers.py # Multiple answer tests
β βββ test_show_right_answer.py # Show answer tests
β βββ test_selenium_multiple_choice.py # Selenium multiple choice tests
β βββ test_selenium_registration_fields.py # Selenium registration tests
β βββ test_user_journey_selenium.py # Selenium user journey tests
βββ .github/
βββ workflows/
βββ test.yml # CI/CD pipeline
# Generated at runtime (excluded from git):
βββ quizzes/ # Quiz files directory
βββ default.yaml # Default quiz (auto-created)
βββ *.yaml # Additional quiz files
The webquiz command provides several options:
# Start server in foreground (default)
webquiz
# Start server with admin interface (requires master key)
webquiz --master-key secret123
# Start server with custom directories
webquiz --quizzes-dir my_quizzes
webquiz --logs-dir /var/log
webquiz --csv-dir /data
webquiz --static /var/www/quiz
# Combine multiple options
webquiz --master-key secret123 --quizzes-dir quizzes --logs-dir logs
# Set master key via environment variable
export WEBQUIZ_MASTER_KEY=secret123
webquiz
# Start server as daemon (background)
webquiz -d
webquiz --daemon
# Stop daemon server
webquiz --stop
# Check daemon status
webquiz --status
# Show help
webquiz --help
# Show version
webquiz --version--master-key: Enable admin interface with authentication--quizzes-dir: Directory containing quiz YAML files (default:./quizzes)--logs-dir: Directory for server logs (default: current directory)--csv-dir: Directory for CSV exports (default: current directory)--static: Directory for static files (default:./static)-d, --daemon: Run server in background--stop: Stop daemon server--status: Check daemon status
- Background execution: Server runs independently in background
- PID file management: Automatic process tracking via
webquiz.pid - Graceful shutdown: Proper cleanup on stop
- Status monitoring: Check if daemon is running
- Log preservation: All output still goes to
server.log
This project uses GitHub Actions for automated versioning, PyPI deployment, and GitHub Release creation.
- Go to GitHub Actions in the repository
- Select "Release and Deploy to PyPI" workflow
- Click "Run workflow"
- Enter the new version (e.g.,
1.0.6,2.0.0) - Click "Run workflow"
The action will automatically:
- β
Update version in
pyproject.tomlandwebquiz/__init__.py - β Run tests to ensure everything works
- β Commit the version changes
- β Create a git tag with the version
- β Build the package using Poetry
- β Publish to PyPI
- π Create a GitHub Release with built artifacts
Each release automatically includes:
- π¦ Python wheel package (
.whlfile) - π Source distribution (
.tar.gzfile) - π Formatted release notes with installation instructions
- π Links to commit history for detailed changelog
- π Installation commands for the specific version
Repository maintainers need to set up:
PYPI_API_TOKENsecret in GitHub repository settings- PyPI account with publish permissions for the
webquizpackage GITHUB_TOKENis automatically provided by GitHub Actions
Run the comprehensive test suite:
# With Poetry
poetry run pytest
# Or directly
pytest tests/
# Run with verbose output
pytest tests/ -v
# Run in parallel with 4 workers
pytest tests/ -v -n 4
# Run specific test file
pytest tests/test_admin_api.py
pytest tests/test_registration_approval.pyThe project has 222+ tests across 15 test files covering:
- CLI and Directory Creation (7 tests): Directory and file creation
- Admin API (14 tests): Admin interface and authentication
- Admin Quiz Management (18 tests): Quiz switching and management
- Admin Quiz Editor (7 tests): Wizard mode quiz creation with randomize_questions and show_answers_on_completion
- Config Management (16 tests): Config editor and validation
- Registration Approval (20 tests): Approval workflow and timing
- Files Management (32 tests): File manager interface
- Index Generation (13 tests): Template generation tests
- Registration Fields (12 tests): Custom registration fields
- Show Right Answer (5 tests): Answer display functionality
- Show Answers on Completion (10 tests): Dynamic answer visibility after all students complete
- Integration Tests (6 tests): Multiple choice, multiple answers
- Selenium Tests (56 tests): End-to-end browser testing
- Auto-Advance (6 tests): Automatic progression behavior
The test suite uses GitHub Actions CI/CD for automated testing on every commit.
Stress testing has been moved to a separate project for better maintainability and independent versioning.
# Install from PyPI
pip install webquiz-stress-test
# Or download pre-built binaries from releases
# https://github.com/oduvan/webquiz-stress-test/releases# Basic test with 10 concurrent users
webquiz-stress-test
# Heavy load test with 100 users
webquiz-stress-test -c 100
# Test custom server
webquiz-stress-test -u http://localhost:9000 -c 50- Concurrent client simulation with configurable users
- Realistic user behavior (random delays, page reloads)
- Randomized quiz support
- Approval workflow testing
- Detailed performance statistics
- Multi-platform binaries (Linux, macOS, Windows)
For complete documentation, see the webquiz-stress-test repository.
Questions are stored in YAML files in the quizzes/ directory. The server automatically creates a default.yaml file if the directory is empty.
Example quiz file (quizzes/math_quiz.yaml):
title: "Mathematics Quiz"
randomize_questions: true # Set to true to randomize question order for each student (default: false)
questions:
- question: "What is 2 + 2?"
options:
- "3"
- "4"
- "5"
- "6"
correct_answer: 1 # 0-indexed (option "4")
- question: "What is 5 Γ 3?"
options:
- "10"
- "15"
- "20"
- "25"
correct_answer: 1 # 0-indexed (option "15")Question Randomization:
- Set
randomize_questions: truein your quiz YAML to give each student a unique question order - Each student receives a randomized order that persists across sessions
- Helps prevent cheating and ensures fair testing
- Default is
false(questions appear in YAML order)
Optional server configuration file (webquiz.yaml):
server:
host: "0.0.0.0"
port: 8080
registration:
approve: false # Set to true to require admin approval
fields:
- name: "full_name"
label: "Full Name"
required: true
quiz:
show_right_answer: false # Show correct answer after submission
show_answers_on_completion: true # Reveal answers only after all students completeAll configuration sections are optional and have sensible defaults.
WebQuiz offers flexible control over when students can see correct answers:
show_right_answer: true(default): Students see correct answers immediately after submitting each questionshow_right_answer: false: Correct answers are completely hidden during the quiz and on the final results pageshow_answers_on_completion: true: Works withshow_right_answer: falseto reveal answers dynamically:- Answers remain hidden until ALL students complete the quiz
- Students see a waiting message with a reload button
- Once all students finish, correct answers become visible
- If new students register, answers are hidden again until everyone completes
- In approval mode, only approved students count toward completion
Example Use Case: Useful for collaborative learning environments where you want students to discuss answers together after everyone has completed the quiz independently.
User responses are automatically exported to CSV files with quiz-prefixed filenames and unique suffixes to prevent overwrites:
Example: math_quiz_user_responses_0001.csv
user_id,question,selected_answer,correct_answer,is_correct,time_taken_seconds
123456,"What is 2 + 2?","4","4",True,3.45
123456,"What is 5 Γ 3?","15","15",True,2.87
CSV files are created with proper escaping and include all user response data. Files are flushed periodically (every 30 seconds) to ensure data persistence.
-
Create a YAML file in the
quizzes/directory# Example: quizzes/science_quiz.yaml -
Add your questions following the format:
title: "Science Quiz" questions: - question: "What is H2O?" options: ["Water", "Hydrogen", "Oxygen", "Salt"] correct_answer: 0
-
Switch to your quiz via the admin interface
- Access
/adminwith your master key - Select your quiz from the dropdown
- Click "Switch Quiz"
- Access
Enable admin features with a master key:
webquiz --master-key secret123Access admin panels:
/admin- Quiz management and user approval/files- View logs, CSV files, and edit configuration/live-stats- Real-time user progress dashboard
- Templates are located in
webquiz/templates/ - Built-in dark/light theme toggle
- Responsive design works on mobile and desktop
- Generated
static/index.htmlcan be customized (regenerates on quiz switch)
Create a standalone executable with PyInstaller:
# Build binary
poetry run build_binary
# Or directly
python -m webquiz.build
# The binary will be created at:
./dist/webquiz
# Run the binary
./dist/webquiz
./dist/webquiz --master-key secret123The binary includes all templates and configuration examples, with automatic directory creation on first run.
- Multi-quiz system: Questions loaded from
quizzes/directory with YAML files - Master key authentication: Admin endpoints protected with decorator-based authentication
- Server-side timing: All timing calculated server-side for accuracy
- Server-side question randomization: Random question order generated server-side, stored per-user, ensures unique randomized order for each student with session persistence
- Middleware error handling: Clean error management with proper HTTP status codes
- CSV module usage: Proper escaping for data with commas/quotes
- Smart file naming: CSV files prefixed with quiz names, unique suffixes prevent overwrites
- Dynamic quiz switching: Complete server state reset when switching quizzes
- WebSocket support: Real-time updates for admin and live statistics
- Binary distribution: PyInstaller for standalone executable with auto-configuration
- Backend: Python 3.9-3.14 with aiohttp async web framework
- Frontend: Vanilla HTML/CSS/JavaScript (no frameworks)
- Storage: In-memory with periodic CSV backups (30-second intervals)
- Session Management: Cookie-based with server-side validation
- Real-time Features: WebSocket for live stats and admin notifications
Port already in use:
# Kill process using port 8080
lsof -ti:8080 | xargs kill -9Virtual environment issues:
# Recreate virtual environment
rm -rf venv
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtQuiz not loading:
- Check that quiz YAML files have valid syntax
- Verify
quizzes/directory exists and contains.yamlfiles - Check server logs for errors
- Restart server after adding new quiz files
Admin interface not accessible:
- Ensure you started server with
--master-keyoption - Or set
WEBQUIZ_MASTER_KEYenvironment variable - Check that you're using the correct master key
Tests failing:
- Always run tests in virtual environment:
source venv/bin/activate - Install test dependencies:
poetry installorpip install -r requirements.txt - Use parallel testing:
pytest tests/ -v -n 4
Daemon not stopping:
# Check status
webquiz --status
# Force kill if needed
cat webquiz.pid | xargs kill -9
rm webquiz.pidThis project is open source. Feel free to use and modify as needed.
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
For questions or issues:
- Check the server logs (
server.log) - Run the test suite to verify setup
- Review this README and
CLAUDE.mdfor detailed documentation