Unit 06.03: Testing refusal on purpose
The refusal path is the least-tested part of most RAG systems, because eval sets are built from questions people wanted answered.
Half the eval set should have no answer
An eval set made only of answerable questions measures one behaviour. The refusal path never runs, so a bug in it never surfaces until a user finds one.
The example below runs a three-case set where two cases expect refusal, and scores each on whether the refusal decision was correct.
CORPUS "Refunds are allowed within 7 days of purchase."
CASE QUESTION SHOULD REFUSE? DID REFUSE? VERDICT
q1 What is the refund window? no no PASS
q2 What is the office address? yes yes PASS
q3 Who is the CEO? yes yes PASS
3 of 3 correct
An eval set with no unanswerable questions never runs the refusal path, so a
fault in it stays hidden until a user finds one.
Each case declares expect_refusal up front, so the assertion is on the *decision*, not on the wording. That is what makes the test stable across changes to the answer text.
Note that a refusal case can fail in two directions. The system can answer when it should refuse - a fluent guess - or refuse when it could have answered, which the last unit of this module shows is the cheaper error. The test catches both, and treating them as equally severe would be wrong.
The mistake this prevents
The mistake is building the eval set from support tickets alone. Tickets are questions someone had an answer for; they systematically exclude the questions your documents cannot support. Add unanswerable cases deliberately, and aim for something close to a third of the set.
Takeaway
An eval set with no unanswerable questions never tests the refusal path. Declare the expected decision per case, assert on the decision rather than the wording, and keep the two failure directions distinguishable.
