This is a group project for CITS3403 – Agile Web Development (Semester 1, 2026) at the University of Western Australia.
CONTRIBUTORS:
| UWA ID | NAME | GITHUB USERNAME |
|---|---|---|
| 24177482 | Mambwe M Nsanje | mambwensanje |
| 24313991 | Bronte Watts | brontewatts |
| 24803486 | Keithlin Lapuz | KGLapuz |
The application is a UniReviews platform where students can view and contribute:
- Unit reviews
- Discussion threads
- Project ideas and submissions
- Study tips ("Get Ahead" tips)
All content is organised by UWA unit codes (e.g. CITS1401), with user-generated contributions tied to authentication and session state.
git clone https://github.com/KGLapuz/AgileWebDevCits3403
cd AgileWebDevCits3403python -m venv venv
venv\Scripts\activatepython3 -m venv venv
source venv/bin/activatepython -m pip install --upgrade pippip install -r requirements.txtThis project requires a secret key for Flask session security. Do not hardcode secrets into the codebase.
In the root directory of the project, create a file named:
.env
Add the following variables:
SECRET_KEY=your-secret-key-here
DATABASE_URL=sqlite:///app.dbYou can generate a secure secret key using Python:
python -c "import secrets; print(secrets.token_hex(32))"If not already installed:
pip install python-dotenvMake sure your application loads the .env file before running. In your main entry file (e.g. app.py):
from dotenv import load_dotenv
load_dotenv()Ensure your .env file is excluded from version control:
.env
(Already included in .gitignore)
The SECRET_KEY is used to secure user sessions and protect against tampering. Never share or expose this value publicly or commit it to Git.
Populate the database with sample UWA units and users, we used CSSE units for starters:
python seed_database.pyRecommended entry point:
python run_app.pyThe app will be available at:
http://127.0.0.1:5000
The project uses Python's built-in unittest framework for automated testing.
python run_tests.pyTests are discovered automatically from the tests/ directory. Each test file follows the test_*.py naming convention and each test function is prefixed with test_.
Each test class:
- Extends
unittest.TestCase - Uses
setUpto spin up a fresh in-memory SQLite database and populate it with helper data before every test - Uses
tearDownto drop all tables and pop the app context after every test, ensuring no state leaks between tests
The test suite validates:
- User Model (Auth & Session Flow): Password hashing, uniqueness constraints, and role defaults are tested via successful login/logout routing, registration pipelines, and UI flash errors for missing or duplicate credentials.
- Unit & Review Models (Submission & Metrics): Validation rules, optional fields, and relationships are tested by verifying that logged-in users can submit complete review forms to update dynamic list views, while unauthenticated guests are automatically redirected to login.
- Discussion & Comment Models (Interactivity & Hierarchy): Content constraints, linkage requirements, and auto-incrementing reply counts are tested via deep UI page traversal, verifying that authenticated users can post top-level thread comments and nested replies while guests trigger a flash warning.
- Project Model (Global Pipeline): Model relationships, structural constraints, and optional field inputs are tested via a standalone global submission pipeline that successfully renders custom project entries directly into the extended template listing view.
Each test prints its name and result to the terminal when run with verbosity=2:
OK→ Feature behaves as expectedFAIL→ Anassertmethod did not hold — check the printed traceback for which assertion failed and whyERROR→ The test itself raised an unexpected exception before reaching any assertion — typically caused by:- A missing or misconfigured
TestingConfig - Import or path errors in the test setup
- A database constraint violation in a helper function
- A missing or misconfigured
| Route | Description |
|---|---|
/ |
Displays all available units |
| Route | Description |
|---|---|
/unit/<unit_code> |
Displays a specific unit page |
Example:
/unit/CITS1401
| Route | Description |
|---|---|
/<unit_code>/reviews |
Displays all reviews for a unit |
/<unit_code>/create_review |
Create a new review (login required) |
- Users must be logged in to submit reviews
- Rating must be between 1 and 5 stars
- Workload must be between 1 and 20 hours
- Review content must be at least 30 characters
- Optional "Get Ahead" tips are limited to 200 characters
| Route | Description |
|---|---|
/<unit_code>/discussions |
View all discussions for a unit |
/<unit_code>/create_discussion |
Create a discussion (login required) |
/discussion/<discussion_id> |
View discussion thread |
| Route | Description |
|---|---|
/<unit_code>/projects |
View all projects |
/<unit_code>/submit_project |
Submit a project (login required) |
/projects/<project_id> |
View project details |
- Users authenticate via a login form
- On success,
user_idis stored in the session - Session state determines access to restricted actions
- Logging out clears the session
user_id - This prevents access to:
- Creating reviews
- Posting discussions
- Submitting projects
Certain actions require authentication:
- Create review
- Create discussion
- Submit project
If a user is not logged in:
- They are redirected to the login page
- A flash message explains the requirement
Each unit supports optional Get Ahead tips, which allow students to:
- Share preparation advice before semester start
- Provide study strategies
- Share what caught them off guard
Rules:
- Optional field (can be left blank)
- Maximum 200 characters
- Stored as
NULLif empty
- Flask app uses application factory pattern (
create_app) - Config classes:
DevelopmentConfigTestingConfig(uses in-memory SQLite + CSRF disabled)
- Database is managed via SQLAlchemy + Flask-Migrate
- All tests must run under
TestingConfig— this is applied automatically viarun_tests.py
Tests are designed to validate:
- Behaviour, not implementation
- Database integrity constraints
- Model property correctness
- Nullable and uniqueness constraint enforcement
- Authentication logic (password hashing,
authenticate()method)
Usually means:
- Route mismatch
- Missing dynamic parameter (
<unit_code>) - Blueprint not registered correctly
Usually means:
- Test data missing required model fields
- Helper functions not supplying all required attributes
- Model constraints stricter than test assumptions
Usually means:
TestingConfignot applied — checkcreate_appaccepts a config argument- Database state not cleaned up — confirm
tearDowncallsdb.drop_all()anddb.session.remove() - Import path issue — confirm
tests/is discoverable from the project root
This project is for educational use as part of [CITS3403]: Agile Web Development at the University of Western Australia in semester 1 of 2026.
Disclaimer: This application is a student-built educational tool and is not affiliated with, endorsed by, or representative of the University of Western Australia; all official unit information is sourced directly from the [UWA Handbook](https://www.handbooks.uwa.edu.au/) and users should refer there for authoritative and up-to-date unit details.