8Regression tests for :class:`oct.core.progress.ProgressTracker` and
9:class:`oct.core.progress.Dashboard`.
13- Verify ProgressTracker lifecycle (start, complete, fail, skip) and markers.
14- Verify Dashboard in-place updates, timer, quiet mode, and non-TTY fallback.
21 L3 — assertion details
26- All output is captured via ``io.StringIO``; no real terminal writes.
33from oct.core.progress
import Dashboard, ProgressTracker
38 kwargs.setdefault(
"stream", buf)
39 return ProgressTracker(tasks, **kwargs), buf
46 for name
in (
"A",
"B",
"C"):
47 tracker.start_task(name)
48 tracker.complete_task(name, summary=f
"{name} done")
49 output = buf.getvalue()
50 assert "[x] A A done" in output
51 assert "[x] B B done" in output
52 assert "[x] C C done" in output
56 tracker.start_task(
"X")
57 tracker.fail_task(
"X", summary=
"TIMEOUT")
58 assert "[!] X TIMEOUT" in buf.getvalue()
62 tracker.start_task(
"X")
63 tracker.skip_task(
"X", summary=
"skipped")
64 assert "[-] X skipped" in buf.getvalue()
71 with tracker.task(
"T"):
73 assert "[x] T" in buf.getvalue()
78 with tracker.task(
"T"):
79 raise ValueError(
"boom")
82 assert "[!] T" in buf.getvalue()
89 tracker.start_task(
"A")
90 tracker.complete_task(
"A", summary=
"done")
92 assert buf.getvalue() ==
""
99 tracker.start_task(
"Counter", total=1000)
105 threads = [threading.Thread(target=tick_100)
for _
in range(10)]
111 assert tracker._progress == 1000
118 tracker.start_task(
"Slow", total=0)
119 output = buf.getvalue()
120 assert "[start] Slow" in output
124 tracker.start_task(
"X", total=10)
126 assert tracker._progress == 0
133 tracker.start_task(
"A")
134 tracker.complete_task(
"A", summary=
"ok")
135 output = buf.getvalue()
136 assert "[start] A" in output
137 assert "[x] A ok" in output
138 assert "\033" not in output
145 tracker.complete_task(
"nonexistent")
146 tracker.fail_task(
"nonexistent")
147 tracker.skip_task(
"nonexistent")
148 assert buf.getvalue() ==
""
152 assert "oct health" in buf.getvalue()
156 tracker.start_task(
"A")
157 tracker.complete_task(
"A")
159 output = buf.getvalue()
160 assert "[x] A" in output
161 assert "[ ] B" in output
171 kwargs.setdefault(
"stream", buf)
172 return Dashboard(**kwargs), buf
179 db.render([
"line0",
"line1",
"line2"], tasks_total=1)
180 assert len(db._lines) == 3
184 db.render([
"aaa",
"bbb"], tasks_total=1)
185 assert buf.getvalue() ==
""
189 db.render([
"[ ] A",
"footer",
"==="], footer_line=1, tasks_total=1)
190 db.update_line(0,
"[x] A done")
193 output = buf.getvalue()
194 assert "[x] A done" in output
195 assert "===" in output
202 db.render([
"old0",
"old1",
"old2"], tasks_total=1)
203 db.update_line(1,
"new1")
204 assert db._lines[1] ==
"new1"
208 db.render([
"a",
"b"], tasks_total=1)
209 db.update_line(5,
"nope")
210 db.update_line(-1,
"nope")
211 assert db._lines == [
"a",
"b"]
218 db.render([
"a",
"b",
"c"], tasks_total=1)
220 db.update_line(0,
"changed")
223 assert buf.getvalue() ==
""
230 db.render([
"a",
"footer",
"end"], footer_line=1, tasks_total=3)
233 assert db._tasks_done == 2
237 db.render([
"a",
"footer",
"end"], footer_line=1, tasks_total=1)
238 db.set_task(
"Test suite")
239 assert db._task_name ==
"Test suite"
243 db.render([
"a",
"footer",
"end"], footer_line=1, tasks_total=1)
246 assert db._task_name
is None
253 db.render([
"header",
"footer",
"==="], footer_line=1, tasks_total=2)
257 output = buf.getvalue()
258 assert "All 2 checks completed" in output
262 db.render([
"a",
"b",
"c"], tasks_total=1)
264 assert db._timer_thread
is None
271 db.render([
"header",
"footer",
"==="], footer_line=1, tasks_total=1)
275 assert "Slow" in db._lines[1]
276 assert "elapsed" in db._lines[1]
test_basic_lifecycle(self)
test_context_manager_failure(self)
test_context_manager_success(self)
test_finish_stops_timer_thread(self)
test_finish_updates_footer(self)
test_quiet_suppresses_all_output(self)
test_non_tty_prints_final_state_on_finish(self)
test_render_stores_lines(self)
test_non_tty_no_output_on_render(self)
test_set_task_stores_name(self)
test_tasks_done_increments(self)
test_complete_task_clears_name(self)
test_footer_includes_elapsed(self)
test_update_line_changes_internal_state(self)
test_update_out_of_range_ignored(self)
test_indeterminate_mode(self)
test_tick_zero_no_advance(self)
test_unknown_task_name_ignored(self)
test_finish_clears_pending(self)
test_non_tty_simple_lines(self)
_make_dashboard(**kwargs)
_make_tracker(tasks, **kwargs)