# WebQuiz
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.
## โจ Features
- **User Management**: Unique username registration with UUID-based session 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 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**: 210+ tests covering all functionality with CI/CD pipeline
- **Flexible File Paths**: Configurable paths for quizzes, logs, CSV, and static files
## ๐ Quick Start
### Prerequisites
- Python 3.9+ (required by aiohttp)
- Poetry (recommended) or pip
- Git
### Installation with Poetry (Recommended)
1. **Clone the repository**
```bash
git clone git@github.com:oduvan/webquiz.git
cd webquiz
```
2. **Install with Poetry**
```bash
poetry install
```
3. **Run the server**
```bash
webquiz # Foreground mode
webquiz -d # Daemon mode
```
4. **Open your browser**
```
http://localhost:8080
```
The server will automatically create necessary directories and files on first run.
### Alternative Installation with pip
1. **Clone and set up virtual environment**
```bash
git clone git@github.com:oduvan/webquiz.git
cd webquiz
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
```
2. **Install dependencies**
```bash
pip install -r requirements.txt
```
3. **Run the server**
```bash
python -m webquiz.cli
```
The server will automatically create necessary directories and files on first run.
## ๐ Project Structure
```
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
```
## ๐ฅ๏ธ CLI Commands
The `webquiz` command provides several options:
```bash
# 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
```
### Key Options
- `--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
### Daemon Mode Features
- **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`
## ๐ Release Management
This project uses GitHub Actions for automated versioning, PyPI deployment, and GitHub Release creation.
### Creating a New Release
1. **Go to GitHub Actions** in the repository
2. **Select "Release and Deploy to PyPI" workflow**
3. **Click "Run workflow"**
4. **Enter the new version** (e.g., `1.0.6`, `2.0.0`)
5. **Click "Run workflow"**
The action will automatically:
- โ
Update version in `pyproject.toml` and `webquiz/__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
### What's included in GitHub Releases
Each release automatically includes:
- ๐ฆ **Python wheel package** (`.whl` file)
- ๐ **Source distribution** (`.tar.gz` file)
- ๐ **Formatted release notes** with installation instructions
- ๐ **Links to commit history** for detailed changelog
- ๐ **Installation commands** for the specific version
### Prerequisites for Release Deployment
Repository maintainers need to set up:
- `PYPI_API_TOKEN` secret in GitHub repository settings
- PyPI account with publish permissions for the `webquiz` package
- `GITHUB_TOKEN` is automatically provided by GitHub Actions
## ๐งช Testing
Run the comprehensive test suite:
```bash
# 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.py
```
### Test Coverage
The project has **210+ tests** across **14 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
- **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
- **Integration Tests** (6 tests): Multiple choice, multiple answers
- **Selenium Tests** (56 tests): End-to-end browser testing
The test suite uses GitHub Actions CI/CD for automated testing on every commit.
## ๐ Configuration Format
### Quiz Files
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`):
```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: true` in 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)
### Server Configuration
Optional server configuration file (`webquiz.yaml`):
```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
```
All configuration sections are optional and have sensible defaults.
## ๐ Data Export
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`
```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.
## ๐จ Customization
### Adding Your Own Quizzes
1. **Create a YAML file** in the `quizzes/` directory
```bash
# Example: quizzes/science_quiz.yaml
```
2. **Add your questions** following the format:
```yaml
title: "Science Quiz"
questions:
- question: "What is H2O?"
options: ["Water", "Hydrogen", "Oxygen", "Salt"]
correct_answer: 0
```
3. **Switch to your quiz** via the admin interface
- Access `/admin` with your master key
- Select your quiz from the dropdown
- Click "Switch Quiz"
### Admin Interface
Enable admin features with a master key:
```bash
webquiz --master-key secret123
```
Access admin panels:
- `/admin` - Quiz management and user approval
- `/files` - View logs, CSV files, and edit configuration
- `/live-stats` - Real-time user progress dashboard
### Styling
- Templates are located in `webquiz/templates/`
- Built-in dark/light theme toggle
- Responsive design works on mobile and desktop
- Generated `static/index.html` can be customized (regenerates on quiz switch)
## ๐ ๏ธ Development
### Building Binary Executable
Create a standalone executable with PyInstaller:
```bash
# 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 secret123
```
The binary includes all templates and configuration examples, with automatic directory creation on first run.
### Key Technical Decisions
- **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
- **UUID-based sessions**: Secure user identification without passwords
- **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
### Architecture
- **Backend**: Python 3.9+ 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
## ๐ Troubleshooting
### Common Issues
**Port already in use:**
```bash
# Kill process using port 8080
lsof -ti:8080 | xargs kill -9
```
**Virtual environment issues:**
```bash
# Recreate virtual environment
rm -rf venv
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
**Quiz not loading:**
- Check that quiz YAML files have valid syntax
- Verify `quizzes/` directory exists and contains `.yaml` files
- Check server logs for errors
- Restart server after adding new quiz files
**Admin interface not accessible:**
- Ensure you started server with `--master-key` option
- Or set `WEBQUIZ_MASTER_KEY` environment 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 install` or `pip install -r requirements.txt`
- Use parallel testing: `pytest tests/ -v -n 4`
**Daemon not stopping:**
```bash
# Check status
webquiz --status
# Force kill if needed
cat webquiz.pid | xargs kill -9
rm webquiz.pid
```
## ๐ License
This project is open source. Feel free to use and modify as needed.
## ๐ค Contributing
1. Fork the repository
2. Create a feature branch
3. Add tests for new functionality
4. Ensure all tests pass
5. Submit a pull request
## ๐ Support
For questions or issues:
- Check the server logs (`server.log`)
- Run the test suite to verify setup
- Review this README and `CLAUDE.md` for detailed documentation
Raw data
{
"_id": null,
"home_page": null,
"name": "webquiz",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": null,
"keywords": "quiz, testing, aiohttp, web, assessment, education",
"author": "Oleksandr Liabakh",
"author_email": "oduvan@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/4d/fd/0b2bd090f3daf3b0fbcfea151cc2ef0ea5cede555049da630c865e7ef8b6/webquiz-1.5.4.tar.gz",
"platform": null,
"description": "# WebQuiz\n\nA 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.\n\n## \u2728 Features\n\n- **User Management**: Unique username registration with UUID-based session tracking\n- **Multi-Quiz System**: Questions loaded from `quizzes/` directory with multiple YAML files\n- **Admin Interface**: Web-based admin panel with master key authentication for quiz management\n- **Registration Approval**: Optional admin approval workflow for new registrations with real-time notifications\n- **Question Randomization**: Configurable per-student question order randomization for fair testing\n- **Dynamic Quiz Switching**: Real-time quiz switching with automatic server state reset\n- **Config File Editor**: Web-based configuration editor with real-time validation\n- **Live Statistics**: Real-time WebSocket-powered dashboard showing user progress\n- **Real-time Validation**: Server-side answer checking with immediate feedback\n- **Session Persistence**: Cookie-based user sessions for seamless experience\n- **Performance Tracking**: Server-side timing for accurate response measurement\n- **Data Export**: Automatic CSV export with quiz-prefixed filenames and unique suffixes\n- **Responsive UI**: Clean web interface with dark/light theme support\n- **Binary Distribution**: Standalone PyInstaller executable with auto-configuration\n- **Comprehensive Testing**: 210+ tests covering all functionality with CI/CD pipeline\n- **Flexible File Paths**: Configurable paths for quizzes, logs, CSV, and static files\n\n## \ud83d\ude80 Quick Start\n\n### Prerequisites\n\n- Python 3.9+ (required by aiohttp)\n- Poetry (recommended) or pip\n- Git\n\n### Installation with Poetry (Recommended)\n\n1. **Clone the repository**\n ```bash\n git clone git@github.com:oduvan/webquiz.git\n cd webquiz\n ```\n\n2. **Install with Poetry**\n ```bash\n poetry install\n ```\n\n3. **Run the server**\n ```bash\n webquiz # Foreground mode\n webquiz -d # Daemon mode\n ```\n\n4. **Open your browser**\n ```\n http://localhost:8080\n ```\n\nThe server will automatically create necessary directories and files on first run.\n\n### Alternative Installation with pip\n\n1. **Clone and set up virtual environment**\n ```bash\n git clone git@github.com:oduvan/webquiz.git\n cd webquiz\n python3 -m venv venv\n source venv/bin/activate # On Windows: venv\\Scripts\\activate\n ```\n\n2. **Install dependencies**\n ```bash\n pip install -r requirements.txt\n ```\n\n3. **Run the server**\n ```bash\n python -m webquiz.cli\n ```\n\nThe server will automatically create necessary directories and files on first run.\n\n## \ud83d\udcc1 Project Structure\n\n```\nwebquiz/\n\u251c\u2500\u2500 pyproject.toml # Poetry configuration and dependencies\n\u251c\u2500\u2500 requirements.txt # Legacy pip dependencies\n\u251c\u2500\u2500 .gitignore # Git ignore rules\n\u251c\u2500\u2500 CLAUDE.md # Project documentation\n\u251c\u2500\u2500 README.md # This file\n\u251c\u2500\u2500 webquiz/ # Main package\n\u2502 \u251c\u2500\u2500 __init__.py # Package initialization\n\u2502 \u251c\u2500\u2500 cli.py # CLI entry point (webquiz command)\n\u2502 \u251c\u2500\u2500 server.py # Main application server\n\u2502 \u251c\u2500\u2500 build.py # PyInstaller binary build script\n\u2502 \u251c\u2500\u2500 binary_entry.py # Binary executable entry point\n\u2502 \u251c\u2500\u2500 version_check.py # Version update checking\n\u2502 \u251c\u2500\u2500 server_config.yaml.example # Configuration example\n\u2502 \u2514\u2500\u2500 templates/ # HTML templates\n\u2502 \u251c\u2500\u2500 index.html # Main quiz interface\n\u2502 \u251c\u2500\u2500 admin.html # Admin management panel\n\u2502 \u251c\u2500\u2500 files.html # File manager interface\n\u2502 \u251c\u2500\u2500 live_stats.html # Live statistics dashboard\n\u2502 \u251c\u2500\u2500 quiz_selection_required.html # Quiz selection prompt\n\u2502 \u2514\u2500\u2500 template_error.html # Error page template\n\u251c\u2500\u2500 tests/ # Test suite (14 test files)\n\u2502 \u251c\u2500\u2500 conftest.py # Test fixtures and configuration\n\u2502 \u251c\u2500\u2500 test_cli_directory_creation.py # CLI and directory tests\n\u2502 \u251c\u2500\u2500 test_admin_api.py # Admin API tests\n\u2502 \u251c\u2500\u2500 test_admin_quiz_management.py # Quiz management tests\n\u2502 \u251c\u2500\u2500 test_config_management.py # Config editor tests\n\u2502 \u251c\u2500\u2500 test_registration_approval.py # Registration approval tests\n\u2502 \u251c\u2500\u2500 test_registration_fields.py # Registration fields tests\n\u2502 \u251c\u2500\u2500 test_index_generation.py # Template generation tests\n\u2502 \u251c\u2500\u2500 test_files_management.py # File manager tests\n\u2502 \u251c\u2500\u2500 test_integration_multiple_choice.py # Multiple choice integration tests\n\u2502 \u251c\u2500\u2500 test_multiple_answers.py # Multiple answer tests\n\u2502 \u251c\u2500\u2500 test_show_right_answer.py # Show answer tests\n\u2502 \u251c\u2500\u2500 test_selenium_multiple_choice.py # Selenium multiple choice tests\n\u2502 \u251c\u2500\u2500 test_selenium_registration_fields.py # Selenium registration tests\n\u2502 \u2514\u2500\u2500 test_user_journey_selenium.py # Selenium user journey tests\n\u2514\u2500\u2500 .github/\n \u2514\u2500\u2500 workflows/\n \u2514\u2500\u2500 test.yml # CI/CD pipeline\n\n# Generated at runtime (excluded from git):\n\u2514\u2500\u2500 quizzes/ # Quiz files directory\n \u251c\u2500\u2500 default.yaml # Default quiz (auto-created)\n \u2514\u2500\u2500 *.yaml # Additional quiz files\n```\n\n## \ud83d\udda5\ufe0f CLI Commands\n\nThe `webquiz` command provides several options:\n\n```bash\n# Start server in foreground (default)\nwebquiz\n\n# Start server with admin interface (requires master key)\nwebquiz --master-key secret123\n\n# Start server with custom directories\nwebquiz --quizzes-dir my_quizzes\nwebquiz --logs-dir /var/log\nwebquiz --csv-dir /data\nwebquiz --static /var/www/quiz\n\n# Combine multiple options\nwebquiz --master-key secret123 --quizzes-dir quizzes --logs-dir logs\n\n# Set master key via environment variable\nexport WEBQUIZ_MASTER_KEY=secret123\nwebquiz\n\n# Start server as daemon (background)\nwebquiz -d\nwebquiz --daemon\n\n# Stop daemon server\nwebquiz --stop\n\n# Check daemon status\nwebquiz --status\n\n# Show help\nwebquiz --help\n\n# Show version\nwebquiz --version\n```\n\n### Key Options\n\n- `--master-key`: Enable admin interface with authentication\n- `--quizzes-dir`: Directory containing quiz YAML files (default: `./quizzes`)\n- `--logs-dir`: Directory for server logs (default: current directory)\n- `--csv-dir`: Directory for CSV exports (default: current directory)\n- `--static`: Directory for static files (default: `./static`)\n- `-d, --daemon`: Run server in background\n- `--stop`: Stop daemon server\n- `--status`: Check daemon status\n\n### Daemon Mode Features\n\n- **Background execution**: Server runs independently in background\n- **PID file management**: Automatic process tracking via `webquiz.pid`\n- **Graceful shutdown**: Proper cleanup on stop\n- **Status monitoring**: Check if daemon is running\n- **Log preservation**: All output still goes to `server.log`\n\n## \ud83d\ude80 Release Management\n\nThis project uses GitHub Actions for automated versioning, PyPI deployment, and GitHub Release creation.\n\n### Creating a New Release\n\n1. **Go to GitHub Actions** in the repository\n2. **Select \"Release and Deploy to PyPI\" workflow**\n3. **Click \"Run workflow\"**\n4. **Enter the new version** (e.g., `1.0.6`, `2.0.0`)\n5. **Click \"Run workflow\"**\n\nThe action will automatically:\n- \u2705 Update version in `pyproject.toml` and `webquiz/__init__.py`\n- \u2705 Run tests to ensure everything works\n- \u2705 Commit the version changes\n- \u2705 Create a git tag with the version\n- \u2705 Build the package using Poetry\n- \u2705 Publish to PyPI\n- \ud83c\udd95 **Create a GitHub Release** with built artifacts\n\n### What's included in GitHub Releases\n\nEach release automatically includes:\n- \ud83d\udce6 **Python wheel package** (`.whl` file)\n- \ud83d\udccb **Source distribution** (`.tar.gz` file)\n- \ud83d\udcdd **Formatted release notes** with installation instructions\n- \ud83d\udd17 **Links to commit history** for detailed changelog\n- \ud83d\udccb **Installation commands** for the specific version\n\n### Prerequisites for Release Deployment\n\nRepository maintainers need to set up:\n- `PYPI_API_TOKEN` secret in GitHub repository settings\n- PyPI account with publish permissions for the `webquiz` package\n- `GITHUB_TOKEN` is automatically provided by GitHub Actions\n\n## \ud83e\uddea Testing\n\nRun the comprehensive test suite:\n\n```bash\n# With Poetry\npoetry run pytest\n\n# Or directly\npytest tests/\n\n# Run with verbose output\npytest tests/ -v\n\n# Run in parallel with 4 workers\npytest tests/ -v -n 4\n\n# Run specific test file\npytest tests/test_admin_api.py\npytest tests/test_registration_approval.py\n```\n\n### Test Coverage\n\nThe project has **210+ tests** across **14 test files** covering:\n\n- **CLI and Directory Creation** (7 tests): Directory and file creation\n- **Admin API** (14 tests): Admin interface and authentication\n- **Admin Quiz Management** (18 tests): Quiz switching and management\n- **Config Management** (16 tests): Config editor and validation\n- **Registration Approval** (20 tests): Approval workflow and timing\n- **Files Management** (32 tests): File manager interface\n- **Index Generation** (13 tests): Template generation tests\n- **Registration Fields** (12 tests): Custom registration fields\n- **Show Right Answer** (5 tests): Answer display functionality\n- **Integration Tests** (6 tests): Multiple choice, multiple answers\n- **Selenium Tests** (56 tests): End-to-end browser testing\n\nThe test suite uses GitHub Actions CI/CD for automated testing on every commit.\n\n## \ud83d\udccb Configuration Format\n\n### Quiz Files\n\nQuestions are stored in YAML files in the `quizzes/` directory. The server automatically creates a `default.yaml` file if the directory is empty.\n\n**Example quiz file** (`quizzes/math_quiz.yaml`):\n\n```yaml\ntitle: \"Mathematics Quiz\"\nrandomize_questions: true # Set to true to randomize question order for each student (default: false)\nquestions:\n - question: \"What is 2 + 2?\"\n options:\n - \"3\"\n - \"4\"\n - \"5\"\n - \"6\"\n correct_answer: 1 # 0-indexed (option \"4\")\n\n - question: \"What is 5 \u00d7 3?\"\n options:\n - \"10\"\n - \"15\"\n - \"20\"\n - \"25\"\n correct_answer: 1 # 0-indexed (option \"15\")\n```\n\n**Question Randomization:**\n- Set `randomize_questions: true` in your quiz YAML to give each student a unique question order\n- Each student receives a randomized order that persists across sessions\n- Helps prevent cheating and ensures fair testing\n- Default is `false` (questions appear in YAML order)\n\n### Server Configuration\n\nOptional server configuration file (`webquiz.yaml`):\n\n```yaml\nserver:\n host: \"0.0.0.0\"\n port: 8080\n\nregistration:\n approve: false # Set to true to require admin approval\n fields:\n - name: \"full_name\"\n label: \"Full Name\"\n required: true\n\nquiz:\n show_right_answer: false # Show correct answer after submission\n```\n\nAll configuration sections are optional and have sensible defaults.\n\n## \ud83d\udcca Data Export\n\nUser responses are automatically exported to CSV files with quiz-prefixed filenames and unique suffixes to prevent overwrites:\n\n**Example:** `math_quiz_user_responses_0001.csv`\n\n```csv\nuser_id,question,selected_answer,correct_answer,is_correct,time_taken_seconds\n123456,\"What is 2 + 2?\",\"4\",\"4\",True,3.45\n123456,\"What is 5 \u00d7 3?\",\"15\",\"15\",True,2.87\n```\n\nCSV files are created with proper escaping and include all user response data. Files are flushed periodically (every 30 seconds) to ensure data persistence.\n\n## \ud83c\udfa8 Customization\n\n### Adding Your Own Quizzes\n\n1. **Create a YAML file** in the `quizzes/` directory\n ```bash\n # Example: quizzes/science_quiz.yaml\n ```\n\n2. **Add your questions** following the format:\n ```yaml\n title: \"Science Quiz\"\n questions:\n - question: \"What is H2O?\"\n options: [\"Water\", \"Hydrogen\", \"Oxygen\", \"Salt\"]\n correct_answer: 0\n ```\n\n3. **Switch to your quiz** via the admin interface\n - Access `/admin` with your master key\n - Select your quiz from the dropdown\n - Click \"Switch Quiz\"\n\n### Admin Interface\n\nEnable admin features with a master key:\n\n```bash\nwebquiz --master-key secret123\n```\n\nAccess admin panels:\n- `/admin` - Quiz management and user approval\n- `/files` - View logs, CSV files, and edit configuration\n- `/live-stats` - Real-time user progress dashboard\n\n### Styling\n\n- Templates are located in `webquiz/templates/`\n- Built-in dark/light theme toggle\n- Responsive design works on mobile and desktop\n- Generated `static/index.html` can be customized (regenerates on quiz switch)\n\n## \ud83d\udee0\ufe0f Development\n\n### Building Binary Executable\n\nCreate a standalone executable with PyInstaller:\n\n```bash\n# Build binary\npoetry run build_binary\n\n# Or directly\npython -m webquiz.build\n\n# The binary will be created at:\n./dist/webquiz\n\n# Run the binary\n./dist/webquiz\n./dist/webquiz --master-key secret123\n```\n\nThe binary includes all templates and configuration examples, with automatic directory creation on first run.\n\n### Key Technical Decisions\n\n- **Multi-quiz system**: Questions loaded from `quizzes/` directory with YAML files\n- **Master key authentication**: Admin endpoints protected with decorator-based authentication\n- **Server-side timing**: All timing calculated server-side for accuracy\n- **Server-side question randomization**: Random question order generated server-side, stored per-user, ensures unique randomized order for each student with session persistence\n- **UUID-based sessions**: Secure user identification without passwords\n- **Middleware error handling**: Clean error management with proper HTTP status codes\n- **CSV module usage**: Proper escaping for data with commas/quotes\n- **Smart file naming**: CSV files prefixed with quiz names, unique suffixes prevent overwrites\n- **Dynamic quiz switching**: Complete server state reset when switching quizzes\n- **WebSocket support**: Real-time updates for admin and live statistics\n- **Binary distribution**: PyInstaller for standalone executable with auto-configuration\n\n### Architecture\n\n- **Backend**: Python 3.9+ with aiohttp async web framework\n- **Frontend**: Vanilla HTML/CSS/JavaScript (no frameworks)\n- **Storage**: In-memory with periodic CSV backups (30-second intervals)\n- **Session Management**: Cookie-based with server-side validation\n- **Real-time Features**: WebSocket for live stats and admin notifications\n\n## \ud83d\udc1b Troubleshooting\n\n### Common Issues\n\n**Port already in use:**\n```bash\n# Kill process using port 8080\nlsof -ti:8080 | xargs kill -9\n```\n\n**Virtual environment issues:**\n```bash\n# Recreate virtual environment\nrm -rf venv\npython3 -m venv venv\nsource venv/bin/activate\npip install -r requirements.txt\n```\n\n**Quiz not loading:**\n- Check that quiz YAML files have valid syntax\n- Verify `quizzes/` directory exists and contains `.yaml` files\n- Check server logs for errors\n- Restart server after adding new quiz files\n\n**Admin interface not accessible:**\n- Ensure you started server with `--master-key` option\n- Or set `WEBQUIZ_MASTER_KEY` environment variable\n- Check that you're using the correct master key\n\n**Tests failing:**\n- Always run tests in virtual environment: `source venv/bin/activate`\n- Install test dependencies: `poetry install` or `pip install -r requirements.txt`\n- Use parallel testing: `pytest tests/ -v -n 4`\n\n**Daemon not stopping:**\n```bash\n# Check status\nwebquiz --status\n\n# Force kill if needed\ncat webquiz.pid | xargs kill -9\nrm webquiz.pid\n```\n\n## \ud83d\udcdd License\n\nThis project is open source. Feel free to use and modify as needed.\n\n## \ud83e\udd1d Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Add tests for new functionality\n4. Ensure all tests pass\n5. Submit a pull request\n\n## \ud83d\udcde Support\n\nFor questions or issues:\n- Check the server logs (`server.log`)\n- Run the test suite to verify setup\n- Review this README and `CLAUDE.md` for detailed documentation\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A modern web-based quiz and testing system built with Python and aiohttp",
"version": "1.5.4",
"project_urls": {
"Bug Tracker": "https://github.com/oduvan/webquiz/issues",
"Documentation": "https://github.com/oduvan/webquiz",
"Homepage": "https://github.com/oduvan/webquiz",
"Repository": "https://github.com/oduvan/webquiz"
},
"split_keywords": [
"quiz",
" testing",
" aiohttp",
" web",
" assessment",
" education"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "dee2e79a7db900910161b4b9c2a31408a4ca9f2a3bdd72b00c278ececdcec1c0",
"md5": "a7f4abe7ac88312deef30c1a4cacafae",
"sha256": "df6617c1fb1fb92b6ff35e3b7f7c537579f9bea56ce5cd5319f2fe8d755e0fce"
},
"downloads": -1,
"filename": "webquiz-1.5.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a7f4abe7ac88312deef30c1a4cacafae",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 76862,
"upload_time": "2025-10-14T13:38:02",
"upload_time_iso_8601": "2025-10-14T13:38:02.003573Z",
"url": "https://files.pythonhosted.org/packages/de/e2/e79a7db900910161b4b9c2a31408a4ca9f2a3bdd72b00c278ececdcec1c0/webquiz-1.5.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "4dfd0b2bd090f3daf3b0fbcfea151cc2ef0ea5cede555049da630c865e7ef8b6",
"md5": "c921263c8b2b0f173f160ec28ab2f3c2",
"sha256": "f2c73095ed75b8fac94e142a951d7249f6e8acd93ad1a33ec6724eeaa92564ee"
},
"downloads": -1,
"filename": "webquiz-1.5.4.tar.gz",
"has_sig": false,
"md5_digest": "c921263c8b2b0f173f160ec28ab2f3c2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.9",
"size": 74985,
"upload_time": "2025-10-14T13:38:04",
"upload_time_iso_8601": "2025-10-14T13:38:04.274628Z",
"url": "https://files.pythonhosted.org/packages/4d/fd/0b2bd090f3daf3b0fbcfea151cc2ef0ea5cede555049da630c865e7ef8b6/webquiz-1.5.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-14 13:38:04",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "oduvan",
"github_project": "webquiz",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "aiohttp",
"specs": [
[
"==",
"3.12.13"
]
]
},
{
"name": "PyYAML",
"specs": [
[
"==",
"6.0.2"
]
]
},
{
"name": "aiofiles",
"specs": [
[
"==",
"24.1.0"
]
]
},
{
"name": "pytest",
"specs": [
[
"==",
"8.3.3"
]
]
},
{
"name": "pytest-asyncio",
"specs": [
[
"==",
"0.24.0"
]
]
},
{
"name": "pytest-xdist",
"specs": [
[
"==",
"3.8.0"
]
]
},
{
"name": "requests",
"specs": [
[
"==",
"2.32.0"
]
]
},
{
"name": "selenium",
"specs": [
[
"==",
"4.24.0"
]
]
},
{
"name": "webdriver-manager",
"specs": [
[
"==",
"4.0.0"
]
]
},
{
"name": "pytest-html",
"specs": [
[
"==",
"4.1.0"
]
]
}
],
"lcname": "webquiz"
}