Skip to content
← Advanced DevOps

Practical lab guide

Lab: test an operational analysis toolkit

Run offline algorithm fixtures and explain correctness, cost, and production limits.

Documentation reviewed2026-10-01 · 4 min read · lab time varies
On this page

1. Prepare the local exercise

Save the seven preceding bites' Python listings in .local/advanced-design/ inside your MicroBank checkout, using their documented filenames. The listings are independent exercise utilities, not modifications to the application. Use Python 3.11 or later. No dependency installation or network request is required.

bash
cd .local/advanced-design
python3 --version

Create test_toolkit.py in the same directory:

python
import unittest
from bisect import bisect_left
from random import Random

from complexity import unique_in_order
from events import summarize
from graph_walk import bfs_distances, dfs_reachable
from dependency_order import dependency_order
from topk import top_k_counts
from time_search import lower_bound, interval_indices
from rate_window import SlidingWindow


class ToolkitTests(unittest.TestCase):
    def test_ordered_deduplication(self):
        self.assertEqual(unique_in_order(["b", "a", "b"]), ["b", "a"])
        self.assertEqual(unique_in_order([]), [])

    def test_deliveries_and_distinct_events(self):
        rows = [{"id": "1", "kind": "timeout"}] * 2
        self.assertEqual(summarize(rows), ({"timeout": 2}, {"timeout": 1}, 1))
        self.assertEqual(summarize([]), ({}, {}, 0))
        with self.assertRaises(ValueError):
            summarize([{"id": "", "kind": "timeout"}])
        with self.assertRaises(KeyError):
            summarize([{"id": "1"}])

    def test_cycle_does_not_loop_forever(self):
        graph = {"a": ["b", "c"], "b": ["a", "c"], "c": [], "z": []}
        self.assertEqual(bfs_distances(graph, "a"), {"a": 0, "b": 1, "c": 1})
        self.assertEqual(dfs_reachable(graph, "a"), {"a", "b", "c"})
        with self.assertRaises(ValueError):
            bfs_distances({"a": ["missing"]}, "a")

    def test_precedence_property(self):
        graph = {"db": [], "api": ["db", "db"], "check": ["api"], "docs": []}
        order = dependency_order(graph)
        self.assertEqual(set(order), set(graph))
        position = {task: i for i, task in enumerate(order)}
        self.assertTrue(all(position[p] < position[t]
                            for t, parents in graph.items() for p in parents))
        self.assertEqual(dependency_order({}), [])
        for invalid in ({"a": ["a"]}, {"a": ["b"], "b": ["a"], "c": ["b"]},
                        {"a": ["missing"]}):
            with self.subTest(invalid=invalid), self.assertRaises(ValueError):
                dependency_order(invalid)

    def test_heap_against_full_sort(self):
        rng = Random(41)
        for size in range(20):
            counts = {f"event-{i}": rng.randrange(6) for i in range(size)}
            ranked = sorted(((count, name) for name, count in counts.items()), reverse=True)
            for k in (0, 1, 3, size + 2):
                expected = [(name, count) for count, name in ranked[:k]]
                self.assertEqual(top_k_counts(counts, k), expected)
        with self.assertRaises(ValueError):
            top_k_counts({"timeout": -1}, 1)

    def test_search_against_library_and_linear_filter(self):
        rng = Random(42)
        for size in range(20):
            values = sorted(rng.randrange(10) for _ in range(size))
            for target in range(-1, 12):
                self.assertEqual(lower_bound(values, target), bisect_left(values, target))
            for start, end in ((0, 5), (3, 3), (-1, 11), (7, 9)):
                left, right = interval_indices(values, start, end)
                self.assertEqual(values[left:right], [v for v in values if start <= v < end])
        with self.assertRaises(ValueError):
            interval_indices([], 2, 1)

    def test_window_boundaries(self):
        limiter = SlidingWindow(2, 60)
        self.assertEqual([limiter.allow(t) for t in (0, 1, 2, 60, 60, 61)],
                         [True, True, False, True, False, True])
        self.assertLessEqual(len(limiter.accepted), 2)
        with self.assertRaises(ValueError):
            limiter.allow(59)
        with self.assertRaises(ValueError):
            limiter.allow(float("nan"))

    def test_independent_replicas_have_independent_limits(self):
        replicas = [SlidingWindow(2, 60), SlidingWindow(2, 60)]
        accepted = sum(replica.allow(0) for replica in replicas for _ in range(2))
        self.assertEqual(accepted, 4)  # Not a shared global limit of two.


if __name__ == "__main__":
    unittest.main()

2. Verify behavior, then change a requirement

bash
python3 -m unittest -v test_toolkit

Expected outcome: eight test methods pass. These fixtures check small local algorithms, not a running MicroBank deployment. Tests against a different implementation, such as full sorting or a linear filter, can expose mistakes that assertions copied from the optimized algorithm miss.

Choose one extension: reject conflicting duplicate-event payloads, return a shortest unweighted path as well as distance, or reverse the documented top-k tie rule. Write a failing example for the new behavior before modifying the function. Retain the existing contract tests unless the requirement intentionally changes.

3. Explain the operating boundary

Write exercise-review.md alongside the files. For each utility, state its invariant, time and space bounds, invalid-input behavior, and one deployment limitation. Explain what happens with a file larger than RAM, many distinct keys, multiple workers, or out-of-order timestamps. Streaming input does not by itself bound maps, sets, or exact quantile structures.

These algorithms analyze data or simulate behavior locally. Do not wire graph reachability to automatic remediation. If later consuming real logs, normalize and redact them first; never copy credentials or customer data into practice fixtures.

Checkpoint

Keep the Python version, actual test result, your added edge case, and the review. Use those results to record what you completed. You can now continue to the optional problem set or the system-design bites; no cluster needs to be started yet.

Read a failure productively

An import error usually means a filename or working directory differs from the setup, before any algorithm was tested. An assertion failure names a behavior to compare with the written contract. In the heap test, the full-sort oracle supplies an independent answer; in the graph test, the precedence property allows several correct orders. Do not replace either with a hardcoded output merely to get green tests.

Before moving on, explain one passing edge case without looking at the implementation. Then save a new failing example for your chosen requirement change. The optional checkpoint offers more patterns; it is not a prerequisite for the design review.

Sources

Python unittest↗. Algorithm references and input contracts are linked in the preceding seven bites. All fixtures and test cases here are newly authored for this path.

Your notes and evidence

Record observations, questions, or links to your work. Keep credentials out of your notes.

Loading saved progress…

Back up or restore this path

Progress and notes stay in this browser. A backup contains only this learning path.