# Test ```bash .venv/bin/pytest # tutti (≈ 7 s) .venv/bin/pytest tests/test_fit.py # un file .venv/bin/pytest -k raffreddamento # per nome .venv/bin/pytest -x -q # ferma al primo errore, output breve .venv/bin/pytest -rs # mostra i test saltati e il motivo .venv/bin/ruff check src tests # stile e import (deve passare) ``` ## Due livelli | Livello | File | Dati | Se i CSV mancano | |---|---|---|---| | **Unitari** | `test_domini`, `test_fit`, `test_selezione`, `test_config_dati` | segnale sintetico generato nei test (`conftest.py`) | girano comunque | | **Integrazione** | `test_integrazione` | `input/gen_{1,2,3}.csv` di `gen_data`; CLI | **saltati** (non falliti) | Un clone nuovo non ha i CSV (`input/*.csv` è ignorato da git): i test unitari bastano per lavorare sul codice; per quelli di integrazione si generano i CSV come in [uso.md](uso.md) §2. ## Il segnale sintetico (`tests/conftest.py`) $$T(t) = T_\text{amb} + \sum_j A_j\,e^{-(t-t_j)/\tau}\,\mathbb{1}[t \ge t_j] + \varepsilon, \qquad \varepsilon \sim \mathcal{N}(0, 0.1^2)$$ con $T_\text{amb} = 23$, $\tau = 16$ s, gradini $(t_j, A_j) = (15, 80), (18, 70), (22, 60)$, campionamento 0.15 s, 120 s, **nessun scarto casuale**. La verità è nota, quindi si possono controllare numericamente i parametri recuperati. La funzione `segnale(...)` accetta rumore, seme, gradini e durata per costruire casi particolari (nessun gradino, un gradino, gradino sotto soglia). `dT_C` = $T - T_\text{amb}$. Fixture: `cfg` (config reale), `sintetico`, `csv_gen` (un CSV `gen_data`, saltato se assente). ## `test_domini.py` — suddivisione (assunzioni A5, A6, A21) | Test | Verifica | |---|---| | `test_tre_gradini` | 3 gradini → 7 domini: riposo, (riscaldamento, raffreddamento) × 3 | | `test_riscaldamento_e_la_salita_rapida` | ogni riscaldamento ha ≤ 3 campioni | | `test_confini_vicini_agli_istanti_dei_gradini` | l'inizio di ogni riscaldamento è entro 0.5 s dal gradino vero | | `test_domini_contigui_e_completi` | primo `i0 = 0`, ultimo `i1 = n`, nessun buco | | `test_senza_gradini_un_solo_riposo` | nessun gradino → solo riposo | | `test_un_solo_gradino` | riposo, riscaldamento, raffreddamento | | `test_gradino_sotto_soglia_ignorato` | un salto di 10 °C (< soglia) non è un gradino | | `test_domini_toml_andata_e_ritorno` | scrivere e rileggere `domini.toml` dà gli stessi domini | | `test_domini_toml_non_contigui_rifiutati` | domini non contigui → `ValueError` | | `test_domini_toml_tipo_non_valido` | tipo sconosciuto → `ValueError` | ## `test_fit.py` — fit e analisi (A7, A8, A13, A18, A22, A23) | Test | Verifica | |---|---| | `test_modelli_valutazione` | valori dei modelli; il registro contiene esattamente `costante`, `lineare`, `esp_decad` | | `test_esp_decad_recupera_parametri` (5 seed) | $\tau$ entro il 2 %, $c$ entro 0.2, $A$ entro il 2 %, $\mathrm{RMSE} \approx \sigma$, fit valido | | `test_parametri_fissi_restano_fissi` | $c$ e $\tau$ fissi restano invariati, $k = 1$, $A$ recuperata entro il 3 % | | `test_tau_libero_non_identificabile_su_tratto_corto_e_rumoroso` (5 seed) | su 3 s con disturbi di 2 °C, $\tau$ libero è «non identificabile» (motivo del fissaggio) | | `test_analisi_completa_sintetico` | 7 domini; finale con $\tau$ entro il 3 % e nessun parametro fisso; intermedi con `c`, `tau` fissi uguali al finale; ampiezze $A$ degli intermedi entro il 5 % dal valore atteso | | `test_riscaldamento_descritto_come_salto_non_fittato` | `fit` vuoto, `scelta` assente, $\Delta$ entro il 15 % dell'ampiezza vera, ≤ 3 campioni | | `test_un_solo_raffreddamento_resta_libero` | un solo gradino → il raffreddamento (finale) non ha parametri fissi | | `test_dominio_troppo_corto_indeterminato` | 5 campioni → `indeterminato` | | `test_riproducibile` | due esecuzioni identiche danno risultati identici | ## `test_selezione.py` — regola di scelta ([algoritmi.md](algoritmi.md) §6) Su fit finti costruiti a mano: vince il modello con meno parametri entro $\Delta\mathrm{AICc}$; vince il migliore oltre la soglia; si scartano non convergenti, a limite, non identificabili; nessun valido → indeterminato; si preferiscono i modelli adeguati anche con AICc peggiore; nessun adeguato → scelto ma segnalato. ## `test_config_dati.py` — errori di configurazione e CSV (A1, A2) `config.toml` reale valido; chiave mancante; lista dei modelli vuota per un tipo; file di configurazione inesistente; CSV valido (conversione ms → s); colonna mancante; tempo non crescente. ## `test_integrazione.py` — su `gen_data` e CLI | Test | Verifica | |---|---| | `test_domini_su_csv_gen` (3 seed) | 7 domini nell'ordine atteso | | `test_raffreddamento_tau_nominale` (3 seed) | raffreddamento finale: `esp_decad`, $\tau$ entro il 10 % di 15.9 s | | `test_raffreddamenti_intermedi_ereditano_costanti` (3 seed) | intermedi con `c`, `tau` fissi uguali al finale, $A > 0$ | | `test_cli_domini_e_analizza` | `fitseg domini` scrive solo `01_domini/`; `analizza --domini` scrive sovrapposizione e report; il report rimanda alle immagini giuste; formule principali in LaTeX e `$` bilanciati su ogni riga | | `test_cli_errori` | CSV inesistente → exit 4; configurazione inesistente → exit 3 | ## Cosa non è coperto Seed oltre i tre di `gen_data`; rumore e gradini molto diversi dalla configurazione d'esempio; dati reali; i grafici (si controllano a vista, [output.md](output.md)). Prova manuale dopo una modifica: `fitseg analizza input/gen_1.csv` e controllare in `report.md` i 7 domini e $\tau \approx 16$ s nel finale.