LESSON 4 OF 4
Test, explain and extend your report
Independent expectations
A test should express the requirement rather than a second copy of the implementation. If you use the same incorrect <= 10 condition to create your expected results, both code paths can agree while violating “strictly below ten.” Write an explicit table of cases from the specification.
Save this as test_inventory_report.py beside the implementation and run python -m unittest -v. Do not paste these tests into the programme's command-line execution block; they are a separate consumer of its classification function.
import unittest
from inventory_report import classify_row
class ClassificationTests(unittest.TestCase):
def test_valid_boundaries(self):
cases = [("0", "REVIEW"), ("9", "REVIEW"),
("10", "OK"), ("100", "OK")]
for raw, expected in cases:
with self.subTest(raw=raw):
result = classify_row({"host": "LAB-A", "free_pct": raw})
self.assertEqual(result["status"], expected)
self.assertEqual(result["free_pct"], int(raw))
def test_invalid_values(self):
for raw in ["", "unknown", "-1", "101", "9.5", None, True]:
with self.subTest(raw=raw):
result = classify_row({"host": "LAB-A", "free_pct": raw})
self.assertEqual(result["status"], "INVALID")
self.assertIsNone(result["free_pct"])
def test_source_is_not_changed(self):
source = {"host": " LAB-A ", "free_pct": "9"}
before = source.copy()
result = classify_row(source)
self.assertEqual(source, before)
self.assertEqual(result["host"], "LAB-A")
def test_missing_identity(self):
result = classify_row({"host": " ", "free_pct": "20"})
self.assertEqual(result["status"], "INVALID")
self.assertEqual(result["reason"], "missing host")
if __name__ == "__main__":
unittest.main()
These tests cover classification, not the whole operational pipeline. You still need the file experiments from the previous chapter. Passing a pure-function test cannot establish that the command opens the intended path, handles encoding correctly or refuses an existing output file.
A useful failure investigation
When a test fails, read the expected and actual values. Identify the smallest relevant function and case. A boundary failure suggests a comparison problem; every valid row failing suggests an input-contract or parsing problem; a missing output suggests file or command-line behavior. Do not solve every failure by catching a broader exception.
Temporarily make the comparison wrong again and run the tests. The ten-percent subtest must fail. Restore the operator and rerun. A test suite that never fails under a deliberate defect provides weak evidence that it protects the intended behavior.
assert statements are helpful in small teaching examples, but Python can disable ordinary asserts when run with optimization options. The unittest assertions are explicit test methods. Production input validation should use deliberate checks and errors, rather than relying only on an assert to reject untrusted input.
Project extension A: report data quality
Add a summary file containing received row count, valid row count, invalid row count and status counts. Decide what to do if the summary filename already exists. Reconcile the totals: valid plus invalid must equal received, and the status totals must also equal received.
A complete answer preserves all five baseline rows, identifies two invalid values, and does not pretend invalid rows are healthy. Include the source filename and an observation timestamp for the report run, while explaining that this timestamp is not a device measurement timestamp. If you add source timestamps later, keep the two concepts separate.
Project extension B: configurable threshold
Allow a threshold argument with a default of ten. Define the accepted threshold range and whether it must be an integer. Pass that value into classification rather than reading a mutable global from multiple functions. Test thresholds zero, ten and one hundred, and reject an out-of-range setting before writing a report.
At threshold zero, a valid zero-percent value is OK under “strictly below threshold.” That may be mathematically consistent but operationally unhelpful. Discuss whether the business should allow zero as a configured threshold. Software correctness includes both faithful implementation and a useful requirement; a passing test cannot make a poor policy wise.
Project extension C: separate collection from remediation
Write a proposal for a later live inventory collector. Identify the source, required permissions, collection-completeness signal, source age and failure behavior. Keep remediation out of this course's report programme. An invalid field, a failed collector and a genuine low-capacity measurement require different responses.
A complete proposal does not claim that a missing host should be deleted or that every REVIEW row should trigger an automatic cleanup. It names the accountable owner and evidence needed before a change. This boundary keeps a beginner's reporting exercise from accidentally becoming an unsafe administration script.
Final acceptance record
Submit your source, test file, baseline input and report, six failure experiments and one project extension. Include the interpreter version and commands used. Explain the strict boundary, invalid-versus-zero distinction, source preservation and output-file policy in your own words.
The acceptance criteria are observable: expected baseline labels, retained invalid rows, unchanged input, correct exit status for structural failures, visible rejection of an existing output, and a deliberate defect caught by a test. Reading the solution and clicking Complete is not an independently assessed demonstration of these skills.
Suggested next study
Choose Python IT Automation if you want to reconcile datasets or Python Security Log Analysis if you want to work with timestamps and aggregation. You now have the prerequisite ideas: parsing, explicit contracts, pure functions, iteration, separate output and independent expected results. Reuse those ideas rather than treating the next script as unrelated magic.
Transfer project — changed conditions
Add negative values, free greater than total, leading/trailing whitespace and non-finite numeric strings. Python float can represent NaN/infinity, so define and test finiteness explicitly if you accept floats. Write tests for exact threshold and near-threshold values. Explain whether your use case needs decimal arithmetic, and keep that decision separate from output rounding. Submit code, test output and a short contract for accepted inputs.
Practical assessment rubric
Score each dimension 0–2: 0 = absent or materially incorrect; 1 = partly correct with an unresolved gap; 2 = correct, explicit and supported by the supplied evidence or an actual labeled lab result.
- Evidence/model: identify the relevant entities, inputs, assumptions and boundaries without inventing facts.
- Main result: derive the case-specific expected result, calculation or decision and show the intermediate reasoning.
- Failure/boundary: test the changed condition and explain why the original conclusion does or does not transfer.
- Verification: supply reproducible steps and expected/observed results; label manual traces as manual, not executed.
- Communication/safety: explain limitations, owners and a proportionate next action without unsafe or unnecessary access.
Target: at least 8/10, with no zero in main result or communication/safety. This is a local learning rubric, not an accredited certification standard. A written/manual solution demonstrates reasoning only; operational competence additionally requires the relevant executable lab in an authorized environment. The native multiple-choice score is separate and does not automatically grade this rubric.
Submission template
- My input/evidence and assumptions:
- Expected result with calculations or trace:
- My implementation/decision and justification:
- Changed-condition result:
- Observed execution, or explicitly labeled manual trace:
- Failure and recovery evidence:
- Unverified limitation and next action:
- Self-score with evidence for each dimension:
Remediation
If the main result is wrong, reconstruct the supplied case from the raw inputs before changing code or controls. If the boundary case is wrong, identify the assumption that changed and rerun both the original and changed case. If verification is missing, do not convert a prediction into an observed result. Reattempt the transfer task without copying the worked solution, then explain it to another person.
Official reference for further study
Assessment: explain your decisions
Choose an answer and write your reason before opening each explanation. Then explain why the other choices do not fit the evidence. Use missed questions to revisit the lesson. This knowledge check is only one part of assessment: complete the practical transfer project as well. It does not predict certification-exam success.
1. Which device matches the original condition?
- LAB-A only
- Both devices
- Neither device
Answer and explanation
LAB-A only — 9 < 10, but 10 < 10 is false.
2. Why return results from a function?
- To require admin access
- To separate calculation from display
- To remove all tests
Answer and explanation
To separate calculation from display — Returned values can be tested and reused independently.
3. Which test is especially useful for threshold logic?
- Only a typical value
- Only file size
- A value exactly at the boundary
Answer and explanation
A value exactly at the boundary — Equality reveals < versus <= mistakes.
4. The rule flags free capacity below 10%. A valid row has free_pct 10. Which result fits the rule?
- OK, because exactly 10 is outside the strict below-10 condition.
- REVIEW, because 10 is close to the threshold.
- INVALID, because a threshold value cannot be classified.
Answer and explanation
OK, because exactly 10 is outside the strict below-10 condition. — A strict boundary is a requirement, not a judgement about closeness. Test 9, 10 and 11 independently. A change from < to <= incorrectly flags the boundary row.
5. A CSV capacity field contains unknown. Which reporting behavior preserves the evidence?
- Replace unknown with zero so the field stays numeric.
- Mark the row invalid and retain the raw source value and reason.
- Drop the row and call the remaining population healthy.
Answer and explanation
Mark the row invalid and retain the raw source value and reason. — Unknown is not measured zero. Conversion or silent deletion creates an unsupported conclusion. The report keeps a rejected value visible so the collector and analyst can investigate it.
6. The report output already exists. What should this course program do?
- Overwrite it because the new report is likely more current.
- Append new rows without checking the schema.
- Fail clearly and preserve the existing report.
Answer and explanation
Fail clearly and preserve the existing report. — The no-overwrite contract protects evidence. Use a new output path. A preflight existence check alone can race; the exclusive file-open operation also needs to enforce the contract.
7. How many fixture rows are valid?
- Two.
- Four because every row has three strings.
- Three because unknown should become zero.
Answer and explanation
Two. — Shape alone is insufficient. C violates the positive-total rule; D cannot be parsed as the required number.
8. Should B alert?
- It cannot be calculated.
- No; its ratio is exactly 0.10.
- Yes; the rule says less than or equal.
Answer and explanation
No; its ratio is exactly 0.10. — 20/200 = 0.10 and the rule is strictly below the threshold.
9. Why add a finiteness check when accepting float input?
- Every float is necessarily a whole number.
- It replaces all other validation.
- NaN/infinity may parse numerically but violate the intended domain.
Answer and explanation
NaN/infinity may parse numerically but violate the intended domain. — Successful parsing does not imply a sensible capacity value. Finiteness and range checks are separate requirements.
Open the scored course assessment to use the existing practice-test engine. Earlier attempts remain part of your history.
YOUR NEXT STEP
Keep building your skills
No directly related CogniSkill book is mapped to this course yet. Continue with the free learning, or compare the publishing catalogue by your next goal.
Explore books by topic and goal →Sign in to save lesson completion. Reading position is separate from completion.
Practice notes — your working space
Save predictions, outputs and explanations as you work. Notes stay on this browser, not your account; people sharing this browser can access them. Avoid passwords and sensitive data. Export to keep a portable copy, or clear your notes before leaving a shared device.
How was this lesson?
Help us improve this lesson.