f029820a14
Il test controllava solo l'assenza dell'agilita (scoreAgilita/scoreAgilityMs) e non della seconda funzione esclusa dal brief, score_generic_range_local: se qualcuno la reintroducesse un domani nessun test se ne accorgerebbe. Aggiunta l'assertion con lo stesso criterio, rinominato il test perche' ora copre entrambe le esclusioni.
75 lines
3.6 KiB
TypeScript
75 lines
3.6 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { readFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import * as F from '../../src/lib/longevity/motore/test-fisici';
|
|
|
|
const RIF = JSON.parse(
|
|
readFileSync(join(process.cwd(), 'tests/longevity/riferimento/riferimento.json'), 'utf8')
|
|
) as { casi: { fn: string; args: unknown[]; atteso: number }[] };
|
|
|
|
/** Ogni funzione dell'oracolo con la sua gemella in TypeScript. */
|
|
const COPPIE: [string, (...a: never[]) => number][] = [
|
|
['score_fat_percent', F.scoreGrassoPercento as never],
|
|
['score_muscle_percent', F.scoreMuscoloPercento as never],
|
|
['score_whr', F.scoreWhr as never],
|
|
['score_vo2max', F.scoreVo2max as never],
|
|
['score_spo2', F.scoreSpo2 as never],
|
|
['score_blood_pressure', F.scorePressione as never],
|
|
['score_hrr', F.scoreRecuperoCardiaco as never],
|
|
['score_handgrip', F.scoreHandgrip as never],
|
|
['score_pushup', F.scorePushup as never],
|
|
['score_flexed_arm_hang', F.scoreTrazioneIsometrica as never],
|
|
['score_sit_to_stand_1min', F.scoreSitToStand as never],
|
|
['score_plank', F.scorePlank as never],
|
|
['score_back_scratch', F.scoreBackScratch as never],
|
|
['score_shoulder_mobility_wt', F.scoreMobilitaSpalla as never],
|
|
['score_flamingo', F.scoreFlamingo as never],
|
|
['score_sit_and_reach', F.scoreSitAndReach as never],
|
|
['vo2max_from_step_test', F.vo2maxDaStepTest as never],
|
|
['vo2max_from_2km_walk', F.vo2maxDa2kmWalk as never],
|
|
['vo2max_from_mutt', F.vo2maxDaMutt as never],
|
|
['vo2max_from_milfit', F.vo2maxDaMilfit as never],
|
|
];
|
|
|
|
describe('curve dei test fisici, confrontate con l oracolo caso per caso', () => {
|
|
for (const [nomePython, fnTs] of COPPIE) {
|
|
it(`${nomePython} combacia su tutti i casi del riferimento`, () => {
|
|
const casi = RIF.casi.filter((c) => c.fn === nomePython);
|
|
expect(casi.length, `nessun caso per ${nomePython}: la griglia non lo copre`).toBeGreaterThan(0);
|
|
const divergenti: string[] = [];
|
|
for (const c of casi) {
|
|
const ottenuto = (fnTs as (...a: unknown[]) => number)(...c.args);
|
|
if (Math.abs(ottenuto - c.atteso) > 0.05) {
|
|
divergenti.push(`${nomePython}(${c.args.join(', ')}): atteso ${c.atteso}, ottenuto ${ottenuto}`);
|
|
}
|
|
}
|
|
expect(divergenti.slice(0, 5).join('\n')).toBe('');
|
|
});
|
|
}
|
|
|
|
it('i sollevamenti sul peso corporeo combaciano su tutte e tre le tabelle', () => {
|
|
const casi = RIF.casi.filter((c) => c.fn === 'score_bw_ratio_lift');
|
|
expect(casi.length).toBeGreaterThan(50);
|
|
const perTabella = (nome: string) =>
|
|
({ bench: [F.TIERS_BENCH_M, F.TIERS_BENCH_F], squat: [F.TIERS_SQUAT_M, F.TIERS_SQUAT_F],
|
|
row: [F.TIERS_ROW_M, F.TIERS_ROW_F] } as Record<string, unknown[]>)[nome];
|
|
for (const c of casi) {
|
|
const [carico, peso, rip, tiersM, tiersF, sesso] = c.args as [number, number, number, unknown, unknown, 'M' | 'F'];
|
|
const ottenuto = F.scoreSollevamentoSuPeso(
|
|
carico, peso, rip,
|
|
tiersM as [number, number][], tiersF as [number, number][], sesso
|
|
);
|
|
expect(ottenuto, `carico ${carico} ${sesso}`).toBeCloseTo(c.atteso, 1);
|
|
}
|
|
expect(perTabella('bench')).toBeTruthy();
|
|
});
|
|
|
|
it('le due funzioni escluse dal porting non esistono nel modulo', () => {
|
|
// Agilita: il cliente l'ha esclusa dallo score il 13/08 (scale non comparabili fra protocolli).
|
|
expect((F as Record<string, unknown>).scoreAgilita).toBeUndefined();
|
|
expect((F as Record<string, unknown>).scoreAgilityMs).toBeUndefined();
|
|
// score_generic_range_local: definita in fondo all'oracolo ma non chiamata da nessun peso.
|
|
expect((F as Record<string, unknown>).scoreGenericRangeLocal).toBeUndefined();
|
|
});
|
|
});
|