Blank asset numbers, contested device claims, and honest toner forecasting
This commit is contained in:
@@ -267,3 +267,75 @@ def test_forecast_endpoint_says_so_when_zabbix_is_absent(client, db):
|
||||
assert 'not configured' in body['reason']
|
||||
assert body['cartridges'] == []
|
||||
assert body['orderlist'] == []
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Noise that used to read as cartridge changes, and bursts that used to bias
|
||||
# the rate for the life of the cartridge. Both were reported from the floor:
|
||||
# "5 changes in 90 days, that's hard to believe", and a cartridge that dropped
|
||||
# 20 percent in two days then barely moved.
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
def test_a_poll_returning_zero_is_not_a_cartridge_change():
|
||||
"""0 then a real level is an SNMP error or a calibrating printer.
|
||||
|
||||
The rise is +60, which cleared the old threshold on its own. It does not
|
||||
land near full, so it is not a swap.
|
||||
"""
|
||||
points = normalise(series([70, 60, 0, 60, 55, 50]))
|
||||
assert find_replacements(points) == []
|
||||
|
||||
|
||||
def test_a_gauge_ticking_back_up_mid_range_is_not_a_change():
|
||||
"""A coarse gauge after a reseat or a power cycle. Lands at 55, not full."""
|
||||
points = normalise(series([70, 60, 45, 55, 50, 45]))
|
||||
assert find_replacements(points) == []
|
||||
|
||||
|
||||
def test_a_real_swap_is_still_counted():
|
||||
"""Near-empty to near-full. The shape a cartridge change actually makes."""
|
||||
points = normalise(series([30, 15, 5, 100, 95, 90]))
|
||||
assert len(find_replacements(points)) == 1
|
||||
|
||||
|
||||
def test_the_run_starts_at_the_real_swap_not_at_the_noise():
|
||||
"""current_run and find_replacements must agree on what a change is.
|
||||
|
||||
They read the same predicate now; when they did not, a phantom rise reset
|
||||
the run and threw away the history the estimate needed.
|
||||
"""
|
||||
points = normalise(series([90, 0, 85, 80, 75, 70]))
|
||||
assert find_replacements(points) == []
|
||||
assert len(current_run(points)) == len(points)
|
||||
|
||||
|
||||
def test_an_early_burst_does_not_dominate_the_rate_forever():
|
||||
"""20 percent in two days, then a month of almost nothing.
|
||||
|
||||
The endpoint slope reads the burst forever: (100-75)/30 = 0.83 %/day, so
|
||||
the report keeps promising the cartridge runs out long after printing
|
||||
stopped. The median sees one fast interval among many quiet ones.
|
||||
"""
|
||||
levels = [100, 90, 80] + [80 - i * 0.2 for i in range(1, 28)]
|
||||
rate = burn_rate(normalise(series(levels)))
|
||||
assert rate is not None
|
||||
assert rate < 1.0, rate
|
||||
detail = analyse(series(levels))
|
||||
assert detail['rateunstable'] is True
|
||||
|
||||
|
||||
def test_a_steady_cartridge_is_not_flagged_unstable():
|
||||
detail = analyse(series([100, 95, 90, 85, 80, 75, 70]))
|
||||
assert detail['burnrateperday'] == 5.0
|
||||
assert detail['rateunstable'] is False
|
||||
|
||||
|
||||
def test_a_real_near_empty_reading_before_a_swap_is_kept():
|
||||
"""30, 5, 100 is a cartridge run to the end and changed - not a spike.
|
||||
|
||||
The dip filter must not eat it: the 5 does not RECOVER to 30, it jumps to
|
||||
full, which is the shape of a swap rather than of a bad poll.
|
||||
"""
|
||||
points = normalise(series([40, 30, 5, 100, 95, 90]))
|
||||
assert 5.0 in [level for _, level in points]
|
||||
assert len(find_replacements(points)) == 1
|
||||
|
||||
Reference in New Issue
Block a user