Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
unit test roll die
#1
I am beginner at tests. I am trying to do a unit test for a roll die program.
I have tried many options and failed.

Here is the code:
from random import randint
def run():
    try:
        num = int(input('Enter an number to roll: '))
        print('result: ', randint(1, 6))
        while num != 0:
            num = int(input('Enter an number to roll your die, 0 to quit: '))
            print('result: ', randint(1, 6))
        else:
            return 'Game terminated!'
    except ValueError:
        return 'Only integers are allowed'
#run()
The program just freezes when I run the test program.
What am i doing wrong?
Here is the test part.

import pytest
import rolldie
from unittest import mock


def test_die():
    with mock.patch('builtins.input', input_value=range(1, 10)):
        assert rolldie.run() == range(1, 7)
    with mock.patch('builtins.iput', input_value=0):
        assert rolldie.run() == "Game terminated!"
    with mock.patch('builtins.iput', input_value='a'):
        assert rolldie.run() == "Only integers are allowed"

if __name__ == '__main__':
    pytest.main()
Reply
#2
Your second print is a different randint from the first one.
Reply
#3
In test_die(), mock.patch() isn't being used in your with statements. When using "with", you need to assign the operation as a variable and reference that variable in the following code body. From the documentation:

with patch('__main__.Class') as MockClass:
    instance = MockClass.return_value
    instance.method.return_value = 'foo'
    assert Class() is instance
    assert Class().method() == 'foo'
In test_die on line 8, there will be an assertion error because rolldie.run() does not return a range object. Your next two assertions would work because those strings are returned by rolldie.run(). A proper test passes a known value to a function/method and validates that the returned value matches expectations.

The third problem I see is that rolldie.run() isn't supportive of testing because of the input() calls. In fact, that's likely why it's freezing; rolldie.run() isn't receiving the inputs it wants so the program cannot move forward. Unit tests are best used with functions that return a value. I rewrote the code to support unit testing though there isn't really enough there to test:

from random import randint

def run():
    while True:
        num = integer_input("Enter an number to roll: ")

        if validate(num):
            return "Game terminated"

        roll = randint(1,6)
        print(format_result(roll))

def integer_input(message):
    while True:
        try:
            x = int(input(message))
            return x
        except ValueError:
            print("\nInvalid value, please enter an integer.")

def validate(num):
    return num == 0

def format_result(num):
    return f"Result {num}"
With that code, you could test both validate() and format_result() because they have predictable outputs with known inputs. So, you could ensure that validate returns True if a 0 is passed in or that "Result 5" is returned by format_result is a 5 is provided. However, we already know those would work since those functions merely do basic behaviors of Python.
Reply
#4
I know there's not much to test. It's part of test that I am taking. I am also a beginner in python, your approach has taught me new ways to write code that I didn't know before. Thanks @stullis Smile

I just resolved a test on bubble sort algorithm, I am now trying merge sort.
Reply
#5
(Nov-06-2018, 11:43 AM)stullis Wrote: def integer_input(message):
    while True:
        try:
            x = int(input(message))
            return x
        except ValueError:
            print("\nInvalid value, please enter an integer.")
 

had easy time testing each function, am having trouble testing this one.
the other two functions just needed a line of code to be tested like;
def test_validate():
    assert rolldie.validate(True) == 0

def test_result():
    num = 2
    assert rolldie.format_result(num) == f"Result {num}"
Reply
#6
Testing integer_input() isn't feasible because of the input() call. As written, it will not return anything without an input value and it can't be tested without a return value. On a positive note, isolating the input into its own function lets us test the rest of the code.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Unit Testing Set Up and Use RockBlok 2 380 Jan-08-2024, 07:43 PM
Last Post: deanhystad
  How to test and import a model form computer to test accuracy using Sklearn library Anldra12 6 3,068 Jul-03-2021, 10:07 AM
Last Post: Anldra12
  Dice Roll (Find out how many rolls until specified streak) DustinKlent 4 3,916 Jun-13-2021, 09:44 AM
Last Post: Gribouillis
  Writing unit test results into a text file ateestructural 3 4,654 Nov-15-2020, 05:41 PM
Last Post: ateestructural
  Help with dice roll program kraco 4 2,043 Sep-22-2020, 02:06 PM
Last Post: kraco
  How to write test cases for a init function by Unit test in python? binhduonggttn 2 3,062 Feb-24-2020, 12:06 PM
Last Post: Larz60+
  How to write test cases by Unit test for database configuration file? binhduonggttn 0 2,512 Feb-18-2020, 08:03 AM
Last Post: binhduonggttn
  Remove function and unit test ftg 5 3,480 Jan-07-2020, 03:10 PM
Last Post: ndc85430
  Odd Unit Test Behavior ichabod801 3 2,541 Jan-02-2020, 03:34 PM
Last Post: ichabod801
  Define unit of measure of a number doug2019 3 2,344 Oct-15-2019, 03:43 PM
Last Post: jefsummers

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020