Skip to content

Commit

Permalink
post-debugging updates, tdd prep
Browse files Browse the repository at this point in the history
  • Loading branch information
colevandersWands committed Dec 9, 2024
1 parent 36d96ba commit 09ba7c8
Show file tree
Hide file tree
Showing 38 changed files with 392 additions and 374 deletions.
Binary file added .assets/zone_of_proximal_development.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion 4_debugging/exercises/3_figure_it_out/reverse_words.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def reverse_words(text: str) -> str:
''
"""
assert isinstance(text, str), "input must be a string"

words = text.split(" ")
result = ""

Expand Down
18 changes: 10 additions & 8 deletions 4_debugging/exercises/3_figure_it_out/tests/test_reverse_words.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ class TestReverseWords(unittest.TestCase):

def test_empty_string(self):
"""It should return empty string for empty input"""
self.assertEqual(reverse_words(""), "")
self.assertEqual(reverse_words(""), "") # probably ok

def test_one_word(self):
"""It should return the same string for one word"""
# BUG: Test doesn't account for extra space bug
self.assertEqual(reverse_words("hello"), "hello")
self.assertEqual(reverse_words("hello"), "hello") # probably ok

def test_two_words(self):
"""It should reverse two words"""
# BUG: Test expects wrong output format
self.assertEqual(reverse_words("hello world"), "world,hello")
self.assertEqual(reverse_words("hello world"), "world hello") # probably ok

def test_multiple_spaces(self):
"""It should handle multiple spaces"""
self.assertEqual(reverse_words("hello world"), "world hello")
def test_two_spaces(self):
"""It should handle two spaces"""
self.assertEqual(reverse_words("hello world"), "world hello") # probably ok

def test_three_spaces(self):
"""It should handle three spaces"""
self.assertEqual(reverse_words("hello world"), "world hello") # probably ok

# write more tests!
30 changes: 30 additions & 0 deletions 4_debugging/lesson_plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class: middle

- **Learning Objectives**

- **Zone of Proximal Development (_ZPD_)**

- **Errors vs. Bugs**

- **Avoiding Bugs**
Expand All @@ -38,6 +40,8 @@ class: middle

## Learning Objectives

- You can use the ZPD model to choose which challenges to study

- You can describe the difference between an _error_ and a _bug_

- Remember: It's easier to avoid bugs than to fix them!
Expand All @@ -60,6 +64,32 @@ class: middle

---

class: middle, center

## Zone of Proximal Development (_ZPD_)

[![zone of proximal development](../.assets/zone_of_proximal_development.png)](https://mavink.com/explore/Zone-of-Proximal-Development-Infographic)

---

class: middle

## ZPD: _study advice_

<a href="https://mavink.com/explore/Zone-of-Proximal-Development-Infographic" target="_blanks"><img alt="zone of proximal development" src="../.assets/zone_of_proximal_development.png" height="50%" width="50%"></a>

- You have of two separate ZPDs as you learn to program
- The **difficulty of challenges** you study
- The **debugging process** you use to study challenges

- Focus on your **debugging process**, not hard challenges
- Repeat the _entire process_ with _good practices_ on easy challenges
- Not fewer times with harder challenges with bad practices

- Focus on coding challenges in your _can do now_ zone

---

class: middle

## Errors vs. Bugs
Expand Down
20 changes: 13 additions & 7 deletions 5_tdd_with_llms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,25 @@ master all of the skills introduced in this workshop.

</details>

### TDD with LLMs
### TDD without LLMs

- 🥚 You can translate an open-ended problem into a complete docstring.
- 🥚 You can use an LLM to generate code by providing a clear prompt and code
for context.
- 🥚 You can comment, understand and review code generated by an LLM, judging if
it is correct or not.
- 🥚 You can translate an open-ended problem into a complete docstring with doctests.
- 🥚 You write unit tests for a function _before_ the function exists.
- 🥚 You can stay focused on passing one test at a time when writing a function.
- 🥚 You run your unit tests every time you make any change to your function,
making sure they still pass.
- 🥚 Every time you want to change a function's behavior, you first update the
tests before changing the function.
- 🐣 When a test fails, you can determine if it was the test or the function
that is not correct.
- 🐣 You can iteratively improve your function's implementation and still pass your test suite.

### TDD with LLMs

- 🥚 You can use an LLM to generate code by providing a clear prompt and code
for context.
- 🥚 You can comment, understand and review code generated by an LLM, judging if
it is correct or not.
- 🐣 You can collaborate with an LLM to find and fix bugs in your code.
- 🐣 You can collaborate with an LLM to _refactor_ a program's strategy or
implementation without modifying its behavior.
Expand All @@ -70,7 +76,7 @@ master all of the skills introduced in this workshop.
- 🥚 You are aware that LLMs can, despite many guardrails, produce responses
that perpetuate stereotypes and misconceptions.

### Non-Objective: Prompt Engineering
### Non-Objective: _Prompt Engineering_

This workshop does not cover _prompt engineering_: how to carefully construct
sentences and questions for the LLM to get better results. Prompt engineering is
Expand Down
16 changes: 16 additions & 0 deletions 5_tdd_with_llms/asdf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

1. **Understand the requirements** of the story, work item, or feature that you are working on.
1. **Red: Create a test and make it fail.**
1. Imagine how the new code should be called and write the test as if the code already existed.
1. Create the new production code stub. Write just enough code so that it compiles.
1. Run the test. It should fail. This is a calibration measure to ensure that your test is calling the correct code and that the code is not working by accident. This is a meaningful failure, and you expect it to fail.
1. **Green: Make the test pass by any means necessary.**
1. Write the production code to make the test pass. Keep it simple.
1. Some advocate the hard-coding of the expected return value first to verify that the test correctly detects success. This varies from practitioner to practitioner.
1. If you've written the code so that the test passes as intended, you are finished. You do not have to write more code speculatively. The test is the objective definition of "done." If new functionality is still needed, then another test is needed. Make this one test pass and continue.
1. When the test passes, you might want to run all tests up to this point to build confidence that everything else is still working.
1. **Refactor: Change the code to remove duplication in your project and to improve the design while ensuring that all tests still pass.**
1. Remove duplication caused by the addition of the new functionality.
1. Make design changes to improve the overall solution.
1. After each refactoring, rerun all the tests to ensure that they all still pass.
1. **Repeat the cycle.** Each cycle should be very short, and a typical hour should contain many Red/Green/Refactor cycles.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
Returns: a list of dicts where each dict contains the given key,
and the dicts are sorted alphabetically by the value stored in the given key
Raises: AssertionError
if the argument is not a list
if each item is not a dict
if any key in any dict is not a string
if any value in any dict is not a string
>>> f([{'a':'z'},{'b':'y'},{'a':'x'}], 'a')
[{'a':'x'},{'a','z'}]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ def f(lst, key):
Returns: a list of dicts where each dict contains the given key,
and the dicts are sorted alphabetically by the value stored in the given key
Raises: AssertionError
if the argument is not a list
if each item is not a dict
if any key in any dict is not a string
if any value in any dict is not a string
>>> f([{'a':'z'},{'b':'y'},{'a':'x'}], 'a')
[{'a':'x'},{'a','z'}]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ def f(lst, key):
Returns: a list of dicts where each dict contains the given key,
and the dicts are sorted alphabetically by the value stored in the given key
Raises: AssertionError
if the argument is not a list
if each item is not a dict
if any key in any dict is not a string
if any value in any dict is not a string
>>> f([{'a':'z'},{'b':'y'},{'a':'x'}], 'a')
[{'a':'x'},{'a','z'}]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ def f(lst, key):
Returns: a list of dicts where each dict contains the given key,
and the dicts are sorted alphabetically by the value stored in the given key
Raises: AssertionError
if the argument is not a list
if each item is not a dict
if any key in any dict is not a string
if any value in any dict is not a string
>>> f([{'a':'z'},{'b':'y'},{'a':'x'}], 'a')
[{'a':'x'},{'a','z'}]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ def f(lst, key):
Returns: a list of dicts where each dict contains the given key,
and the dicts are sorted alphabetically by the value stored in the given key
Raises: AssertionError
if the argument is not a list
if each item is not a dict
if any key in any dict is not a string
if any value in any dict is not a string
>>> f([{'a':'z'},{'b':'y'},{'a':'x'}], 'a')
[{'a':'x'},{'a','z'}]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@ def f(lst, sort_key):
Returns: a list of dicts where each dict contains the given key,
and the dicts are sorted alphabetically by the value stored in the given key
Raises: AssertionError
if the argument is not a list
if each item is not a dict
if any key in any dict is not a string
if any value in any dict is not a string
>>> f([{'a':'z'},{'b':'y'},{'a':'x'}], 'a')
[{'a':'x'},{'a','z'}]
>>> f([{'a':'z','b':'j'},{'b':'y'},{'b':'i',a':'x'}], 'b')
[{'b':'i',a':'x'},{'a':'z','b':'j'},{'b':'y'}]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,15 @@ def filter_and_sort_dictionaries(
Returns: a list of dicts where each dict contains the given key,
and the dicts are sorted alphabetically by the value stored in the given key
Raises: AssertionError
if the argument is not a list
if each item is not a dict
if any key in any dict is not a string
if any value in any dict is not a string
>>> filter_and_sort_dictionaries([{'a':'z'},{'b':'y'},{'a':'x'}], 'a')
[{'a': 'x'}, {'a': 'z'}]
>>> filter_and_sort_dictionaries([{'a':'z','b':'j'},{'b':'y'},{'b':'i','a':'x'}], 'b')
[{'b': 'i', 'a': 'x'}, {'a': 'z', 'b': 'j'}, {'b': 'y'}]
Expand Down

This file was deleted.

This file was deleted.

6 changes: 0 additions & 6 deletions 5_tdd_with_llms/examples/separated_even_odd/README.md

This file was deleted.

Loading

0 comments on commit 09ba7c8

Please sign in to comment.