Ever since I learned of it, I have been enamored with the TDD concept. In an effort to expand my knowledge of both Python and AI, I am attempting to work through the following two tutorials while modifying them to fit the TDD process:
A comment on my styling: in general, I am interested in self-documenting and readable code over optimization or fancy tricks to reduce lines.
I also value vertical alignment when it adds readability to code. User matthewthorning created an excellent vertical alignment tool for VS Code. I take advantage of this tool whenever it makes sense.
I find comments that precede code to be distracting, they break my flow while reviewing. To combat this, I use "footnotes" and "endnotes". Footnotes follow the end of a logical block, while endnotes appear after the end of the current scope. For example:
self.assertEqual(actualArrayMetadata , expectedArrayMetadata) # Footnote 1
self.assertEqual(gameVariables.gameOver , False)
self.assertEqual(gameVariables.turnNumber , 1)
self.assertEqual(gameVariables.currentPlayer, 1)
# FOOTNOTES:
# 1. This duplicates test_setup_game_board. Is it possible to reuse any code?
This helps me keep my flow while reading code, as well as place long comments on specific lines without making a mess. Footnote numbering restarts after each logical block, endnote numbers restart after the end of each scope. This helps keep numbering straight if major changes are made to code, since I don't have a programatic way to add them (yet).
As always, my goal is to write clear, maintainable, useful code for myself and others. Comments and insights are always appreciated!
Here I will log the concepts I learned during this process. This log is for both myself and anyone coming by later that may be interested in my thought process.
We need a way to examine stdout in order to test a function like this:
print(f"Player {player}, make your selection (1-7):")
This Stackoverflow thread gave me some insight into the process. I was able to determine that, for my purposes, the following code is sufficient:
with patch('sys.stdout', new=StringIO()) as fakeOutput:
connect4.prompt_player(1)
self.assertEqual(fakeOutput.getvalue().strip(), expectedValue)
- What is the
with
command and how is it used? - What is the
patch
command and how it is used? - What is the line
new=StringIO())
doing? - Understand how
fakeOutput
is formatted and howgetvalue()
andstrip()
interact with it.
One of the tests needs to ensure that the game exits properly. To exit, the game calls this code:
if gameVariables.gameOver:
sys.exit(0)
For a while, I wasn't sure if I could test this behavior; but this Stackoverflow thread helped me nail down the following test:
with self.assertRaises(SystemExit):
connect4.game_loop_step(gameVariables)
- Understand the
with
command and how it's used