A modern, full-stack web application for managing online examinations with role-based access for administrators and students.
- Overview
- Features
- Tech Stack
- Prerequisites
- Quick Start
- Project Structure
- Setup Instructions
- Running the Application
- Environment Configuration
- Database Management
- Testing
- API Documentation
- Contributing
- License
Testify is a comprehensive online examination system that enables administrators to create and manage question banks, design exams, and track student performance. Students can take exams in a controlled environment with automatic grading and instant results.
- π Question Bank Management with Excel import/export
- π Exam Creation and Configuration
- π₯ Student Management
- π Results Analytics and Grading
- π Advanced filtering and search capabilities
- π Browse and take assigned exams
- β±οΈ Timed exam sessions with auto-submit
- π View results and performance analytics
- π Review submitted answers
- π Secure JWT-based authentication
- π€ Role-based access control (Admin/Student)
- π± Responsive Material UI design
- π Real-time exam state management
- πΎ Automatic data persistence
- Framework: FastAPI 0.121.1
- ORM: SQLAlchemy 2.0.44
- Database: PostgreSQL 15
- Authentication: JWT (python-jose)
- Password Hashing: bcrypt
- Migrations: Alembic 1.17.1
- Testing: pytest, pytest-cov
- Server: Uvicorn (ASGI)
- Framework: React 19.2.0
- Language: TypeScript 5.9.3
- Build Tool: Vite 7.2.2
- UI Library: Material-UI (MUI) 7.3.5
- State Management: Zustand 5.0.8
- HTTP Client: Axios 1.13.2
- Routing: React Router DOM 7.9.6
- Forms: React Hook Form 7.66.0
- Charts: Recharts 3.4.1
- Containerization: Docker & Docker Compose
- Database Admin: pgAdmin 4
- Version Control: Git
Before you begin, ensure you have the following installed:
- Node.js (v18 or higher) - Download
- Python (3.9 or higher) - Download
- Docker Desktop - Download
- Git - Download
- PostgreSQL (optional, can use Docker) - Download
Get the application running in 5 minutes:
# 1. Clone the repository
git clone https://github.com/Tanjim-Noor/Testify.git
cd Testify
# 2. Start backend services
cd backend
python -m venv venv
.\venv\Scripts\Activate.ps1
pip install -r requirements.txt
Copy-Item .env.example .env
# Start database
cd docker
docker-compose up -d
cd ..
# Run migrations
alembic upgrade head
# Start backend server
.\run_server.ps1
# 3. In a new terminal, start frontend
cd frontend
npm install
Copy-Item .env.example .env
npm run devAccess the application:
- Frontend: http://localhost:3000
- Backend API: http://localhost:8000
- API Docs: http://localhost:8000/docs
- pgAdmin: http://localhost:5050
Testify/
βββ backend/ # FastAPI backend application
β βββ alembic/ # Database migration scripts
β β βββ versions/ # Migration version files
β βββ docker/ # Docker configuration
β β βββ docker-compose.yml # PostgreSQL & pgAdmin setup
β βββ docs/ # Backend documentation
β βββ scripts/ # Helper scripts for migrations
β βββ seeds/ # Database seeding utilities
β βββ src/ # Source code
β β βββ config/ # Configuration & settings
β β βββ models/ # SQLAlchemy database models
β β βββ routes/ # API endpoint definitions
β β βββ schemas/ # Pydantic request/response schemas
β β βββ services/ # Business logic layer
β β βββ utils/ # Utility functions & dependencies
β β βββ main.py # Application entry point
β βββ tests/ # Test suite
β βββ uploads/ # File upload storage
β βββ .env.example # Environment variables template
β βββ alembic.ini # Alembic configuration
β βββ pytest.ini # Pytest configuration
β βββ requirements.txt # Python dependencies
β βββ run_server.ps1 # Server startup script
β
βββ frontend/ # React frontend application
β βββ public/ # Static assets
β βββ src/ # Source code
β β βββ api/ # API client services
β β βββ components/ # React components
β β β βββ admin/ # Admin portal components
β β β βββ student/ # Student portal components
β β βββ hooks/ # Custom React hooks
β β βββ store/ # Zustand state management
β β βββ theme/ # Material-UI theme configuration
β β βββ types/ # TypeScript type definitions
β β βββ utils/ # Utility functions
β β βββ main.tsx # Application entry point
β βββ .env.example # Environment variables template
β βββ package.json # Node dependencies & scripts
β βββ tsconfig.json # TypeScript configuration
β βββ vite.config.ts # Vite build configuration
β
βββ project phases/ # Development phase documentation
βββ scripts/ # Utility scripts
βββ README.md # This file
cd backendWindows (PowerShell):
python -m venv venv
.\venv\Scripts\Activate.ps1Linux/Mac:
python3 -m venv venv
source venv/bin/activatepip install -r requirements.txt# Copy the example environment file
Copy-Item .env.example .env
# Edit .env with your preferred editor
notepad .envImportant environment variables to configure:
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | postgresql://admin:admin_password@postgres:5432/testify_db |
JWT_SECRET |
Secret key for JWT tokens | your-secret-key-change-in-production |
JWT_EXPIRATION |
Token expiration in minutes | 30 |
DEBUG |
Enable debug mode | False |
cd docker
docker-compose up -d
cd ..Verify containers are running:
docker-compose -f docker/docker-compose.yml ps# Apply all migrations
alembic upgrade head
# Or use the helper script
.\scripts\migrate.ps1# Seed all data
python -u scripts/seed.py all
# Or seed specific data
python -u scripts/seed.py users
python -u scripts/seed.py questions
python -u scripts/seed.py examsNote: Seeding requires DEBUG=True in your .env file.
cd frontendnpm install# Copy the example environment file
Copy-Item .env.example .env
# Edit .env with your preferred editor
notepad .envFrontend environment variables:
| Variable | Description | Default |
|---|---|---|
VITE_API_BASE_URL |
Backend API base URL | http://localhost:8000 |
VITE_APP_NAME |
Application name | Testify |
VITE_APP_VERSION |
Application version | 0.1.0 |
npm run generate:templateThis creates a question import template at public/questions_template.xlsx with three sample questions:
- Single Choice: HTTP status code question (Web Dev)
- Text (Open-ended): React hooks comparison question (Frontend)
- Multi-Choice: Identifying fruits question (General Knowledge)
The template demonstrates the correct Excel format for importing questions into the system. You can modify these examples or use them as a reference when creating your own question bank.
Option 1: Using the startup script (Windows)
cd backend
.\run_server.ps1Option 2: Manual start
cd backend
.\venv\Scripts\Activate.ps1
python -m uvicorn src.main:app --reload --host 0.0.0.0 --port 8000Linux/Mac:
cd backend
source venv/bin/activate
uvicorn src.main:app --reload --host 0.0.0.0 --port 8000The backend will be available at:
- API: http://localhost:8000
- Swagger Docs: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
cd frontend
npm run devThe frontend will be available at http://localhost:3000
pgAdmin:
- URL: http://localhost:5050
- Email: admin@example.com (from .env)
- Password: admin_password (from .env)
Register PostgreSQL Server in pgAdmin:
- Click "Add New Server"
- General Tab: Name:
Testify DB - Connection Tab:
- Host:
postgres - Port:
5432 - Database:
testify_db - Username:
admin - Password:
admin_password
- Host:
# Database Configuration
DATABASE_URL=postgresql://admin:admin_password@postgres:5432/testify_db
POSTGRES_DB=testify_db
POSTGRES_USER=admin
POSTGRES_PASSWORD=admin_password
# JWT Configuration
JWT_SECRET=your-secret-key-change-in-production
JWT_ALGORITHM=HS256
JWT_EXPIRATION=30
# CORS Configuration
CORS_ORIGINS=["http://localhost:3000","http://localhost:8000","http://127.0.0.1:3000"]
# Application Configuration
APP_TITLE=Online Exam Management System
APP_VERSION=0.1.0
DEBUG=False
# pgAdmin Configuration
PGADMIN_DEFAULT_EMAIL=admin@example.com
PGADMIN_DEFAULT_PASSWORD=admin_passwordVITE_API_BASE_URL=http://localhost:8000
VITE_APP_NAME=Testify
VITE_APP_VERSION=0.1.0# Auto-generate migration from model changes
alembic revision --autogenerate -m "Description of changes"
# Or use helper script
.\scripts\create_migration.ps1 "Description of changes"# Apply all pending migrations
alembic upgrade head
# Or use helper script
.\scripts\migrate.ps1# Rollback last migration
alembic downgrade -1
# Rollback to specific version
alembic downgrade <revision_id>
# Or use helper script
.\scripts\rollback.ps1# Show current version
alembic current
# Show migration history
alembic history
# Or use helper scripts
.\scripts\current_version.ps1
.\scripts\migration_history.ps1cd backend
# Seed all data
python -u scripts/seed.py all
# Seed specific data types
python -u scripts/seed.py users
python -u scripts/seed.py questions
python -u scripts/seed.py exams
python -u scripts/seed.py exam-questions
python -u scripts/seed.py student-exams
python -u scripts/seed.py student-answers
# Clean all seeded data
python -u scripts/seed.py clean --force
# Verify seeded data
python -u scripts/verify_seeds.pyNote: Seeding requires DEBUG=True in .env unless using --force flag.
The backend includes comprehensive pytest test suites with 80% coverage requirement.
cd backend
pytest -vvpytest -vv --cov=src --cov-report=htmlView coverage report at backend/htmlcov/index.html
# Authentication tests
pytest -vv tests/comprehensive\ testing/test_auth.py
# Service layer tests
pytest -vv tests/comprehensive\ testing/test_services_core.py
# Phase-based tests
pytest backend/tests/phase_08_student_exam -q
# Run by keyword
pytest -vv -k "test_grade"# Start database
cd docker
docker-compose up -d
cd ..
# Run integration tests
pytest -q -m integrationTests are organized by development phase:
tests/phase_05_excel_import/- Excel import functionalitytests/phase_06_question_crud/- Question CRUD operationstests/phase_07_exam_management/- Exam managementtests/phase_08_student_exam/- Student exam workflow
cd frontend
# Run linter
npm run lint
# Build test
npm run build
# Preview production build
npm run previewOnce the backend is running, access the interactive API documentation:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
POST /api/auth/register- Register new userPOST /api/auth/login- Login and get JWT token
GET /api/admin/questions- List all questionsPOST /api/admin/questions- Create new questionPOST /api/admin/questions/import- Import questions from ExcelGET /api/admin/questions/export- Export questions to ExcelPUT /api/admin/questions/{id}- Update questionDELETE /api/admin/questions/{id}- Delete question
GET /api/admin/exams- List all examsPOST /api/admin/exams- Create new examPUT /api/admin/exams/{id}- Update examDELETE /api/admin/exams/{id}- Delete examPOST /api/admin/exams/{id}/publish- Publish exam
GET /api/student/exams- List available examsPOST /api/student/exams/{id}/start- Start examPOST /api/student/exams/{id}/submit- Submit examGET /api/student/exams/{id}/results- Get exam results
GET /api/results/{student_exam_id}- Get detailed resultsGET /api/admin/results- Admin view all results
For complete API documentation with request/response schemas, see backend/docs/BACKEND_API_DOCUMENTATION.md
-
Change Default Credentials
- Update
JWT_SECRETin production - Change database passwords
- Update pgAdmin credentials
- Update
-
Environment Variables
- Never commit
.envfiles - Use strong, unique secrets in production
- Rotate JWT secrets periodically
- Never commit
-
Database
- Use strong passwords
- Enable SSL for production databases
- Regular backups
-
CORS
- Configure
CORS_ORIGINSfor production domains - Restrict to necessary origins only
- Configure
# Build backend image
docker build -t testify-backend ./backend
# Build frontend image
docker build -t testify-frontend ./frontend
# Run complete stack
docker-compose up -d- Use environment-specific
.envfiles - Enable HTTPS/SSL certificates
- Configure reverse proxy (nginx/traefik)
- Set up monitoring and logging
- Enable database backups
- Use managed database services (AWS RDS, etc.)
-
Code Style
- Follow PEP 8 guidelines
- Use type hints
- Write docstrings for functions
-
Database Changes
- Always use Alembic migrations
- Never edit applied migrations
- Test migrations before committing
-
Testing
- Write tests for new features
- Maintain 80% coverage minimum
- Test both success and error cases
-
Code Style
- Use TypeScript strict mode
- Follow ESLint rules
- Use functional components and hooks
-
State Management
- Use Zustand for global state
- Keep component state local when possible
- Use React Hook Form for forms
-
API Integration
- Use centralized API client (
src/utils/apiClient) - Handle errors consistently
- Implement proper loading states
- Use centralized API client (
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
type(scope): description
[optional body]
[optional footer]
Types: feat, fix, docs, style, refactor, test, chore
Database connection errors:
# Check if Docker containers are running
docker-compose -f backend/docker/docker-compose.yml ps
# Restart containers
cd backend/docker
docker-compose restartMigration errors:
# Check current migration state
alembic current
# Reset database (development only)
alembic downgrade base
alembic upgrade headImport errors:
# Ensure virtual environment is activated
.\venv\Scripts\Activate.ps1
# Reinstall dependencies
pip install -r requirements.txtPort already in use:
# Kill process on port 3000 (Windows)
netstat -ano | findstr :3000
taskkill /PID <PID> /FBuild errors:
# Clear node_modules and reinstall
Remove-Item -Recurse -Force node_modules
Remove-Item package-lock.json
npm installAPI connection issues:
- Verify
VITE_API_BASE_URLin.env - Check backend is running on correct port
- Verify CORS settings in backend
.env
This project is licensed under the MIT License - see the LICENSE file for details.
- Tanjim Noor - GitHub
- FastAPI framework and community
- React and Material-UI teams
- All contributors and testers
For support, please open an issue in the GitHub repository or contact the development team.
Built with β€οΈ for education