SPB Git
8.6 KB · 146 lines python
1"""Tests du chapitre 12 — mesurage, superficies, propagation d'erreur (cas 1, données synthétiques).2Tolérances : 1e-6 sur les identités géométriques ; 0,5 $ sur les montants cités arrondis au dollar ; 5e-4 sur les proportions ;3simulation d'atténuation : moyenne à ±2 écarts-types de la valeur théorique (graine fixée → déterministe)."""4import sys, pathlib, math5import numpy as np, pytest6sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1] / "cases"))7import ch12_mesurage as cas8910@pytest.fixture(scope="module")11def r():12    return cas.tout()131415class TestConversions:16    def test_facteurs(self):17        assert cas.M2_PAR_PI2 == 0.3048 ** 218        assert cas.PI2_PAR_M2 == pytest.approx(1 / cas.M2_PAR_PI2, rel=1e-6)19        assert 165 * cas.PI2_PAR_M2 == pytest.approx(1776.0, abs=0.05)20        assert 190.08 * cas.PI2_PAR_M2 == pytest.approx(2046.0, abs=0.05)21        assert 2000 * cas.M2_PAR_PI2 == pytest.approx(185.8, abs=0.05)222324class TestPlan:25    def test_superficies_sujet(self, r):26        s = r["sup"]27        assert s["aire_sol_m2"] == pytest.approx(95.04, abs=1e-9) and s["perimetre_sol_m"] == pytest.approx(39.84, abs=1e-9)28        assert s["aire_etages_m2"] == pytest.approx(190.08, abs=1e-9) and s["perimetre_etages_m"] == pytest.approx(79.68, abs=1e-9)29        assert s["aire_int_niveau_m2"] == pytest.approx(84.1984, abs=1e-6)30        assert s["habitable_m2"] == pytest.approx(165.0, abs=0.01)       # cohérent avec cas1_gatineau_sujet.json (165 m²)31        assert s["nette_m2"] == pytest.approx(159.94, abs=0.01)32        assert s["habitable_sous_sol_m2"] == pytest.approx(235.0, abs=0.01)33        assert s["garage_m2"] == pytest.approx(22.33, abs=0.01) and s["lot_m2"] == pytest.approx(620.0, abs=0.05)34        assert cas.PLAN["sous_sol_plancher_sous_sol_m"] > 0.4           # le sous-sol n'est pas un étage au sens du MEFQ3536    def test_formule_murs(self, r):37        s = r["sup"]38        assert s["ratio_int_ext"] == pytest.approx(s["ratio_murs_formule"], abs=1e-12)39        assert s["ratio_int_ext"] == pytest.approx(0.8859, abs=5e-5)40        assert s["aire_etages_m2"] / s["habitable_m2"] == pytest.approx(1.152, abs=5e-4)414243class TestPrixUnitaires:44    def test_valeurs(self, r):45        pu = r["pu"].set_index("convention"); V = r["M"]["V"]46        assert V == pytest.approx(637952.85, abs=0.5)47        assert pu.loc["Superficie habitable (convention de l'ouvrage)", "dollars_m2"] == pytest.approx(3866, abs=0.5)48        assert pu.loc["Aire des étages, brute (MEFQ R0702A)", "dollars_m2"] == pytest.approx(3356, abs=0.5)49        assert pu.loc["Habitable + sous-sol fini (fiches de courtage)", "dollars_m2"] == pytest.approx(2715, abs=0.5)50        assert pu.loc["Superficie nette (utile)", "dollars_m2"] == pytest.approx(3989, abs=0.5)51        assert pu.loc["Aire au sol (MEFQ R0701A)", "dollars_m2"] == pytest.approx(6712, abs=0.5)52        assert pu.loc["Superficie habitable (convention de l'ouvrage)", "dollars_pi2"] == pytest.approx(359.2, abs=0.05)53        assert pu.loc["Aire des étages, brute (MEFQ R0702A)", "dollars_pi2"] == pytest.approx(311.8, abs=0.05)545556class TestPropagation:57    def test_derivee(self, r):58        M = r["M"]59        assert M["beta"] == pytest.approx(0.539, abs=5e-4)60        assert r["dVdS"] == pytest.approx(M["beta"] * M["V"] / M["S"], rel=1e-12)61        assert r["dVdS"] == pytest.approx(2084, abs=0.5)62        assert r["dVdS"] / (M["V"] / M["S"]) == pytest.approx(M["beta"], rel=1e-12)6364    def test_cinq_pour_cent(self, r):65        p = r["prop"].set_index("erreur_S_pct")66        assert p.loc[5.0, "lineaire_dollars"] == pytest.approx(17195, abs=0.5) and p.loc[5.0, "lineaire_pct"] == pytest.approx(2.695, abs=5e-4)67        assert p.loc[5.0, "exact_dollars"] == pytest.approx(17002, abs=0.5) and p.loc[5.0, "exact_pct"] == pytest.approx(2.665, abs=5e-4)68        assert p.loc[-5.0, "exact_dollars"] == pytest.approx(-17398, abs=0.5)69        assert p.loc[5.0, "naif_dollars"] == pytest.approx(31898, abs=0.5)70        assert p.loc[10.0, "exact_pct"] == pytest.approx(5.272, abs=5e-4) and p.loc[-10.0, "exact_pct"] == pytest.approx(-5.521, abs=5e-4)71        # identité : effet exact = (1+e)^β − 1 ; linéaire = β e72        for e in (-0.1, -0.05, 0.05, 0.1):73            assert p.loc[100 * e, "exact_pct"] == pytest.approx(100 * ((1 + e) ** r["M"]["beta"] - 1), rel=1e-9)7475    def test_melange_conventions(self, r):76        m = r["mel"]77        assert m["ecart_pct"] == pytest.approx(15.20, abs=5e-3)78        assert m["sujet_brut_pct"] == pytest.approx(7.93, abs=5e-3) and m["sujet_brut_dollars"] == pytest.approx(50573, abs=0.5)79        assert m["sujet_hab_pct"] == pytest.approx(-7.35, abs=5e-3) and m["sujet_hab_dollars"] == pytest.approx(-46858, abs=0.5)80        assert (1 + m["sujet_brut_pct"] / 100) * (1 + m["sujet_hab_pct"] / 100) == pytest.approx(1.0, abs=1e-9)8182    def test_comparable(self, r):83        c, ec = r["comp"], r["ec"]84        assert c["id_vente"] == "G0404" and c["prix_vente"] == 506500 and c["superficie_habitable_m2"] == 16085        assert ec["A_vrai"] == pytest.approx(8472, abs=0.5) and ec["A_obs"] == pytest.approx(-8086, abs=0.5)86        assert ec["erreur"] == pytest.approx(-16558, abs=0.5) and ec["erreur_approx"] == pytest.approx(-17065, abs=0.5)8788    def test_variance_combinee(self, r):89        vc = r["vc"]90        assert vc["base"]["relatif"] == pytest.approx(0.01181, abs=5e-6) and vc["base"]["dollars"] == pytest.approx(7535, abs=0.5)91        assert vc["base"]["part_sujet"] == pytest.approx(5 / 6, rel=1e-9)92        assert vc["sujet_seul"]["dollars"] == pytest.approx(6878, abs=0.5) and vc["comparables_seuls"]["dollars"] == pytest.approx(3076, abs=0.5)93        assert vc["cinq_pct"]["dollars"] == pytest.approx(17468, abs=0.5)94        assert vc["base"]["relatif"] ** 2 == pytest.approx(vc["sujet_seul"]["relatif"] ** 2 + vc["comparables_seuls"]["relatif"] ** 2, rel=1e-9)959697class TestAttenuation:98    def test_theorie_et_simulation(self, r):99        att = r["att"].set_index("sigma_u")100        assert att.attrs["var_e"] == pytest.approx(0.0609, abs=5e-4) and att.attrs["sd_lnS"] == pytest.approx(0.2487, abs=5e-4)101        assert att.loc[0.0, "beta_moyen"] == pytest.approx(r["M"]["beta"], rel=1e-9)102        for s in (0.05, 0.10, 0.20):103            lam = att.attrs["var_e"] / (att.attrs["var_e"] + s ** 2)104            assert att.loc[s, "lambda_theorique"] == pytest.approx(lam, rel=1e-12)105            assert abs(att.loc[s, "beta_moyen"] - att.loc[s, "beta_attendu"]) <= 2 * att.loc[s, "beta_ecart_type"] + 1e-3106        assert att.loc[0.10, "lambda_theorique"] == pytest.approx(0.859, abs=5e-4) and att.loc[0.20, "lambda_theorique"] == pytest.approx(0.604, abs=5e-4)107        assert att.loc[0.10, "beta_moyen"] == pytest.approx(0.465, abs=5e-3)108        assert att["beta_moyen"].is_monotonic_decreasing109        assert att["V_maison_120"].is_monotonic_increasing and att["V_sujet_165"].is_monotonic_decreasing110111112class TestExercices:113    def test_ex1(self):114        # 28 pi × 42 pi, deux étages115        a_pi2 = 28 * 42; a_m2 = a_pi2 * cas.M2_PAR_PI2116        assert a_pi2 == 1176 and a_m2 == pytest.approx(109.25, abs=0.005)117        assert 2 * a_m2 == pytest.approx(218.5, abs=0.05) and 2 * a_pi2 == 2352118        assert 2 * (28 + 42) * 0.3048 == pytest.approx(42.67, abs=0.005)119120    def test_ex3(self):121        L, W, t = 11.0, 9.0, 0.30122        A = L * W; P = 2 * (L + W); Ai = (L - 2 * t) * (W - 2 * t)123        assert A == 99.0 and P == 40.0 and Ai == pytest.approx(87.36, abs=1e-9)124        assert Ai / A == pytest.approx(1 - t * P / A + 4 * t ** 2 / A, rel=1e-12)125        assert 2 * Ai - 3.2 == pytest.approx(171.52, abs=1e-9)126        assert 2 * A / (2 * Ai - 3.2) == pytest.approx(1.154, abs=5e-4)127128    def test_ex4(self):129        V, S, b, sig = 520000, 140.0, 0.55, 0.03130        dVdS = b * V / S131        assert dVdS == pytest.approx(2042.86, abs=0.01) and dVdS * sig * S == pytest.approx(8580, abs=0.5)132        assert V * (1.03 ** b - 1) == pytest.approx(8523, abs=0.5) and V * (0.97 ** b - 1) == pytest.approx(-8639, abs=0.5)133        assert (V / S) * sig * S == pytest.approx(15600, abs=0.5)134135    def test_ex5(self, r):136        b = r["M"]["beta"]137        assert 100 * (math.exp(b * math.log(205 / 178)) - 1) == pytest.approx(7.91, abs=0.01)138        # comparable : 560 000 $, 172 m² habitables, sujet 178 m² ; sujet mesuré 205 m² bruts par erreur139        A_ok = 560000 * ((178 / 172) ** b - 1); A_faux = 560000 * ((205 / 172) ** b - 1)140        assert A_ok == pytest.approx(10447, abs=0.5) and A_faux == pytest.approx(55572, abs=0.5)141142    def test_ex6(self, r):143        var_e = r["att"].attrs["var_e"]144        assert var_e / (var_e + 0.08 ** 2) == pytest.approx(0.905, abs=5e-4)145        assert 0.905 * 0.539 == pytest.approx(0.488, abs=5e-4)146
Files · 52713f1726a682cc02b48561b6b82a2be2ec84ba
Menu

Theme