Voice Development Systems: Build and Test a Small Voice Application
Yenra | Prepared October 3, 2026
Guide: https://yenra.com/voice-development-systems/

LOCAL VOICE APPLICATION LAB
Python 3.10+ standard library. Extract all files into a private folder and open
a terminal there. Run: python -m unittest -v
Windows launcher alternative: py -3 -m unittest -v
Expected: seven tests pass. They create a temporary loopback HTTP server and
stop it automatically. No phone account, credentials or outbound calls.

Commands (replace python with py -3 where appropriate):
python app.py                     -> initial menu XML
python app.py --digits 1          -> fictional hours, then Hangup
python app.py --digits 2          -> fictional directions, then Hangup
python app.py --digits 9          -> one retry, action /menu?attempt=1
python app.py --digits 9 --attempt 1 -> goodbye, then Hangup
python app.py --digits=         -> silence message, then Hangup
python app.py --events            -> 2 unique events; call A sequence 3 completed
python app.py --serve             -> http://127.0.0.1:8765/voice ; Ctrl+C stops

The equals sign supplies an explicit empty value on Windows and other shells.
If port 8765 is occupied, stop your previous
lab process or use the offline commands; the suite uses an available local port.

Optional HTTP request from another terminal (server must be running):
curl.exe -H "Content-Type: application/x-www-form-urlencoded" --data "Digits=1" "http://127.0.0.1:8765/menu?attempt=0"
On systems whose executable is curl, use curl in place of curl.exe.

Files: app.py (XML/HTTP/reducer), test_app.py (unit and HTTP tests), events.json
(fictional out-of-order and repeated events), README.txt (these instructions).
No audio plays. XML is an instruction document. /voice accepts GET; /menu
accepts form-encoded POST with optional Digits and attempt=0 or 1. Missing
Digits means silence. Invalid input gets one retry. All terminal branches end.

The server binds only to loopback and is a local exercise, not production
hosting. It has no webhook signature validation or durable event store.
Do not expose it to the internet or point a real provider at it. A production
deployment requires a supported HTTPS host, provider request authentication,
durable/idempotent state, bounded failure behavior, redacted logging, owned test
numbers and real audio/call testing. See the guide's deployment review.

Supporting sources (see guide for context):
https://www.twilio.com/docs/voice/twiml/gather
https://www.twilio.com/docs/voice/api/call-resource
https://docs.python.org/3/library/http.server.html
https://www.twilio.com/docs/usage/webhooks/webhooks-security
