Derives human-readable manual test cases from stateful behavior: identify states, events, transitions, and guard conditions, draw the state table including invalid (empty-cell) transitions, choose a coverage level (all states, valid transitions / 0-switch, transition pairs / 1-switch per Chow, all transitions including invalid ones), then derive one test case per coverage item as an event sequence with per-step expected states (ISTQB CTFL v4.0 section 4.2.4). A deep single-technique walkthrough rather than a broad multi-lens case matrix; the output is manual step/expected cases rather than parameterized test code, and it covers how cases are derived rather than how a case record is structured. Use for lifecycle entities (accounts, orders, subscriptions), workflows, and UI wizards where the response to an event depends on the current state.
78
93%
Does it follow best practices?
Impact
77%
0.81xAverage score across 10 eval scenarios
Passed
No findings from the security scan
We are handing regression testing of the loan application journey to an outsourced team. They get two logins: the applicant portal and the agent console. They do not get database access and they will not get it - the table holds live applicant financial data.
The pack we have today was written by a backend developer and half of its expected results are things like "row moves to status_code 31" and "is_locked flips to 1". None of that is runnable by the people who will be running it, and worse, it hides that two different status codes look identical to everybody outside the database. An application sitting in the underwriting queue and one actively being worked by an underwriter are two codes and one screen: both say "In Underwriting" in the portal and in the console.
The journey itself is straightforward. An application is received. The underwriting team can ask for documents, which puts the ball back with the applicant; uploading them sends it into underwriting. The underwriter approves or declines. An approved application is funded when the money is disbursed, which happens in a nightly batch. The applicant can walk away right up until the money moves, and once it has moved the application is finished - finance has had to write off two loans where an application was withdrawn after disbursement and the funds were never recovered.
Produce docs/loan-lifecycle-tests.md containing:
Credit scoring rules, document OCR, and the disbursement bank integration are out of scope. Do not write code and do not propose giving the testers database access.
Extract the following files before beginning.
=============== FILE: docs/loan-application-lifecycle.md ===============
| Portal / console label | Meaning |
|---|---|
| Received | Submitted, waiting for the underwriting team to look at it |
| Documents needed | We have asked for paperwork; upload panel is open |
| In underwriting | With the underwriting team |
| Approved | Decision made, money not sent yet |
| Declined | Decision made, no money |
| Funded | Money disbursed |
| Withdrawn | The applicant pulled out |
Both screens show the label and the date it last changed. Nothing else about the internal handling is visible.
| Event | Who |
|---|---|
| docs-requested | Underwriting team, from the console |
| documents-uploaded | Applicant, from the portal |
| approve | Underwriter |
| decline | Underwriter |
| disburse | Nightly funding batch |
| withdraw | Applicant, from the portal, or an agent on their behalf |
=============== FILE: db/loan_applications.sql =============== -- Internal schema. Testers do not have access to this; it is included so the -- pack's author can see what the old cases were asserting on. CREATE TABLE loan_applications ( id BIGINT PRIMARY KEY, applicant_id BIGINT NOT NULL, status_code SMALLINT NOT NULL, is_locked TINYINT(1) NOT NULL DEFAULT 0, doc_reminder_sent TINYINT(1) NOT NULL DEFAULT 0, funding_batch_id BIGINT NULL, decision_json JSON NULL, updated_at DATETIME NOT NULL );
-- is_locked is set while an underwriter has the file open in the decision -- editor and cleared when they save or navigate away. It is not surfaced -- anywhere in the portal or the console. -- funding_batch_id is populated when the nightly batch picks the application -- up and stays populated afterwards.