problems
problems copied to clipboard
CS50P Problem Set 4 - game - check50 only checks for edge case when testing for non-negative numbers in user guess.
Preconditions
- Have a
game.py
, which allows negative guesses from user:
import random
from typing import Sequence
CONST_USER_PROMPT_LEVEL = "Level: "
CONST_USER_PROMPT_GUESS = "Guess: "
CONST_GUESS_TOO_SMALL = "Too small! "
CONST_GUESS_TOO_LARGE = "Too large! "
CONST_GUESS_RIGHT = "Just right! "
def main(argv: Sequence | None = None) -> int:
while True:
try:
level = int(input(CONST_USER_PROMPT_LEVEL))
if level > 0:
break
except ValueError:
continue
target = random.randint(1, level)
try:
while True:
try:
guess = int(input(CONST_USER_PROMPT_GUESS))
except ValueError:
continue
if guess and target == guess:
print(CONST_GUESS_RIGHT)
break
elif guess and target > guess:
print(CONST_GUESS_TOO_SMALL)
continue
elif guess and target < guess:
print(CONST_GUESS_TOO_LARGE)
continue
except EOFError:
return 0
if __name__ == "__main__":
exit(main())
- Have a
test_game.py
:
from io import StringIO
import random
import pytest
from game import main, CONST_GUESS_TOO_SMALL, CONST_GUESS_RIGHT, CONST_USER_PROMPT_GUESS, CONST_USER_PROMPT_LEVEL # noqa, E501
@pytest.mark.parametrize(
"input,expected",
[
("\n".join(("10", "1", "7")), f"{CONST_USER_PROMPT_LEVEL}{CONST_USER_PROMPT_GUESS}{CONST_GUESS_TOO_SMALL}\n{CONST_USER_PROMPT_GUESS}{CONST_GUESS_RIGHT}\n"), # noqa, E501
("\n".join(("10", "0", "7")), f"{CONST_USER_PROMPT_LEVEL}{CONST_USER_PROMPT_GUESS}{CONST_USER_PROMPT_GUESS}{CONST_GUESS_RIGHT}\n"), # noqa, E501
("\n".join(("10", "-1", "7")), f"{CONST_USER_PROMPT_LEVEL}{CONST_USER_PROMPT_GUESS}{CONST_USER_PROMPT_GUESS}{CONST_GUESS_RIGHT}\n"), # noqa, E501
],
)
def test_main_strdin(input, expected, monkeypatch, capsys):
random.seed(0)
with monkeypatch.context() as m:
m.setattr("sys.stdin", StringIO(input))
main()
out, err = capsys.readouterr()
assert out == expected
Steps to reproduce
1, Run check50 cs50/problems/2022/python/game
Actual result
-
check50
only test for edge case of user guess of0
and passes.
Expected result
1, As stated in the problem statement:
Prompts the user to guess that integer. If the guess is not a positive integer, the program should prompt the user again.
-
check50
should check for actual negative values in user guess input, as the code mistake can be quite common and accept an incorrect acceptance of user guesses:
(.venv) [09:06:18] ~/.../week4/game (main)$ python game.py
Level: 1
Guess: -1
Too small!
Guess: -10
Too small!
Guess: 0
Guess: 1
Just right!
Proposed solution
- Add another test to https://github.com/cs50/problems/blob/2022/python/game/init.py:
@check50.check(test_valid_level)
def test_negative_guess():
"""game.py rejects negative guess"""
check50.run("python3 game.py").stdin("4", prompt=True).stdin("-1", prompt=True).reject() # another edge case
check50.run("python3 game.py").stdin("4", prompt=True).stdin("-10", prompt=True).reject() # base case