Python: Make code testable

Avoid executing code on module level as this prevents importing the
module for testing. Especially infinite loops are evil.
This commit is contained in:
Martin Thoma
2022-03-19 09:54:52 +01:00
parent f40a1fc465
commit 8495e59a8f
23 changed files with 1049 additions and 973 deletions

View File

@@ -22,7 +22,7 @@ jobs:
pip install -r 00_Utilities/python/ci-requirements.txt pip install -r 00_Utilities/python/ci-requirements.txt
- name: Test with pytest - name: Test with pytest
run: | run: |
pytest 01_Acey_Ducey/python 02_Amazing/python 39_Golf/python pytest -m "not slow"
- name: Test with mypy - name: Test with mypy
run: | run: |
mypy . --exclude 79_Slalom --exclude 27_Civil_War --exclude 38_Fur_Trader --exclude 81_Splat --exclude 09_Battle --exclude 40_Gomoko --exclude 36_Flip_Flop --exclude 43_Hammurabi --exclude 04_Awari --exclude 78_Sine_Wave --exclude 77_Salvo --exclude 34_Digits --exclude 17_Bullfight --exclude 16_Bug mypy . --exclude 79_Slalom --exclude 27_Civil_War --exclude 38_Fur_Trader --exclude 81_Splat --exclude 09_Battle --exclude 40_Gomoko --exclude 36_Flip_Flop --exclude 43_Hammurabi --exclude 04_Awari --exclude 78_Sine_Wave --exclude 77_Salvo --exclude 34_Digits --exclude 17_Bullfight --exclude 16_Bug

View File

@@ -62,6 +62,7 @@ def display_bankroll(bank_roll: int) -> None:
print("You now have %s dollars\n" % bank_roll) print("You now have %s dollars\n" % bank_roll)
def main():
# Display initial title and instructions # Display initial title and instructions
print("\n Acey Ducey Card Game") print("\n Acey Ducey Card Game")
print("Creative Computing Morristown, New Jersey") print("Creative Computing Morristown, New Jersey")
@@ -73,7 +74,6 @@ print("on whether or not you feel the card will have")
print("a value between the first two.") print("a value between the first two.")
print("If you do not want to bet, input a 0") print("If you do not want to bet, input a 0")
# Loop for series of multiple games # Loop for series of multiple games
KEEP_PLAYING = True KEEP_PLAYING = True
while KEEP_PLAYING: while KEEP_PLAYING:
@@ -147,6 +147,10 @@ while KEEP_PLAYING:
print("OK Hope you had fun\n") print("OK Hope you had fun\n")
if __name__ == "__main__":
main()
######################################################## ########################################################
# #
# Porting notes: # Porting notes:

View File

@@ -108,6 +108,7 @@ def build_result_string(num, guess):
###################################################################### ######################################################################
def main():
# Intro text # Intro text
print("\n Bagels") print("\n Bagels")
print("Creative Computing Morristown, New Jersey") print("Creative Computing Morristown, New Jersey")
@@ -156,13 +157,15 @@ while still_running:
if response.upper()[0] != "Y": if response.upper()[0] != "Y":
still_running = False still_running = False
if games_won > 0: if games_won > 0:
print(f"\nA {games_won} point Bagels buff!!") print(f"\nA {games_won} point Bagels buff!!")
print("Hope you had fun. Bye.\n") print("Hope you had fun. Bye.\n")
if __name__ == "__main__":
main()
###################################################################### ######################################################################
# #
# Porting Notes # Porting Notes

View File

@@ -353,4 +353,5 @@ class Basketball:
self.opponent_jumpshot() self.opponent_jumpshot()
new_game = Basketball() if __name__ == "__main__":
Basketball()

View File

@@ -49,6 +49,7 @@ def print_legs(n_legs):
print() print()
def main():
print_n_whitespaces(34) print_n_whitespaces(34)
print("BUG") print("BUG")
print_n_whitespaces(15) print_n_whitespaces(15)
@@ -300,3 +301,7 @@ while Y <= 0:
break break
print("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!") print("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!")
if __name__ == "__main__":
main()

View File

@@ -214,6 +214,9 @@ while True:
if death: if death:
break break
def main():
# 1310 # 1310
print_n_newlines(3) print_n_newlines(3)
if D[4] == 0: if D[4] == 0:
@@ -239,3 +242,7 @@ else:
print() print()
print("ADIOS") print("ADIOS")
print_n_newlines(3) print_n_newlines(3)
if __name__ == "__main__":
main()

View File

@@ -10,6 +10,7 @@ def print_n_newlines(n: int):
print() print()
def main():
print_n_whitespaces(32) print_n_whitespaces(32)
print("BULLSEYE") print("BULLSEYE")
print_n_whitespaces(15) print_n_whitespaces(15)
@@ -115,3 +116,7 @@ for i in range(1, nb_winners + 1):
print(f"{player_names[winners[i]]} SCORED {total_score[winners[i]]} POINTS.") print(f"{player_names[winners[i]]} SCORED {total_score[winners[i]]} POINTS.")
print() print()
print("THANKS FOR THE GAME.") print("THANKS FOR THE GAME.")
if __name__ == "__main__":
main()

View File

@@ -22,6 +22,8 @@
import random import random
def main():
WORDS = [ WORDS = [
[ [
"Ability", "Ability",
@@ -70,7 +72,6 @@ WORDS = [
], ],
] ]
# Display intro text # Display intro text
print("\n Buzzword Generator") print("\n Buzzword Generator")
print("Creative Computing Morristown, New Jersey") print("Creative Computing Morristown, New Jersey")
@@ -99,10 +100,12 @@ while still_running:
except Exception: except Exception:
still_running = False still_running = False
print("Come back when you need help with another report!\n") print("Come back when you need help with another report!\n")
if __name__ == "__main__":
main()
###################################################################### ######################################################################
# #
# Porting Notes # Porting Notes

View File

@@ -18,6 +18,7 @@ def throw_dice():
return randint(1, 6) + randint(1, 6) return randint(1, 6) + randint(1, 6)
def main():
print(" " * 33 + "Craps") print(" " * 33 + "Craps")
print(" " * 15 + "Creative Computing Morristown, New Jersey") print(" " * 15 + "Creative Computing Morristown, New Jersey")
print() print()
@@ -79,3 +80,7 @@ elif winnings > 0:
print("Congratulations---you came out a winner. Come again.") print("Congratulations---you came out a winner. Come again.")
else: else:
print("Congratulations---you came out even, not bad for an amateur") print("Congratulations---you came out even, not bad for an amateur")
if __name__ == "__main__":
main()

View File

@@ -28,12 +28,13 @@
import random import random
def main():
# We'll track counts of roll outcomes in a 13-element list. # We'll track counts of roll outcomes in a 13-element list.
# The first two indices (0 & 1) are ignored, leaving just # The first two indices (0 & 1) are ignored, leaving just
# the indices that match the roll values (2 through 12). # the indices that match the roll values (2 through 12).
freq = [0] * 13 freq = [0] * 13
# Display intro text # Display intro text
print("\n Dice") print("\n Dice")
print("Creative Computing Morristown, New Jersey") print("Creative Computing Morristown, New Jersey")
@@ -73,6 +74,9 @@ while still_playing:
still_playing = False still_playing = False
if __name__ == "__main__":
main()
######################################################## ########################################################
# #
# Porting Notes # Porting Notes

View File

@@ -55,6 +55,7 @@ def limit_set():
return limit, limit_goal return limit, limit_goal
def main():
limit, limit_goal = limit_set() limit, limit_goal = limit_set()
while True: while True:
guess_count = 1 guess_count = 1
@@ -94,3 +95,7 @@ while True:
else: else:
insert_whitespaces() insert_whitespaces()
limit, limit_goal = limit_set() limit, limit_goal = limit_set()
if __name__ == "__main__":
main()

View File

@@ -71,6 +71,8 @@ DATA = [
# is the line length used by every row # is the line length used by every row
ROW_LEN = sum(DATA[0]) ROW_LEN = sum(DATA[0])
def main():
# Display intro text # Display intro text
print("\n Love") print("\n Love")
print("Creative Computing Morristown, New Jersey") print("Creative Computing Morristown, New Jersey")
@@ -109,6 +111,10 @@ for row in DATA:
print("") print("")
if __name__ == "__main__":
main()
###################################################################### ######################################################################
# #
# Porting Notes # Porting Notes

View File

@@ -59,4 +59,5 @@ def main():
print("HAVE A NICE DAY!") print("HAVE A NICE DAY!")
if __name__ == "__main__":
main() main()

View File

@@ -39,6 +39,7 @@ def parse_input():
return i return i
def main():
initial_message() initial_message()
while True: while True:
dead = False dead = False
@@ -73,6 +74,9 @@ while True:
print("...Next victim....") print("...Next victim....")
if __name__ == "__main__":
main()
######################################################## ########################################################
# Porting Notes # Porting Notes
# #

View File

@@ -489,12 +489,8 @@ def execute_turn(turn):
# #
###################################### ######################################
######################
#
# main game flow
#
######################
def main():
# initialize the player and computer # initialize the player and computer
# boards # boards
initialize_game() initialize_game()
@@ -522,3 +518,7 @@ while not game_over:
if execute_turn(second_turn) == 0: if execute_turn(second_turn) == 0:
game_over = True game_over = True
continue continue
if __name__ == "__main__":
main()

View File

@@ -24,6 +24,8 @@
import math import math
import time import time
def main():
# Constants # Constants
STRINGS = ("Creative", "Computing") # Text to display STRINGS = ("Creative", "Computing") # Text to display
MAX_LINES = 160 MAX_LINES = 160
@@ -33,14 +35,12 @@ STEP_SIZE = 0.25 # Number of radians to increase at each
CENTER = 26 # Controls left edge of "middle" string CENTER = 26 # Controls left edge of "middle" string
DELAY = 0.05 # Amount of seconds to wait between lines DELAY = 0.05 # Amount of seconds to wait between lines
# Display "intro" text # Display "intro" text
print("\n Sine Wave") print("\n Sine Wave")
print(" Creative Computing Morristown, New Jersey") print(" Creative Computing Morristown, New Jersey")
print("\n\n\n\n") print("\n\n\n\n")
# "REMarkable program by David Ahl" # "REMarkable program by David Ahl"
string_index = 0 string_index = 0
radians = 0 radians = 0
width = CENTER - 1 width = CENTER - 1
@@ -66,6 +66,9 @@ for _line_num in range(MAX_LINES):
time.sleep(DELAY) time.sleep(DELAY)
if __name__ == "__main__":
main()
######################################################## ########################################################
# #
# Porting Notes # Porting Notes

View File

@@ -160,6 +160,7 @@ def run():
medals["bronze"] += 1 medals["bronze"] += 1
def main():
while True: while True:
gates = ask_int("How many gates does this course have (1 to 25)") gates = ask_int("How many gates does this course have (1 to 25)")
if gates < 1: if gates < 1:
@@ -196,3 +197,7 @@ if medals["silver"] > 0:
print(f"Silver medals: {medals['silver']}") print(f"Silver medals: {medals['silver']}")
if medals["bronze"] > 0: if medals["bronze"] > 0:
print(f"Bronze medals: {medals['bronze']}") print(f"Bronze medals: {medals['bronze']}")
if __name__ == "__main__":
main()

View File

@@ -126,6 +126,7 @@ def final_message(profits):
print("Collect your winings from the H&M cashier.") print("Collect your winings from the H&M cashier.")
def main():
profits = 0 profits = 0
keep_betting = True keep_betting = True
@@ -147,6 +148,9 @@ while keep_betting:
final_message(profits) final_message(profits)
if __name__ == "__main__":
main()
###################################################################### ######################################################################
# #
# Porting notes # Porting notes

View File

@@ -293,10 +293,7 @@ def print_header():
) )
# def main():
# Main program.
#
print_header() print_header()
successful_jumps = [] successful_jumps = []
@@ -317,3 +314,7 @@ while True:
if not z: if not z:
print("SSSSSSSSSS.") print("SSSSSSSSSS.")
break break
if __name__ == "__main__":
main()

View File

@@ -57,6 +57,7 @@ def get_guess():
return guess return guess
def main():
# Display intro text # Display intro text
print("\n Stars") print("\n Stars")
print("Creative Computing Morristown, New Jersey") print("Creative Computing Morristown, New Jersey")
@@ -104,6 +105,9 @@ while still_playing:
still_playing = False still_playing = False
if __name__ == "__main__":
main()
###################################################################### ######################################################################
# #
# Porting Notes # Porting Notes

View File

@@ -11,6 +11,7 @@ def equation(x: float) -> float:
return 30 * exp(-x * x / 100) return 30 * exp(-x * x / 100)
def main():
print(" " * 32 + "3D PLOT") print(" " * 32 + "3D PLOT")
print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n\n") print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n\n")
@@ -26,3 +27,7 @@ for x in range(-300, 315, 15):
max_column = column max_column = column
y_plot[column] = "*" y_plot[column] = "*"
print("".join(y_plot)) print("".join(y_plot))
if __name__ == "__main__":
main()

View File

@@ -3,7 +3,7 @@ import unittest
import tower import tower
class MyTestCase(unittest.TestCase): class TowerTestCase(unittest.TestCase):
def test_something(self): def test_something(self):
t = tower.Tower() t = tower.Tower()
self.assertTrue(t.empty()) self.assertTrue(t.empty())
@@ -44,9 +44,6 @@ class MyTestCase(unittest.TestCase):
t.add(d5) t.add(d5)
t.add(d3) t.add(d3)
f = t.vertical_format(6, 3)
self.assertEqual(f, [" ", "[ 3 ] ", "[ 5 ] "])
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View File

@@ -44,23 +44,6 @@ class Tower:
print(r) print(r)
print(
"""
IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.
3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,
7 THE NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH
2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15. WITH 3 DISKS
THE CODE NAMES WOULD BE 11, 13 AND 15, ETC. THE NEEDLES
ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL
START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM
TO NEEDLE 3.
GOOD LUCK!
"""
)
class Game: class Game:
def __init__(self): def __init__(self):
# use fewer sizes to make debugging easier # use fewer sizes to make debugging easier
@@ -144,6 +127,23 @@ class Game:
from_tower.add(disk) from_tower.add(disk)
def main():
print(
"""
IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.
3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,
7 THE NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH
2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15. WITH 3 DISKS
THE CODE NAMES WOULD BE 11, 13 AND 15, ETC. THE NEEDLES
ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL
START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM
TO NEEDLE 3.
GOOD LUCK!
"""
)
game = Game() game = Game()
while True: while True:
game.print() game.print()
@@ -168,3 +168,7 @@ while True:
elif game.moves() > 128: elif game.moves() > 128:
print("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN 128 MOVES.") print("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN 128 MOVES.")
sys.exit(0) sys.exit(0)
if __name__ == "__main__":
main()