Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CS50P Problem Set 4 - game - check50 only checks for edge case when testing for non-negative numbers in user guess. #272

Open
kguryanov opened this issue Aug 10, 2024 · 0 comments

Comments

@kguryanov
Copy link

kguryanov commented Aug 10, 2024

Preconditions

  1. 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())
  1. 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

  1. check50 only test for edge case of user guess of 0 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.

  1. 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! 

image

Proposed solution

  1. 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant