diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4342f4c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "ET: Debug Python (unittest)", + "type": "debugpy", + "request": "launch", + "program": "-m", + "args": ["unittest", "${file}"], + "console": "integratedTerminal", + "justMyCode": true + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 5a90e20..5f1bbc6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -113,5 +113,8 @@ }, // Enable/disable update table of contents on save - "markdown.extension.toc.updateOnSave": false + "markdown.extension.toc.updateOnSave": false, + "python.testing.unittestArgs": ["-v", "-s", ".", "-p", "test_*.py"], + "python.testing.pytestEnabled": false, + "python.testing.unittestEnabled": true } diff --git a/2_predictive_stepping/lesson_plan.md b/2_predictive_stepping/lesson_plan.md index 9bbef14..dcc5ce8 100644 --- a/2_predictive_stepping/lesson_plan.md +++ b/2_predictive_stepping/lesson_plan.md @@ -167,9 +167,18 @@ _(live demo)_ class: middle, center -## Predictive Stepping +## Predictive Stepping: _demo_ -### _demo_ +Before stepping: + +- Which line will execute next? +- What will happen? +- What will will change in memory? + +After stepping: + +- Were your predictions correct? +- if not, what did you not understand? --- diff --git a/3_documenting_and_testing/README.md b/3_documenting_and_testing/README.md index 14e1954..bf8587e 100644 --- a/3_documenting_and_testing/README.md +++ b/3_documenting_and_testing/README.md @@ -70,9 +70,12 @@ master all of the skills introduced in this workshop. ### Function Testing -- 🥚 You can use a sandbox file to informally explore a function's _behavior_. - 🥚 You can read and run unit tests to understand a function's _behavior_. -- 🥚 You can import a module in your console and run its doctest. -- 🥚 You can write a simple suite of unit tests with some boundary cases. +- 🥚 You can step through test cases in a debugger to understand a function's _strategy & implementation_. + - open the function and tests side-by-side + - place a breakpoint on the first line of the function + - open the VSCode debugger pane + - launch the `ET: Debug Python (unittest)` process +- 🥚 You can write a suite of unit tests with some boundary cases. - 🐣 You can write a full suite of unit tests including comprehensive boundary - cases, assertions checks, and glass box tests. + cases and assertions checks. diff --git a/3_documenting_and_testing/examples/fibonacci_list.py b/3_documenting_and_testing/examples/fibonacci_list.py index 5dc3523..050a9c1 100644 --- a/3_documenting_and_testing/examples/fibonacci_list.py +++ b/3_documenting_and_testing/examples/fibonacci_list.py @@ -61,6 +61,7 @@ def fibonacci_list(sequence_length: int) -> list[int]: # sum the previous two values and append them to the list sequence = [0, 1] - for _ in range(2, sequence_length): + while len(sequence) < sequence_length: sequence.append(sequence[-1] + sequence[-2]) + return sequence diff --git a/3_documenting_and_testing/examples/tests/test_fibonacci_list.py b/3_documenting_and_testing/examples/tests/test_fibonacci_list.py index a20d909..3a0d0bb 100644 --- a/3_documenting_and_testing/examples/tests/test_fibonacci_list.py +++ b/3_documenting_and_testing/examples/tests/test_fibonacci_list.py @@ -24,19 +24,25 @@ class TestFibLib(unittest.TestCase): def test_0(self): """It should evaluate 0 to []""" - self.assertEqual(fibonacci_list(0), []) + actual = fibonacci_list(0) # call function with test arguments + expected = [] # hand-write the expected return value + self.assertEqual(actual, expected) def test_1(self): """It should evaluate 1 to [0]""" - self.assertEqual(fibonacci_list(1), [0]) + actual = fibonacci_list(1) + expected = [0] + self.assertEqual(actual, expected) def test_2(self): """It should evaluate 2 to [0, 1]""" - self.assertEqual(fibonacci_list(2), [0, 1]) + actual = fibonacci_list(2) + self.assertEqual(actual, [0, 1]) def test_3(self): """It should evaluate 3 to [0, 1, 1]""" - self.assertEqual(fibonacci_list(3), [0, 1, 1]) + expected = [0, 1, 1] + self.assertEqual(fibonacci_list(3), expected) def test_4(self): """It should evaluate 4 to [0, 1, 1, 2]""" diff --git a/3_documenting_and_testing/exercises/mystery_1.py b/3_documenting_and_testing/exercises/mystery_1.py index 4db5d42..d04fa14 100644 --- a/3_documenting_and_testing/exercises/mystery_1.py +++ b/3_documenting_and_testing/exercises/mystery_1.py @@ -1,7 +1,2 @@ -def mystery_1(a): - b = len(a) - for c in range(b): - for d in range(0, b - c - 1): - if a[d] > a[d + 1]: - a[d], a[d + 1] = a[d + 1], a[d] - return a +def mystery_1(a,b): + return a + b diff --git a/3_documenting_and_testing/exercises/mystery_2.py b/3_documenting_and_testing/exercises/mystery_2.py index b119701..460dd64 100644 --- a/3_documenting_and_testing/exercises/mystery_2.py +++ b/3_documenting_and_testing/exercises/mystery_2.py @@ -1,7 +1,5 @@ -def mystery_2(a, b): - c = [] - while a: - if b in a[0]: - c.append(a[0]) - a = a[1:] - return c +def mystery_2(a): + if len(a) == 0: + return None + + return len(a) diff --git a/3_documenting_and_testing/exercises/mystery_3.py b/3_documenting_and_testing/exercises/mystery_3.py index c2b6c43..3e523f9 100644 --- a/3_documenting_and_testing/exercises/mystery_3.py +++ b/3_documenting_and_testing/exercises/mystery_3.py @@ -1,8 +1,7 @@ -def mystery_3(a, b=None): - if b is None: - b = [] - while a: - c = min(a) - a.remove(c) - b.append(c) - return b +def mystery_3(a, b): + if a < b: + return a + elif a > b: + return b + else: + return a + b diff --git a/3_documenting_and_testing/exercises/mystery_4.py b/3_documenting_and_testing/exercises/mystery_4.py index 3e34b73..573fcf1 100644 --- a/3_documenting_and_testing/exercises/mystery_4.py +++ b/3_documenting_and_testing/exercises/mystery_4.py @@ -1,6 +1,9 @@ -def mystery_4(a, b): - c = [] - for d in a: - if b in d: - c.append(d) - return c +def mystery_4(a): + b = [] + + c = 0 + while len(b) < a: + b.append(c) + c = c + 1 + + return b diff --git a/3_documenting_and_testing/exercises/mystery_5.py b/3_documenting_and_testing/exercises/mystery_5.py new file mode 100644 index 0000000..58badfe --- /dev/null +++ b/3_documenting_and_testing/exercises/mystery_5.py @@ -0,0 +1,8 @@ +def mystery_5(a, b=None): + if b is None: + b = [] + while a: + c = min(a) + a.remove(c) + b.append(c) + return b diff --git a/3_documenting_and_testing/exercises/mystery_6.py b/3_documenting_and_testing/exercises/mystery_6.py new file mode 100644 index 0000000..0b57af7 --- /dev/null +++ b/3_documenting_and_testing/exercises/mystery_6.py @@ -0,0 +1,10 @@ +def mystery_6(a, b): + if a == 0: + return [] + + c = [] + while len(c) < a: + c.append(b) + b = b + 1 + + return c diff --git a/3_documenting_and_testing/exercises/mystery_7.py b/3_documenting_and_testing/exercises/mystery_7.py new file mode 100644 index 0000000..ef13d88 --- /dev/null +++ b/3_documenting_and_testing/exercises/mystery_7.py @@ -0,0 +1,6 @@ +def mystery_7(a, b): + c = [] + for d in a: + if b in d: + c.append(d) + return c diff --git a/3_documenting_and_testing/exercises/mystery_8.py b/3_documenting_and_testing/exercises/mystery_8.py new file mode 100644 index 0000000..aff58ac --- /dev/null +++ b/3_documenting_and_testing/exercises/mystery_8.py @@ -0,0 +1,7 @@ +def mystery_8(a, b): + c = [] + while a: + if b in a[0]: + c.append(a[0]) + a = a[1:] + return c diff --git a/3_documenting_and_testing/exercises/mystery_9.py b/3_documenting_and_testing/exercises/mystery_9.py new file mode 100644 index 0000000..9334577 --- /dev/null +++ b/3_documenting_and_testing/exercises/mystery_9.py @@ -0,0 +1,7 @@ +def mystery_9(a): + b = len(a) + for c in range(b): + for d in range(0, b - c - 1): + if a[d] > a[d + 1]: + a[d], a[d + 1] = a[d + 1], a[d] + return a diff --git a/3_documenting_and_testing/exercises/tests/test_mystery_1.py b/3_documenting_and_testing/exercises/tests/test_mystery_1.py index d65c16c..7a5116a 100644 --- a/3_documenting_and_testing/exercises/tests/test_mystery_1.py +++ b/3_documenting_and_testing/exercises/tests/test_mystery_1.py @@ -1,5 +1,6 @@ import unittest +from ..mystery_1 import mystery_1 class TestMystery1(unittest.TestCase): """ """ diff --git a/3_documenting_and_testing/exercises/tests/test_mystery_2.py b/3_documenting_and_testing/exercises/tests/test_mystery_2.py index fdc8ed9..e7a83d6 100644 --- a/3_documenting_and_testing/exercises/tests/test_mystery_2.py +++ b/3_documenting_and_testing/exercises/tests/test_mystery_2.py @@ -1,5 +1,6 @@ import unittest +from ..mystery_2 import mystery_2 class TestMystery2(unittest.TestCase): """ """ diff --git a/3_documenting_and_testing/exercises/tests/test_mystery_3.py b/3_documenting_and_testing/exercises/tests/test_mystery_3.py index 60cbbf8..ad283dd 100644 --- a/3_documenting_and_testing/exercises/tests/test_mystery_3.py +++ b/3_documenting_and_testing/exercises/tests/test_mystery_3.py @@ -1,5 +1,6 @@ import unittest +from ..mystery_3 import mystery_3 class TestMystery3(unittest.TestCase): """ """ diff --git a/3_documenting_and_testing/exercises/tests/test_mystery_4.py b/3_documenting_and_testing/exercises/tests/test_mystery_4.py index b39536d..80b5426 100644 --- a/3_documenting_and_testing/exercises/tests/test_mystery_4.py +++ b/3_documenting_and_testing/exercises/tests/test_mystery_4.py @@ -1,5 +1,6 @@ import unittest +from ..mystery_4 import mystery_4 class TestMystery4(unittest.TestCase): """ """ diff --git a/3_documenting_and_testing/exercises/tests/test_mystery_5.py b/3_documenting_and_testing/exercises/tests/test_mystery_5.py new file mode 100644 index 0000000..5251f12 --- /dev/null +++ b/3_documenting_and_testing/exercises/tests/test_mystery_5.py @@ -0,0 +1,6 @@ +import unittest + +from ..mystery_5 import mystery_5 + +class TestMystery5(unittest.TestCase): + """ """ diff --git a/3_documenting_and_testing/exercises/tests/test_mystery_6.py b/3_documenting_and_testing/exercises/tests/test_mystery_6.py new file mode 100644 index 0000000..315bee1 --- /dev/null +++ b/3_documenting_and_testing/exercises/tests/test_mystery_6.py @@ -0,0 +1,6 @@ +import unittest + +from ..mystery_6 import mystery_6 + +class TestMystery6(unittest.TestCase): + """ """ diff --git a/3_documenting_and_testing/exercises/tests/test_mystery_7.py b/3_documenting_and_testing/exercises/tests/test_mystery_7.py new file mode 100644 index 0000000..f8307bf --- /dev/null +++ b/3_documenting_and_testing/exercises/tests/test_mystery_7.py @@ -0,0 +1,6 @@ +import unittest + +from ..mystery_7 import mystery_7 + +class TestMystery7(unittest.TestCase): + """ """ diff --git a/3_documenting_and_testing/exercises/tests/test_mystery_8.py b/3_documenting_and_testing/exercises/tests/test_mystery_8.py new file mode 100644 index 0000000..21e8d28 --- /dev/null +++ b/3_documenting_and_testing/exercises/tests/test_mystery_8.py @@ -0,0 +1,6 @@ +import unittest + +from ..mystery_8 import mystery_8 + +class TestMystery8(unittest.TestCase): + """ """ diff --git a/3_documenting_and_testing/exercises/tests/test_mystery_9.py b/3_documenting_and_testing/exercises/tests/test_mystery_9.py new file mode 100644 index 0000000..b417d05 --- /dev/null +++ b/3_documenting_and_testing/exercises/tests/test_mystery_9.py @@ -0,0 +1,6 @@ +import unittest + +from ..mystery_9 import mystery_9 + +class TestMystery9(unittest.TestCase): + """ """ diff --git a/3_documenting_and_testing/lesson_plan.md b/3_documenting_and_testing/lesson_plan.md index c3587e0..e111512 100644 --- a/3_documenting_and_testing/lesson_plan.md +++ b/3_documenting_and_testing/lesson_plan.md @@ -57,7 +57,7 @@ class: middle class: middle -## Behavior, Strategy, Implementation +## [Behavior, Strategy, Implementation](./behavior_strategy_implementation.md) - Naming things! @@ -207,18 +207,28 @@ class: middle ## Code Review: _demo_ -- Open the [code review checklist](./code_review_checklist.md) and work from top to bottom +- **Open the [code review checklist](./code_review_checklist.md) and work from top to bottom** -- Run tests: `$ python -m unittest path/to/tests/test_file.py` +_Rely on code quality automations_ -- Print the docstring: `$ python -m pydoc path/to/file.py` +**Print the docstring**: `$ python -m pydoc path/to/file.py` -- Run the doctests: `$ python -m doctest -v path/to/file.py` - -- Check linting: - - with VSCode extensions - - `$ ruff check ./path/to/file.py` - - `$ pylint ./path/to/file.py` +**Run the doctests**: `$ python -m doctest -v path/to/file.py` + +**Run the unit tests**: `$ python -m unittest path/to/tests/test_file.py` + +**Step through the tests in the debugger**: + +- open the function and tests side-by-side +- place a breakpoint in the first line of the function +- open the VSCode debugger pane +- start `ET: Debug Python (unittest)` + +**Lint the code**: + +- _with VSCode extensions_ +- `$ ruff check ./path/to/file.py` +- `$ pylint ./path/to/file.py` --- @@ -248,13 +258,7 @@ class: middle, center class: middle, center -## Learnings + Discussion - ---- - -class: middle, center - -## Q & A +## Discussion, Q & A --- diff --git a/3_documenting_and_testing/prep_work.md b/3_documenting_and_testing/prep_work.md index 0467757..72b36ca 100644 --- a/3_documenting_and_testing/prep_work.md +++ b/3_documenting_and_testing/prep_work.md @@ -1,16 +1,23 @@ # Prep Work +Familiarize yourself with these resources for understanding and discussing code quality: + +- Read through [Behavior, Strategy, Implementation](./behavior_strategy_implementation.md) +- Read through the [Code Review Checklist](./code_review_checklist.md) + +Study and run the [`/examples`](./examples/). Practice using these _code quality automations_ with `fibonacci_list.py` and `tests/test_fibonacci.py`: + +- print the docstring: `$ python -m pydoc path/to/file.py` +- run the doctests: `$ python -m doctest -v path/to/file.py` +- run the unit tests: `$ python -m unittest path/to/tests/test_file.py` +- stepping through unit tests following this process: + - open `fibonacci_list.py` and `tests/test_fibonacci.py` side-by-side + - place a breakpoint on the first line of the function + - open the VSCode debugger pane + - launch the `ET: Debug Python (unittest)` process + Familiarize yourself these built-in Python tools for documenting and testing: - [Docstrings](https://peps.python.org/pep-0257/) - [Doctest](https://docs.python.org/3/library/doctest.html) - [The `uittest` module](https://docs.python.org/3/library/unittest.html) - -Familiarize yourself with these resources for understanding and discussing code quality: - -- Read through [Behavior, Strategy, Implementation](./behavior_strategy_implementation.md) -- Read through the [Code Review Checklist](./code_review_checklist.md) -- Study and run the [`/examples`](./examples/). Practice using these commands with `fibonacci_list.py` and `tests/test_fibonacci.py`: - - print the docstring: `$ python -m pydoc path/to/file.py` - - run the doctests: `$ python -m doctest -v path/to/file.py` - - run the tests using `$ python -m unittest path/to/tests/test_file.py`