Project: a Real Login Flow Test¶
What was run¶
A real, complete test suite — 5 real test cases covering a valid login, an invalid password, an invalid
username, empty credentials, and case sensitivity — run against the local Flask app's real /login form,
combining every real technique from this level: locators, element interaction, and reading real result state.
A real, honest obstacle on the very first run¶
selenium.common.exceptions.NoSuchElementException: Message: no such element:
Unable to locate element: {"method":"css selector","selector":"[id="result"]"}
This capstone's first real run hit exactly the same real race condition this course's own build encountered
earlier: finding #result immediately after clicking submit, with zero wait, genuinely fails — the real
page hadn't finished responding yet. The real, honest, temporary fix used here:
time.sleep(0.3) # a real, deliberately temporary fix -- Level 2 does this properly
return driver.find_element(By.ID, "result").text
Real, complete test results after the fix¶
REAL test_valid_login: PASSED
REAL test_invalid_password: PASSED
REAL test_invalid_username: PASSED
REAL test_empty_credentials: PASSED
REAL test_case_sensitivity: username 'RealUser' (wrong case) -> 'Login Failed'
REAL test_case_sensitivity: PASSED
=== REAL test run complete: 5 passed, 0 failed ===
Every real test case — including the case-sensitivity check, which confirmed the real backend genuinely rejects a username with incorrect capitalization — passed against the real, running Flask app.
How It Actually Works¶
This capstone combines every real piece from this level: Lesson 3's By.ID locators
to find the form fields, Lesson 6's send_keys() and click() to fill and
submit it, and Lesson 9's .text property to read back the real result. The one real,
new wrinkle — the race condition this capstone's own first run hit — is deliberately left in this lesson's
account rather than silently fixed before anyone saw it, because it's exactly the real problem that justifies
Level 2's entire existence: time.sleep(0.3) works here, on this fast local server, but
it's a real, fragile guess, not a real guarantee, and the very next level replaces it with something that
actually is one.
Common mistakes¶
- Writing a login test that only checks the success case — this capstone's real suite covers four distinct real failure modes (wrong password, wrong username, empty fields, wrong case) specifically because a login form's real security properties live in how it handles incorrect input, not just correct input.
- Papering over a real race condition with a sleep and never revisiting it — this lesson's
time.sleep(0.3)is flagged explicitly as temporary, not presented as a real, permanent solution; a growing test suite with dozens of sleeps like this becomes both slow and unreliable in ways Level 2 exists to fix. - Not testing case sensitivity or other input-normalization edge cases — this lesson's real
test_case_sensitivitycheck could just as easily have found a real bug (if the backend normalized usernames) as confirmed correct behavior; either outcome is worth knowing for certain.
Exercise¶
Add a sixth real test case checking what happens when the username or password contains real leading/trailing
whitespace (for example, " realuser " instead of "realuser"). Run it against the real app and find out
whether the real backend trims whitespace before comparing, or treats it as a genuinely different, incorrect
username.