So far you’ve run a program and compared its output with what you expected. Let’s have Python help with that comparison. A check describes an expected result and tells you when the program doesn’t match it. That makes it easier to try a new idea without losing track of what already worked.
Checking an expected result¶
assert condition continues if the condition is true and raises AssertionError
if it is false. Use it to describe expected behavior in exercises and tests.
For example, assert result == 0.0 means that this particular result must be zero.
Keep the motor’s disabled rule in the ordinary if statements that choose its
output. An assertion checks that the rule works; it doesn’t replace the rule.
Why keep those separate?
Python can be started with assertions turned off. They’re useful while developing and testing, but the program must still make safe decisions without them.
Choose cases before writing the solution: a normal request, the boundary, and a case that must be rejected. Our model accepts motor requests from -1 to 1. Values above 1 should be limited to 1; values below -1 should become -1. This is called clamping. We’ll write it with conditionals you already understand.
Read it before running it¶
Put this worked example in student-work/foundations/checking_behavior.py.
Read it once and write down what you think it prints. Then save and run
python student-work/foundations/checking_behavior.py using your environment’s Python.
def clamp_request(request):
if request > 1.0:
return 1.0
if request < -1.0:
return -1.0
return request
assert clamp_request(0.4) == 0.4
assert clamp_request(2.0) == 1.0
assert clamp_request(-2.0) == -1.0
assert clamp_request(1.0) == 1.0
print("All request checks passed.")
If all assertions hold, you see the final message. Change the first comparison
to request < 1.0 and rerun. Which claim catches the mistake? Read its source line,
explain the failure, then repair it. A passing check only covers what you actually
checked; one successful request does not prove every input is correct.
Try it yourself¶
A place to start
Keep the decision order visible: disable, block unwanted forward acquisition, then bound an allowed request.
A more specific hint
Reuse clamp_request in intake_output instead of repeating its comparisons.
Solution to Exercise 1
Check both high and low bounds. A held piece must not prevent reverse release, and disabling must override either direction.
def clamp_request(request):
if request > 1.0:
return 1.0
if request < -1.0:
return -1.0
return request
def intake_output(request, enabled, has_piece):
if not enabled or (has_piece and request > 0):
return 0.0
return clamp_request(request)
assert intake_output(0.5, True, False) == 0.5
assert intake_output(0.5, True, True) == 0.0
assert intake_output(-0.5, True, True) == -0.5
assert intake_output(0.5, False, False) == 0.0
assert intake_output(2.0, True, False) == 1.0
assert intake_output(-2.0, True, True) == -1.0
print("Intake checks passed.")
Before moving on¶
Choose a value exactly at an output limit, then one just beyond it. Write down the expected result for each before running. If either result surprises you, trace the comparisons and note where your prediction went wrong.
Show a deliberate broken rule that your checks detect, then restore it. Explain one behavior your current checks do not cover.