CMPUT-499 · Lesson 4 of 12 · 29 min
Requirements and design: user stories, acceptance criteria and accessibility
Once the client has agreed to the proposal, the team turns scope into requirements that can be built and checked. In a capstone this happens in weeks 4 and 5, alongside the architecture work of lesson 5, and it continues throughout the term as the backlog is refined. CMPUT-301 covered requirements engineering, use cases and UML; CMPUT-401 covered user stories and backlogs; CMPUT-421 covered personas, scenarios, prototyping and accessibility. This lesson shows how a capstone team uses those tools together without drowning in documentation, and why accessibility belongs in requirements from the first day rather than in a final audit.
The goal of requirements work in an agile capstone is not a complete specification. It is shared understanding: the team, the client and the supervisor should agree on what each feature does, for whom, and how everyone will know it works. A few well-written stories with clear acceptance criteria, a set of wireframes the client has seen and a short list of non-functional requirements give far more value than a fifty-page document that nobody reads. Requirements will change as the client sees working software, and the process should make change cheap.
Users and their goals
Start from the people found in discovery. Team Relay wrote three short personas based on real interviews, not imagination: a coordinator modeled on Grace's work; a regular driver, retired, who drives three mornings a week and is comfortable with a phone but not with apps that change often; and an occasional driver, a student who picks up weekend shifts and wants to sign up and swap in seconds. They also wrote one anti-persona, someone the product is not designed for: a large logistics company with paid drivers and dispatch software. The anti-persona was useful for rejecting requests that would pull the product away from a volunteer organization.
For each persona, sketch the main task flows end to end. The driver's core flow is: see open shifts, claim one, get a reminder, confirm or cancel, do the pickup and mark it complete. The coordinator's is: create recurring shifts with donors and agencies, see which are unfilled or unconfirmed, contact drivers, and see what was rescued. Walking through flows before designing screens finds gaps. Team Relay realized while walking the driver flow that a driver who cancels needs somewhere for the shift to go: back to the open list, and with an alert to the coordinator if it is within 24 hours. That became a requirement nobody had stated.
User stories and acceptance criteria
A user story describes a small piece of value from a user's point of view: 'As a driver, I want to claim an open pickup shift so that I can help when I am free.' The three parts name who wants it, what they want and why. The 'why' is the most useful part: it lets the team propose a better way to meet the need, and it lets the client judge priority. Good stories follow the INVEST guidelines from CMPUT-401: independent, negotiable, valuable, estimable, small and testable. In practice the two that matter most for a capstone are small (finishable in a few days) and testable (everyone can agree whether it is done).
Acceptance criteria make a story testable. Write them in the Given, When, Then form: given a situation, when the user does something, then something observable happens. 'Given an open shift, when I tap Claim, then the shift shows my name and is no longer open.' Criteria like this translate almost directly into automated tests (lesson 8) and into a script for the client to check at a demo. Vague words such as 'easy', 'fast' or 'user-friendly' cannot be checked and should be replaced by something measurable, like 'the dashboard loads in under two seconds on the co-op's office laptop'.
# A small linter for user stories and acceptance criteria.
# Flags stories that miss the "As a / I want / so that" form, criteria that are not
# Given/When/Then, vague words that cannot be tested, and stories that are too big.
import re
stories = [
{"id": "RR-12", "points": 3,
"text": "As a driver, I want to claim an open pickup shift so that I can help when I am free.",
"criteria": ["Given an open shift, when I tap Claim, then the shift shows my name and is no longer open",
"Given a shift I claimed, when another driver views it, then it shows as taken"]},
{"id": "RR-13", "points": 2,
"text": "As a driver, I want a reminder before my shift so that I do not forget it.",
"criteria": ["Given a claimed shift, when it is 18 hours away, then I receive a reminder by text or email",
"Given a reminder, when I reply CANCEL, then the shift reopens and the coordinator is alerted"]},
{"id": "RR-14", "points": 13,
"text": "As a coordinator, I want the system to be easy and fast.",
"criteria": ["The dashboard should be user-friendly"]},
{"id": "RR-15", "points": 5,
"text": "As the director, I want a monthly report of food rescued so that I can report to funders.",
"criteria": ["Given pickups completed in a month, when I open Reports, then I see total kg by donor and by agency",
"Given the report, when I choose Download, then I get a CSV file"]},
]
VAGUE = r"\b(easy|fast|user-friendly|intuitive|simple|nice|quickly|robust)\b"
FORM = r"^As (an?|the) .+, I want .+ so that .+\.$"
GWT = r"^Given .+, when .+, then .+$"
for s in stories:
issues = []
if not re.match(FORM, s["text"]): issues.append("not in 'As a ..., I want ..., so that ...' form")
if re.search(VAGUE, s["text"] + " ".join(s["criteria"]), re.I): issues.append("vague, untestable words")
bad = [c for c in s["criteria"] if not re.match(GWT, c)]
if bad: issues.append(f"{len(bad)} criterion not Given/When/Then")
if s["points"] > 8: issues.append(f"{s['points']} points: split it")
print(f"{s['id']}: {'OK' if not issues else '; '.join(issues)}")RR-12: OK RR-13: OK RR-14: not in 'As a ..., I want ..., so that ...' form; vague, untestable words; 1 criterion not Given/When/Then; 13 points: split it RR-15: OK
Story RR-14 failed every check, which is typical of the first draft of a story about something the client cares about deeply but has not yet thought through. Priya took it back to Grace and asked what 'easy and fast' meant in her day. The answer split into three stories: see all unfilled shifts for the next seven days on one screen, filter by donor, and send a message to all drivers who have worked a given shift before. Each of these was small, testable and valuable, and together they captured what Grace had meant far better than the original sentence.
| Story | Points | Sprint | Acceptance criteria (summary) |
|---|---|---|---|
| RR-10 Driver account and sign-in | 3 | 1 | Sign up with email or phone; verify; sign in; reset password |
| RR-11 Coordinator creates recurring shifts | 5 | 1 | Weekly pattern, donor, agency, time window; edit one or all |
| RR-12 Driver claims an open shift | 3 | 1 | Claim, see name on shift, shift no longer open |
| RR-13 Reminder and confirm or cancel | 5 | 2 | Reminder 18 h before; confirm; cancel reopens and alerts |
| RR-16 Dashboard of unfilled shifts | 5 | 3 | Next 7 days; filter by donor; color plus text status |
| RR-17 Message past drivers of a shift | 3 | 3 | Pick shift; send to drivers who did it before; log sent |
| RR-15 Monthly funders report | 5 | 3 | Total kg by donor and agency; CSV download |
| RR-20 Driver shift swap (stretch) | 5 | 4 | Offer, accept, coordinator notified, history kept |
Wireframes and prototypes
Wireframes are low-fidelity sketches of screens that show layout and content without visual design. They are the cheapest way to test whether the team and the client imagine the same product. Team Relay drew wireframes on paper first, then in a shared design tool, for the six screens that cover the core flows. They tested the paper versions with Grace and two drivers in a 30-minute session each, using the think-aloud method from CMPUT-421: the participant tries a task and talks while doing it, and the team watches without helping. Two problems appeared immediately. Drivers looked for the shift time in large type at the top, not in a list of details, and the regular driver did not recognize an icon-only 'swap' button.
Prototypes come in fidelities, and the right one depends on the question. A paper prototype answers 'is this the right content and flow?'. A clickable mock-up answers 'can people find their way?'. A thin coded prototype answers 'does this technology work for us?'. Do not polish a prototype beyond what the question needs. Team Relay built one throwaway coded prototype in week 4, a single page that sent a test text message through the messaging provider, because that integration was their riskiest technical assumption. It worked, and they threw the code away rather than building on it, because it had been written in two hours with no tests.
Accessibility from day one
Accessibility means that people with disabilities can use the product. For RescueRoute this is not hypothetical. The co-op's drivers include older adults, some with low vision or reduced dexterity, and at least one who relies on a screen reader. The coordinator may one day be someone who navigates by keyboard. The Web Content Accessibility Guidelines, WCAG 2.2, published in October 2023, are the standard reference; Level AA conformance is the usual target and the level most accessibility laws point to. CMPUT-421 and CMPUT-404 covered WCAG in detail. The capstone lesson is about timing: accessibility is cheap when built in from the first story and expensive when bolted on at the end.
Make accessibility part of the definition of done and of acceptance criteria. Team Relay added four checks to every user-interface story: it works with a keyboard alone, it has visible focus and correct labels for a screen reader, text and important graphics meet contrast ratios of 4.5 to 1 for normal text and 3 to 1 for large text and interface components, and status is never conveyed by color alone. The last check mattered for the dashboard, where the first design used red, yellow and green dots for shift status. Sofia changed it to colored badges with words, 'Unfilled', 'Unconfirmed' and 'Confirmed', which helped not only color-blind users but everyone glancing at a phone in sunlight.
WCAG 2.2 added several criteria that matter for mobile-first tools. Target size (minimum), success criterion 2.5.8, requires interactive targets of at least 24 by 24 CSS pixels unless they are spaced far enough apart. Focus not obscured requires that sticky headers or footers do not hide the element that has keyboard focus. Accessible authentication limits the use of puzzles and memory tests during sign-in, which ruled out an image-based CAPTCHA the team had considered. Dragging movements requires an alternative to drag-and-drop, which affected the coordinator's planned drag-to-reschedule feature. Checking a design against these early is simple arithmetic, as the program below shows.
# Checking a planned phone layout against WCAG 2.2 target size (2.5.8, Level AA):
# interactive targets at least 24 x 24 CSS pixels, or spaced so a 24 px circle
# drawn around each does not overlap another target. Team Relay's own goal is 44 px.
targets = [
# (name, width, height, mid_x, mid_y) in CSS pixels on a 390 px wide screen
("Claim shift button", 358, 48, 195, 520),
("Swap link", 60, 20, 300, 580),
("Cancel link", 60, 20, 300, 602),
("Menu icon", 24, 24, 24, 30),
("Call coordinator", 170, 44, 100, 660),
("Map pin", 18, 18, 320, 300),
]
import math
def too_small(w, h): return w < 24 or h < 24
for name, w, h, cx, cy in targets:
notes = []
if too_small(w, h):
# spacing exception: no other target midpoint within 24 px
close = [n for n, w2, h2, x2, y2 in targets if n != name and math.dist((cx, cy), (x2, y2)) < 24]
notes.append("below 24 px" + (f", too close to {close}" if close else ", but spaced (passes 2.5.8)"))
if w < 44 or h < 44:
notes.append("below team goal of 44 px")
print(f"{name:20} {w:3}x{h:<3} " + ("; ".join(notes) if notes else "OK"))Claim shift button 358x48 OK Swap link 60x20 below 24 px, too close to ['Cancel link']; below team goal of 44 px Cancel link 60x20 below 24 px, too close to ['Swap link']; below team goal of 44 px Menu icon 24x24 below team goal of 44 px Call coordinator 170x44 OK Map pin 18x18 below 24 px, but spaced (passes 2.5.8); below team goal of 44 px
Automated checkers catch perhaps a third of accessibility problems; the rest need people. Plan at least one session in which someone uses the product with a screen reader and keyboard only, and if possible include a user with a disability in testing. Team Relay asked the driver who uses a screen reader to try the sign-up and claim flows in sprint 2, with Grace's help and his consent. He found that the 'Claim' buttons were all announced as 'Claim' with no shift information, so he could not tell which shift he was claiming. The fix, adding the shift's date and donor to each button's accessible name, took ten minutes; finding it without him would have taken much longer.
Non-functional requirements
Functional requirements say what the system does. Non-functional requirements say how well: performance, availability, security, privacy, maintainability, cost and so on. They are often forgotten in capstones and they often decide whether the client can keep using the product. Write them as measurable statements. Team Relay's included: pages load in under two seconds on a mid-range phone on a 4G connection; the system is available 99 percent of the time during the pilot; hosting costs stay under the co-op's limit; all personal data is encrypted in transit and at rest; and a volunteer with basic web experience can deploy a new version by following the README. Lesson 5 turns these into architecture decisions.
| Quality | Requirement | How it will be checked |
|---|---|---|
| Performance | Pages load in under 2 s on a mid-range phone on 4G | Lighthouse runs in CI on key pages |
| Availability | 99 percent monthly during the pilot | Uptime monitor and SLO report (lesson 10) |
| Accessibility | WCAG 2.2 Level AA on all pages | Automated checks plus a manual screen reader test each sprint |
| Security | OWASP Top 10 risks addressed; no secrets in the repository | Dependency and secret scanning in CI; code review checklist |
| Privacy | Collect only listed fields; no personal data in logs | Data inventory review; log redaction tests (lesson 9) |
| Maintainability | A new developer can run it locally in under an hour | Someone outside the team follows the README in week 12 |
| Cost | Within the co-op's monthly hosting limit | Monthly bill reviewed at sprint planning |
Worked examples
Worked problem
Rewriting a vague story
Rewrite "As a coordinator, I want reports to be better" into a testable story with acceptance criteria.
Show solution
- Ask the client what "better" means; suppose the answer is "I need to see food rescued by donor each month for funders".
- Write the story with a reason: "As the director, I want a monthly report of food rescued by donor so that I can report to funders."
- Add Given/When/Then criteria for the report contents and the download.
Answer: "Given completed pickups in a month, when I open Reports, then I see total kg by donor"; "Given the report, when I choose Download, then I get a CSV file."
Worked problem
A contrast check
Gray text #767676 on white has a contrast ratio of about 4.54 to 1. Does it meet WCAG Level AA for normal body text? What about #949494, at about 3.03 to 1?
Show solution
- Level AA requires 4.5 to 1 for normal text and 3 to 1 for large text.
- 4.54 is above 4.5, so #767676 passes for normal text.
- 3.03 is below 4.5, so #949494 fails for normal text, though it would pass for large text.
Answer: #767676 passes; #949494 fails for body text but is acceptable only for large text.
Worked problem
Status without color alone
A dashboard shows shift status as red, yellow and green dots. Which WCAG principle does this break, and what is a fix?
Show solution
- Information conveyed only by color fails success criterion 1.4.1, Use of Color.
- Add text or a distinct shape to each status.
Answer: Use labeled badges such as "Unfilled", "Unconfirmed" and "Confirmed", optionally with icons, as well as color.
Common mistakes
MistakeWrite a complete specification before any code.
InsteadWrite a few clear stories with acceptance criteria and refine the backlog as the client sees working software.
MistakeAccept stories with words like "easy" or "fast".
InsteadReplace them with measurable criteria agreed with the client.
MistakeLeave accessibility to a final audit in the last week.
InsteadMake it part of every story's definition of done from sprint 1.
MistakeBuild on throwaway prototype code because it already works.
InsteadThrow it away; rebuild the feature properly with tests.
MistakeForget non-functional requirements.
InsteadWrite measurable statements for performance, availability, privacy, maintainability and cost.
Summary and key terms
- Requirements work aims at shared understanding, not a complete specification.
- Personas and anti-personas come from discovery; walking task flows reveals missing requirements.
- User stories state who, what and why; acceptance criteria in Given/When/Then make them testable.
- Wireframes and prototypes are cheap tests; match fidelity to the question and throw prototype code away.
- WCAG 2.2 Level AA is the usual accessibility target; build it into every story from the start.
- Automated checkers miss most accessibility problems; test with people, including users with disabilities.
- Non-functional requirements must be measurable and each needs a way to be checked.
- Persona
- A description of a typical user, based on research, used to guide design.
- Anti-persona
- A description of someone the product is deliberately not designed for.
- User story
- A short description of value from a user's point of view: who, what and why.
- Acceptance criteria
- Testable conditions a story must meet, often in Given/When/Then form.
- Wireframe
- A low-fidelity sketch of a screen's layout and content.
- WCAG 2.2
- The Web Content Accessibility Guidelines version 2.2, published in 2023.
- Non-functional requirement
- A requirement about how well a system works, such as speed, availability or privacy.
- Think-aloud test
- A usability test in which a participant speaks their thoughts while trying a task.
Practice problems
Work each problem on paper first, then reveal the answer to check.
Write Given/When/Then criteria for "a driver cancels a claimed shift".
Show answer
For example: "Given a claimed shift more than 24 h away, when I cancel, then it returns to the open list"; "Given less than 24 h, when I cancel, then the coordinator is alerted."
Name two WCAG 2.2 criteria that matter for a mobile-first web app.
Show answer
For example, target size (minimum) 2.5.8, focus not obscured, accessible authentication, dragging movements.
Turn "the app must be fast" into a measurable requirement.
Show answer
For example, "key pages load in under 2 s on a mid-range phone over 4G, measured in CI."
Why might a team write an anti-persona?
Show answer
To reject requests that would pull the product toward users it is not designed for.
What question does a paper prototype answer best?
Show answer
Whether the content and flow are right, before any code is written.
Lesson quiz · 5 questions
Score 60% or more to complete this lesson.
Create a free account to save your progress, take quizzes and earn a certificate.