__tests__/students.test.js
Rama main · réplica de lectura del repositorio original.
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
const fs = require('fs');
const os = require('os');
const path = require('path');
/*
* The student is chosen by measurement. These hold the two things that would quietly ruin that: a
* trial being mistaken for a training round, and a candidate being scored against a number that
* came off a different paper.
*/
describe('choosing the student', () => {
let dir, students;
beforeEach(() => {
dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gb-students-'));
process.env.PROFILE_DIR = dir;
delete require.cache[require.resolve('../src/students')];
students = require('../src/students');
});
afterEach(() => {
delete process.env.PROFILE_DIR;
delete require.cache[require.resolve('../src/students')];
fs.rmSync(dir, { recursive: true, force: true });
});
const trial = (model, pct, extra = {}, adapter = '') => ({
id: `r-${model.slice(-4)}${adapter.slice(-4)}`, status: 'done', endedAt: '2026-09-26T01:00:00.000Z',
recipe: { base: model, trial: true, adapter },
result: { agreement_pct: pct, turns: 354, args_agreement_pct: pct / 2, unusable_pct: 5, collapse: { ratio: 1.2, tool: 'read' } },
...extra,
});
it('the incumbent stands in the field as the control', () => {
expect(students.CANDIDATES.map((c) => c.id)).toContain('Qwen/Qwen2.5-0.5B-Instruct');
expect(students.CANDIDATES.length).toBeGreaterThanOrEqual(3);
});
it('the field is the family we already serve, and what waits says why', () => {
const ids = students.CANDIDATES.map((c) => c.id);
/* Every candidate serves through the ChatML template the export already writes. */
expect(students.CANDIDATES.every((c) => c.model.startsWith('Qwen/'))).toBe(true);
expect(ids).toContain('Qwen/Qwen3-1.7B');
/* A different family is not refused, it is postponed - with the reason written down. */
expect(students.LATER.map((c) => c.id)).toContain('google/gemma-4-E4B-it');
expect(students.LATER.find((c) => c.id === 'google/gemma-4-E4B-it').needs).toMatch(/template/);
/* And postponed means not queueable by accident. */
expect(() => students.queue(['google/gemma-4-E4B-it'])).toThrow(/not a candidate/);
});
it('a trial is not a training round', () => {
expect(students.isTrial({ recipe: { trial: true, base: 'x' } })).toBe(true);
expect(students.isTrial({ recipe: { base: 'x', lr: 2e-4 } })).toBe(false);
expect(students.isTrial(null)).toBe(false);
});
it('queues candidates once each, and refuses one nobody has heard of', () => {
students.queue(['Qwen/Qwen3-1.7B', 'Qwen/Qwen3-1.7B']);
expect(students.next()).toBe('Qwen/Qwen3-1.7B');
expect(students.list([]).queue).toEqual(['Qwen/Qwen3-1.7B']);
expect(() => students.queue(['nobody/ghost-9000'])).toThrow(/not a candidate/);
students.shift('Qwen/Qwen3-1.7B');
expect(students.next()).toBe('');
});
it('two candidates on one model are told apart by what they wear', () => {
const rounds = [
trial('Qwen/Qwen2.5-0.5B-Instruct', 41.2, {}, 'hub:r-mugxfwm4-y0m6'),
trial('Qwen/Qwen2.5-0.5B-Instruct', 38.9, {}, 'hub:r-muhbyo1p-gzi9'),
trial('Qwen/Qwen2.5-0.5B-Instruct', 6.1),
];
const out = students.list(rounds);
const by = (id) => out.candidates.find((c) => c.id === id).trial.agreement;
expect(by('ours:serving')).toBe(41.2);
expect(by('ours:refused')).toBe(38.9);
/* And the bare incumbent must not pick up either adapter's number. */
expect(by('Qwen/Qwen2.5-0.5B-Instruct')).toBe(6.1);
expect(out.leader.id).toBe('ours:serving');
});
it('reads each candidate score off its own trial round and names the leader', () => {
const rounds = [trial('Qwen/Qwen3-1.7B', 21.4), trial('Qwen/Qwen2.5-0.5B-Instruct', 6.1)];
const out = students.list(rounds);
const inc = out.candidates.find((c) => c.id === 'Qwen/Qwen2.5-0.5B-Instruct');
expect(inc.trial.agreement).toBe(6.1);
expect(inc.trial.turns).toBe(354);
expect(out.leader.id).toBe('Qwen/Qwen3-1.7B');
/* One never tried has no number at all, rather than a zero that would sort like a loss. */
expect(out.candidates.find((c) => c.id === 'Qwen/Qwen3-0.6B').trial).toBe(null);
});
it('a running trial is reported as running, not as a score', () => {
const rounds = [{ id: 'r-run', status: 'running', recipe: { base: 'Qwen/Qwen3-0.6B', trial: true, adapter: '' }, result: null }];
const out = students.list(rounds);
expect(out.running).toBe(true);
expect(out.candidates.find((c) => c.id === 'Qwen/Qwen3-0.6B').trial.agreement).toBe(null);
expect(out.leader).toBe(null);
});
it('a failed trial keeps its reason where it can be read', () => {
const rounds = [{ id: 'r-bad', status: 'failed', recipe: { base: 'Qwen/Qwen3-0.6B', trial: true, adapter: '' }, result: null, why: 'could not load Qwen/Qwen3-0.6B' }];
const t = students.list(rounds).candidates.find((c) => c.id === 'Qwen/Qwen3-0.6B').trial;
expect(t.status).toBe('failed');
expect(t.why).toMatch(/could not load/);
});
it('clearing forgets the queue', () => {
students.queue(['Qwen/Qwen3-0.6B']);
expect(students.clear()).toEqual([]);
expect(students.next()).toBe('');
});
});