unit test roll die - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: unit test roll die (/thread-13903.html) |
unit test roll die - saladgg - Nov-06-2018 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() RE: unit test roll die - woooee - Nov-06-2018 Your second print is a different randint from the first one. RE: unit test roll die - stullis - Nov-06-2018 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. RE: unit test roll die - saladgg - Nov-06-2018 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 I just resolved a test on bubble sort algorithm, I am now trying merge sort. RE: unit test roll die - saladgg - Nov-06-2018 (Nov-06-2018, 11:43 AM)stullis Wrote: def integer_input(message): 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}" RE: unit test roll die - stullis - Nov-06-2018 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. |