triangle.py contains a function is_triangle(a, b, c)
that returns True if (a, b, c) are valid lengths of the sides of a triangle, and returns False otherwise.
triangle_test.py contains unit tests of is_triangle.
Use code coverage to find untested code and a problem with the tests.
-
Run the unit tests. They should all pass.
python3 -m unittest triangle_test.py
-
Run the tests using code coverage, then generate an html coverage report:
coverage run -m unittest triangle_test.py coverage html
-
View the report in a web browser. The file to view is
htmlcov/index.html. -
Is there any part of the code under test (
triangle.py) that was not tested?Write the Line Numbers here: [ ]
-
Modify the tests so that all lines of the code are tested.
-
Run coverage again with the
--branchoption to see if all branches of "if" statements are covered:coverage run --branch -m unittest triangle_test.py coverage html
-
What lines in the unit test code were not executed?
Write the Line Numbers: [ ] -
Normally, all the lines of test code should be executed. When some part of test code is not executed it may indicate a problem with the tests.
Explain the problem in the unit test code.Your Answer:
When done, push your work to Github, including your changes to README.
Use a loop and self.subTest() to replace redundant test code with a loop over sets of data values.
By using subTest(), if one test case fails the test will continue to execute the other test cases. If you simply use a loop without subTest(), the test will stop after the first failure.
-
Copy
triangle_test.pytoparameterized_test.py. -
For each of the 3 test methods, create a list of tuples for the test data. Then replace multiple "assert" statements with a loop (over the test data) that contains only one assert statement.
- you must put the "assert" inside a
self.subTest()block so that all test cases will be run if an assertion fails.
- you must put the "assert" inside a
-
Run the tests with code coverage and verify that the tests work as before.
-
Add
parameterized_test.pyto git and push to Github.
Example:
class TriangleTest(unittest.TestCase):
# The list of data values for your tests can be defined:
# - outside the class (global variable)
# - as a class variable (like this)
# - as a local variable inside the test method.
# Use which ever is most readable.
valid_triangles = [
(1, 1, 1),
(3, 4, 5),
(3, 4, 6),
...
]
def test_valid_triangle(self):
for a,b,c in self.valid_triangles:
with self.subTest():
message = f"sides are ({a},{b},{c})"
self.assertTrue( is_triangle(a, b, c), message)In the assertTrue statement we include a string message (2nd parameter) so that if a test fails we can see the values of a, b, c that were used.
If we do not add the string message, the output of a failed test will
only show assertTrue(is_triangle(a,b,c)) was False,
without showing that actual values of a, b, c.
This is a problem in using variables as test arguments.
On most systems you install it using "pip" or "pip3":
pip3 install coverage`For more info, see the Coverage Documentation.
Subtests in the Python documentation. Has examples.