Skip to content

Commit 0e329c0

Browse files
committed
improve testing harness
1 parent ec96fda commit 0e329c0

File tree

4 files changed

+73
-2
lines changed

4 files changed

+73
-2
lines changed

benches/harness.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,18 @@ async def run_bench(config_path: str):
113113
)
114114
for i in range(cfg.load.get('concurrency', 1))
115115
]
116-
await asyncio.gather(*workers)
117-
mon.stop()
116+
try:
117+
await asyncio.gather(*workers)
118+
except KeyboardInterrupt:
119+
# ensure monitor and workers are stopped on Ctrl-C
120+
for w in workers:
121+
w.cancel()
122+
raise
123+
finally:
124+
try:
125+
mon.stop()
126+
except Exception:
127+
pass
118128

119129
# write per-sample
120130
out_prefix = cfg.io['output_prefix']

benches/plot.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""Simple plotting helpers for benchmark outputs."""
2+
from __future__ import annotations
3+
import pathlib
4+
from typing import Optional
5+
6+
def plot_resources(csv_path: str, out_png: Optional[str] = None):
7+
try:
8+
import pandas as pd
9+
import matplotlib.pyplot as plt
10+
except Exception:
11+
raise RuntimeError('pandas and matplotlib are required for plotting')
12+
13+
p = pathlib.Path(csv_path)
14+
df = pd.read_csv(p)
15+
fig, ax = plt.subplots(2, 1, figsize=(8, 6), sharex=True)
16+
if 't_s' in df:
17+
ax[0].plot(df['t_s'], df['cpu_pct'], label='cpu_pct')
18+
ax[0].set_ylabel('CPU %')
19+
ax[1].plot(df['t_s'], df['rss_mb'], label='rss_mb')
20+
ax[1].set_ylabel('RSS MB')
21+
else:
22+
raise RuntimeError('unexpected resources csv format')
23+
24+
ax[0].legend()
25+
ax[1].legend()
26+
if out_png is None:
27+
out_png = str(p.with_suffix('.png'))
28+
fig.tight_layout()
29+
fig.savefig(out_png)
30+
return out_png

requirements-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pytest
22
pytest-cov
3+
matplotlib

tests/test_integration_harness.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import asyncio, tempfile, shutil, pathlib, os
2+
3+
4+
def test_harness_writes_artifacts():
5+
# create a temporary config copying the example config and dataset
6+
root = pathlib.Path(__file__).resolve().parents[1]
7+
td = tempfile.TemporaryDirectory()
8+
out_prefix = pathlib.Path(td.name) / "reports" / "it_demo"
9+
config = {
10+
'run_name': 'it_demo',
11+
'provider': {'kind': 'mock'},
12+
'io': {'dataset_path': str(root / 'datasets' / 'qa_tiny.jsonl'), 'output_prefix': str(out_prefix)},
13+
'prompt': {'system': 'You are concise.', 'template': 'Q: {input}\nA:'},
14+
'limits': {'max_samples': 2, 'timeout_s': 10},
15+
'load': {'batch_size': 1, 'concurrency': 1},
16+
'metrics': {'bleu': False, 'rougeL': False, 'normalization': 'lower_strip'},
17+
}
18+
import yaml
19+
cfg_path = pathlib.Path(td.name) / 'cfg.yaml'
20+
cfg_path.write_text(yaml.safe_dump(config), encoding='utf8')
21+
22+
# run harness
23+
from benches.harness import run_bench
24+
asyncio.run(run_bench(str(cfg_path)))
25+
26+
# assert artifacts exist
27+
assert (out_prefix.with_suffix('.jsonl')).exists()
28+
assert (out_prefix.with_name(out_prefix.name + '_summary.csv')).exists()
29+
assert (out_prefix.with_name(out_prefix.name + '_resources.csv')).exists()
30+
assert (out_prefix.with_name(out_prefix.name + '_report.md')).exists()

0 commit comments

Comments
 (0)