This lab is completed over three class meetings.
You will use GitHub Codespaces as your programming environment instead of Google Colab.
This is not a Git lab. You are not required to commit, push, create branches, or submit work through GitHub. GitHub Codespaces is being used as your browser-based programming environment.
There is nothing to submit to Canvas. Completion is recorded through daily instructor sign-offs.
| Day | Functions | Tests |
|---|---|---|
| Day 1 | day1.py |
test_1.py |
| Day 2 | day2.py |
test_2.py |
| Day 3 | day3.py |
test_3.py |
- Sign in to GitHub.
- Open the public Programming Lab 1 repository provided by your instructor.
- Click Code.
- Select Codespaces.
- Create a new Codespace.
- Wait for Visual Studio Code to load in your browser.
- Open:
day1.pytest_1.py
Write today's functions in day1.py and today's tests in test_1.py.
Develop a function named:
absolute_valueThe function must:
- take one parameter of type
float; - return the absolute value of the argument as a
float; - not use Python's predefined
absfunction.
Write multiple unit tests.
At minimum, consider:
- a positive value;
- a negative value;
- zero.
- Which inputs require the function to change the value?
- Which inputs may already have the desired value?
- Why is zero useful to test?
Develop a function named:
smallestThe function must:
- take two parameters of type
float; - return the smaller value;
- return that value when the two arguments are equal;
- not use Python's predefined
minfunction.
Your tests should include cases where:
- the first argument is smaller;
- the second argument is smaller;
- the arguments are equal.
- Why is testing only one ordering of the arguments insufficient?
- Why is the equal-values case useful to test?
Show an instructor:
- your working GitHub Codespace;
- your implementation of
absolute_value; - multiple tests for
absolute_value; - your implementation of
smallest; - multiple tests for
smallest; - all Day 1 tests running successfully.
Be prepared to explain why one of your tests represents a meaningfully different category of input.
Open:
day2.pytest_2.py
Today, begin by investigating code that does not behave according to its specification.
Do not randomly change code until the tests pass.
Use this workflow:
- Reproduce the problem.
- Predict what should happen.
- Observe what actually happens.
- Compare expected and actual execution.
- Correct the problem.
- Retest the complete test suite.
The starter code contains a function named:
doubleThe function is intended to return twice its argument.
The provided implementation contains a bug.
Run the provided tests in test_2.py.
At least one test should fail.
Before changing the code, identify:
- Which test failed?
- What value was expected?
- What value was actually returned?
- Which assertion detected the failure?
Run the failing test using the debugger.
Place a breakpoint at the beginning of the failing test and follow execution into double.
Observe:
- the value passed to the function;
- the value bound to the parameter;
- the statements executed;
- the value returned.
Determine where the program's actual behavior differs from its required behavior.
Once you understand the cause of the problem:
- correct the implementation;
- rerun the previously failing test;
- run all tests again.
- Why should the complete test suite be rerun after changing a function?
- Would one passing test prove that a function is correct for every possible input?
Develop a function named:
clampThe function takes three parameters of type float:
value
lower
upper
You may assume:
lower <= upperThe function must:
- return
lowerwhenvalueis less thanlower; - return
upperwhenvalueis greater thanupper; - return
valueotherwise.
At minimum, test:
- a value below the lower bound;
- a value between the bounds;
- a value above the upper bound;
- a value equal to the lower bound;
- a value equal to the upper bound.
- How many meaningfully different behaviors does this function have?
- Why are the exact boundary values useful tests?
- What kinds of problems might remain hidden if you tested only values between the bounds?
If a test fails, apply the same debugging process used in Task 3.
Show an instructor:
- the failure produced by the original
doubleimplementation; - the expected and actual values from the failed test;
- your ability to follow execution from the test into the function using the debugger;
- the corrected
doublefunction; - your implementation of
clamp; - tests covering the different behaviors and boundary cases of
clamp; - all Day 2 tests running successfully.
Be prepared to explain how the failed test helped you identify the problem.
Open:
day3.pytest_3.py
Today, organize the activities from the previous two days into a deliberate function-design process.
For each function:
-
State the purpose.
- What does the function compute?
- What information does it receive?
- What does it return?
-
Identify the data representation.
- What are the parameter types?
- What is the return type?
-
Name and template the function.
- Write the definition, parameters, and return type.
-
Work examples by hand and write tests.
- Determine expected results for representative inputs before completing the implementation.
-
Complete the implementation.
-
Run all tests.
- If a test fails, compare expected and actual behavior, correct the implementation, and rerun the tests.
The goal is to move from:
problem → examples → tests → implementation
rather than immediately beginning with the function body.
Develop a function named:
distanceThe function takes four parameters of type float:
x1
y1
x2
y2
These values represent two points:
(x1, y1)
(x2, y2)
The function must return the Euclidean distance between the points as a float.
Use the distance formula:
sqrt((x2 - x1)^2 + (y2 - y1)^2)
You may use sqrt from Python's math module.
Consider tests involving:
- two different points;
- the same point twice;
- negative coordinates;
- points where only one coordinate differs;
- reversing the order of the two points.
- What should the distance from a point to itself be?
- Should reversing the two points change the result?
- How could a test check that property?
Develop a function named:
triangle_perimeterThe function takes six parameters of type float:
x1
y1
x2
y2
x3
y3
These values represent three points.
The function must return the perimeter of the triangle formed by those points.
Your implementation must use the distance function from Task 5.
Do not duplicate the distance calculation inside triangle_perimeter.
At minimum, include:
- a triangle whose side lengths you can determine independently;
- a triangle located somewhere else in the coordinate system;
- another triangle with known side lengths.
- Which pairs of points form the three sides?
- What arguments should be passed to each call to
distance? - Why is using
distancepreferable to copying its implementation? - If a problem were discovered in
distance, what advantage does this design provide?
Show an instructor:
- your implementation of
distance; - multiple meaningful tests for
distance; - your implementation of
triangle_perimeter; - multiple meaningful tests for
triangle_perimeter; triangle_perimeterusingdistance;- all Day 3 tests running successfully;
- completed sign-offs for Days 1 and 2.
Be prepared to explain how you applied the design recipe to one of today's functions.
There is nothing to submit to Canvas.
Only after your instructor completes your final sign-off:
- return to your GitHub Codespaces page;
- locate the Codespace for Programming Lab 1;
- open the
...menu; - select Delete;
- confirm the deletion.
Do not delete the Codespace before receiving the final sign-off.