tiny-computer-agent / tests /test_diff.py
hkblockchaintechnology's picture
2.0: skills, approval gates, a resumable task runner, structural verification
e2f048d verified
Raw History Blame Contribute Delete
3.62 kB
"""A change you cannot measure is a change you cannot verify."""
from tiny_computer_agent import ChangeVerifier, Delta, Element, Observation, diff, element_key
def frame(elements, text=""):
return Observation(index=0, frame="frame", elements=tuple(elements), text=text)
def button(label, x=10, y=10, width=60, height=20, kind="button"):
return Element(label, kind=kind, x=x, y=y, width=width, height=height)
def test_nothing_changed_is_measured_rather_than_guessed():
picture = frame([button("Save", x=100)])
delta = diff(picture, picture)
assert delta.empty and not delta.changed
assert delta.summary() == "no change"
assert isinstance(delta, Delta)
def test_a_dialog_closing_is_a_removed_element_not_a_missing_string():
"""The whole point: verification without depending on the dialog's own words."""
before = frame([button("Save As"), button("Cancel", x=80)])
after = frame([button("Save As")])
delta = diff(before, after)
assert delta.closed and not delta.opened
assert [e.label for e in delta.removed] == ["Cancel"]
assert delta.matches(disappeared=["cancel"])
assert not delta.matches(appeared=["cancel"])
def test_a_menu_opening_is_an_added_element():
delta = diff(frame([button("File")]), frame([button("File"), button("Save As", y=60)]))
assert delta.opened and not delta.closed
assert [e.label for e in delta.added] == ["Save As"]
assert delta.matches(appeared=["save as"])
def test_a_redraw_is_not_movement_and_a_real_move_is():
still = diff(frame([button("Save", x=100)]), frame([button("Save", x=101)]))
assert still.empty, "a one-pixel re-render is not a change"
moved = diff(frame([button("Save", x=100)]), frame([button("Save", x=400)]))
assert moved.moved and moved.settled, "nothing appeared or vanished: it moved"
assert not moved.changed is False
assert moved.to_dict()["moved"] == ["Save"]
def test_labels_are_compared_the_way_the_index_compares_them():
"""OCR drops spaces and models add punctuation, so identity is the alphanumeric core."""
before = frame([button("Save As")])
after = frame([button("SaveAs.")])
delta = diff(before, after)
assert delta.empty, "the same label, differently spelled, is the same element"
assert element_key(button("Save As")) == element_key(button("SaveAs."))
def test_added_and_removed_are_told_apart_when_counts_differ():
before = frame([button("Row 1"), button("Row 2")])
after = frame([button("Row 2"), button("Row 3"), button("Row 4")])
delta = diff(before, after)
assert sorted(e.label for e in delta.added) == ["Row 3", "Row 4"]
assert [e.label for e in delta.removed] == ["Row 1"]
assert delta.summary().startswith("+2")
def test_the_verifier_remembers_the_previous_frame():
verify = ChangeVerifier(disappeared=["Cancel"])
with_cancel = frame([button("Save"), button("Cancel", x=200)])
without_cancel = frame([button("Save")])
assert verify(with_cancel) is False, "the first frame has nothing to compare against"
assert verify(without_cancel) is True
assert verify.last is not None and verify.last.closed, "Cancel is gone: the dialog closed"
assert verify(without_cancel) is False, "and the comparison advances with the frame"
assert verify.last is not None and verify.last.empty
def test_the_verifier_can_be_reset_between_episodes():
verify = ChangeVerifier(appeared=["Saved"])
verify(frame([button("Save")]))
verify.reset()
assert verify.previous is None and verify.last is None
assert verify(frame([button("Saved")])) is False