gestion_table_tournante_libre/scripts/banc/statistiques.test.js

64 lines
3.1 KiB
JavaScript
Raw Normal View History

// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// Épreuves des statistiques du temps par image (§ 19.10) : des listes
// écrites, dont chaque statistique se lit à la main sur la liste triée.
import assert from 'node:assert/strict';
import { describe, test } from '../../test/lanceur.js';
import { statistiques } from './statistiques.js';
// Vingt intervalles dans le désordre. Triés : 6 7 7 8 8 8 9 9 9 10 | 11 11 12
// 12 13 14 15 33 41 50. La médiane est la moyenne des deux du milieu, 10 et
// 11 ; le p95, au rang ⌈0,95 × 20⌉ = 19, vaut 41 — une interpolation
// rendrait 41,45, le rang 20 rendrait 50.
const VINGT = Object.freeze([12, 9, 33, 7, 8, 41, 10, 6, 15, 11, 9, 7, 50, 8, 13, 11, 12, 9, 14, 8]);
describe('statistiques du temps par image', () => {
test('vingt intervalles connus : nombre d’images, médiane, p95 au rang le plus proche, maximum', () => {
assert.deepEqual(statistiques(VINGT), { images: 20, medianeMs: 10.5, p95Ms: 41, maxMs: 50 });
});
test('une longueur impaire : la médiane est l’intervalle du milieu', () => {
assert.deepEqual(statistiques([5, 1, 3]), { images: 3, medianeMs: 3, p95Ms: 5, maxMs: 5 });
});
test('cent intervalles de 1 à 100 : le p95 est le 95e, la médiane la moyenne du 50e et du 51e', () => {
const cent = Array.from({ length: 100 }, (_, i) => 100 - i);
assert.deepEqual(statistiques(cent), { images: 100, medianeMs: 50.5, p95Ms: 95, maxMs: 100 });
});
// 0,95 × 11 = 10,45 : le rang ⌈10,45⌉ = 11 et l'arrondi au plus proche,
// 10, désignent deux intervalles distincts ; aux longueurs 1, 3, 20 et 100
// des autres épreuves, ils désignent le même.
test('onze intervalles de 1 à 11 : le p95 est au rang ⌈10,45⌉ = 11, et non à l’arrondi 10', () => {
const onze = [4, 11, 7, 1, 9, 2, 10, 5, 8, 3, 6];
assert.deepEqual(statistiques(onze), { images: 11, medianeMs: 6, p95Ms: 11, maxMs: 11 });
});
test('un seul intervalle : chaque statistique le vaut', () => {
assert.deepEqual(statistiques([16.7]), { images: 1, medianeMs: 16.7, p95Ms: 16.7, maxMs: 16.7 });
});
test('la liste reçue reste dans son ordre', () => {
const recue = [...VINGT];
statistiques(recue);
assert.deepEqual(recue, VINGT);
});
test('une liste vide est refusée', () => {
assert.throws(() => statistiques([]), RangeError);
});
test('un intervalle négatif, non fini ou qui n’est pas un nombre est refusé en le nommant', () => {
assert.throws(() => statistiques([3, -1]), { name: 'RangeError', message: /-1/ });
assert.throws(() => statistiques([3, Number.NaN]), { name: 'RangeError', message: /NaN/ });
assert.throws(() => statistiques([3, Number.POSITIVE_INFINITY]), { name: 'RangeError', message: /Infinity/ });
assert.throws(() => statistiques([3, '4']), { name: 'RangeError', message: /4/ });
});
test('autre chose qu’une liste est refusé', () => {
assert.throws(() => statistiques(null), TypeError);
assert.throws(() => statistiques(new Set([1, 2])), TypeError);
});
});