Learn
09.5 | TESTING AND DEPLOYING A WEB APP
01 | TEST THE CONTRACT A CLIENT SEES
A view’s return value matters, but a real client also sees a status code, headers, cookies and rendered content. Route tests should inspect that full contract, including redirects and denied access.
Flask’s test client runs app requests without a public server. TESTING enables useful test behaviour, but it does not automatically validate your business rules or prove that the external hosting setup works.
Use a temporary database and an explicit test secret. Do not point automated deletion tests at your saved classroom data. Keep CSRF enabled when testing the protection that the application claims to enforce.
02 | CREATE APP INSTANCES WITH A FACTORY
An application factory is a function that constructs and configures an app. The learning lab and portal use create_app so tests can create isolated instances with separate databases rather than reusing one accidental global installation.
Production settings come from the environment. Tests supply TESTING=True, a clearly test-only signing value and a temporary database path. The portal rejects general non-test override dictionaries to keep that route explicit.
A test fixture prepares a known starting state and cleans it up. The bundled unittest files create users and projects deliberately, so success does not depend on yesterday’s manual records.
03 | ASSERT POSITIVE AND NEGATIVE ROUTES
A positive case proves an allowed operation works. A negative case proves a forbidden or unsuitable operation is rejected and leaves accepted data intact. Access-control tests need both.
Test the same record as its owner, another student, a teacher and an anonymous client. Check create, read, edit, delete and feedback independently; one successful permission check does not cover every route.
The portal’s suite includes 28 test methods and keeps CSRF enabled. It tests changed database roles, disabled users, invalid fields, escaped HTML, bound SQL-looking text, cookie flags and method restrictions.
TERMINAL | INSIDE THE PORTAL FOLDER
python -m unittest discover -s . -v
04 | FOLLOW A REDIRECT DELIBERATELY
With follow_redirects=True, the test client follows the response chain. Without it, inspect the 303 and Location header directly. Those checks answer different questions: whether the write redirects correctly and whether the destination renders.
For a protected request, a 302 to sign-in is not the same as a 200 authorised page. Do not declare an access test successful solely because the final response contains some HTML.
Assert stored state after failure. A 403 message is insufficient if the route changed the record before rejecting. A denied cross-owner edit should preserve the earlier title and feedback.
05 | CONFIGURATION IS PART OF THE PROGRAM
Record dependencies, Python baseline, required environment values, database location and startup entry point. A fresh deployment needs them all. An app that only works with your copied .venv is missing a repeatable setup recipe.
Keep secrets outside source and public static folders. A strong random value must be consistent across the intended workers; generating a new signing value for every request or worker causes inconsistent sessions.
Production mode changes Secure-cookie and HSTS behaviour in the portal. It assumes an HTTPS-facing deployment has been configured. Merely setting a flag does not install a certificate or make HTTP traffic encrypted.
06 | A WSGI SERVER RUNS THE PYTHON APP
WSGI is a Python web-server interface. Flask creates a WSGI application, and a production-capable server such as Waitress can host it. A reverse proxy can handle the public connection and HTTPS, then forward appropriate requests to that backend.
The command below runs the portal factory through Waitress on loopback. It is useful for a local serving smoke test. It is not a complete public deployment: HTTPS, process management, access controls and data operations still need their hosting configuration.
Waitress supports a cross-platform local workflow for this course. Other hosts may require different supported startup conventions. Read the selected provider’s Python-hosting requirements rather than assuming one command fits every plan.
TERMINAL | PORTAL FOLDER, SECRET ALREADY SET
waitress-serve --host=127.0.0.1 --port=8080 --call portal:create_app
07 | THE PUBLIC EDGE AND TRUST BOUNDARY
A typical deployment has a browser using HTTPS to reach a proxy or managed edge, which passes requests to the WSGI app. The backend should not be exposed in a way that bypasses the intended public controls.
Proxy headers can describe the original scheme or client address. Only trust them according to the actual proxy configuration and number of trusted intermediaries. Adding ProxyFix with guessed settings can let client-supplied headers influence server decisions.
The sample does not blindly enable proxy middleware. Its deployment instructions ask the operator to configure the chosen supported environment, including host validation and trusted forwarding, before real-user hosting.
08 | CHOOSE A RELEASE CHECK
This fixed model compares development testing, a local WSGI smoke test and a public HTTPS release. It does not deploy anything or check your IONOS plan.
09 | PERSISTENCE, BACKUP AND RELEASE ROLLBACK
A deployment’s filesystem may be ephemeral, meaning it can be replaced during restart or release. Choose persistent storage for the database rather than assuming a file beside source will always survive a platform update.
SQLite fits this small teaching project, but shared production workloads may need a different database and concurrency strategy. Multiple replicas do not automatically share one local SQLite file or signing configuration.
Back up stored data and test restoration. A code rollback does not automatically reverse a database migration, and an old application may not understand a new schema. Plan a compatible transition instead of silently recreating user data.
10 | VERIFY BEFORE REAL ACCOUNTS
Check startup, asset responses, sign-in, session cookie transport, authorised and denied actions, data retention and an error page. Verify debug mode is off and avoid recording passwords or tokens in logs.
The teaching portal does not provide login rate limiting, recovery, breached-password checks, complete session revocation or a public operations system. These are practical next requirements, not features supplied by a passing route suite.
For your static Computer Science Café host, confirm whether its actual plan supports a Python WSGI app or use a separately supported service. These lesson HTML files can be uploaded normally; the Flask download must run in a Python-capable environment.
PUT YOUR SKILLS TO WORK
Use the Section 9 challenges to practise these ideas independently. Work in your Python editor, predict results and keep a short test record.
Section 9 challenges Python course navigation