Drive the line-based UI in-process: input() answers come from a list
and the output is captured. The tests walk the main menu through
creating, playing, querying, deleting, importing and exporting
characters, plus bad menu input and the Ctrl+C handler.
The play loop runs on a fake clock that advances a minute per call and
stops when time.sleep has been called a set number of times, so it
levels up and saves on schedule without waiting.
The test helpers move to tests/helpers.py, which now also holds the
input() feeder.
The roster tests pin down the .old backup rotation and the five minute
periodic save, with a fake clock in place of datetime.
The command line tests call main() in-process with the save and data
paths in a temporary directory, so coverage counts them. They cover
listing, loading, importing and exporting saves, dumping and loading
word lists, and the first-run character creation. The curses UI is
swapped for a stub there so a stray code path fails instead of taking
over the terminal.
--load-save 0 falls through to the menu and --load-save -1 plays the
last character instead of being rejected; both are marked xfail.
A shared fixture restores pytest's SIGINT handler after the UIs
install their own.