CS50P Problem Set 4 - game - check50 only checks for edge case when testing for non-negative numbers in user guess.
Opened this issue · 0 comments
kguryanov commented
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