SPB Git
12.1 KB · 185 lines python
1"""Tests du chapitre 44 — rénovation et efficacité énergétique (sujet du cas 1, DONNÉES SYNTHÉTIQUES).2Tolérances : 0,01 $ sur les montants recalculés ; 5e-4 sur les taux cités en % à deux décimales ; 1e-9 sur les identités."""3import sys, pathlib, math4import numpy as np, pytest5sys.path.insert(0, str(pathlib.Path(__file__).resolve().parents[1] / "cases"))6import ch44_renovation as cas7from traite import finance as fin, cas18910@pytest.fixture(scope="module")11def data():12    mm = cas.mesures()13    d = cas1.charger(); mod = cas1.hedonique(d["ventes"]); vs = float(cas1.predire(mod, cas1.sujet_df(d["sujet"]))[0])14    return {"mm": mm, "fA": cas.flux_mesure(mm["A"]), "fB": cas.flux_mesure(mm["B"]), "fAB": cas.flux_mesure(mm["AB"]),15            "fI": cas.flux_mesure(mm["A_incr"]), "ventes": d["ventes"], "modele": mod, "vs": vs}161718class TestTarifD:19    def test_structure_verifiee(self):20        assert cas.FRAIS_ACCES_JOUR == 0.46154 and cas.PRIX_TRANCHE_1 == 0.07065 and cas.PRIX_TRANCHE_2 == 0.11142 and cas.SEUIL_KWH_JOUR == 402122    def test_facture_sujet(self):23        F = cas.facture_tarif_d(22000.0)24        assert F["acces"] == pytest.approx(168.46, abs=0.005) and F["tranche1_kwh"] == 14600 and F["tranche2_kwh"] == 740025        assert F["energie_t1"] == pytest.approx(1031.49, abs=0.005) and F["energie_t2"] == pytest.approx(824.51, abs=0.005)26        assert F["total"] == pytest.approx(2024.46, abs=0.005)27        assert F["total"] == pytest.approx(F["acces"] + F["energie_t1"] + F["energie_t2"], abs=1e-9)28        assert F["prix_moyen"] == pytest.approx(0.0920, abs=5e-5) and F["prix_marginal"] == 0.111422930    def test_economie_marginale(self):31        # 1 000 kWh retranchés au-dessus du seuil valent 111,42 $ ; à cheval sur le seuil (15 000 → 14 000), 86,96 $32        assert cas.economie_annuelle(26000.0, 25000.0) == pytest.approx(111.42, abs=0.005)33        assert cas.economie_annuelle(15000.0, 14000.0) == pytest.approx(86.96, abs=0.005)34        assert cas.economie_annuelle(22000.0, 18700.0) == pytest.approx(3300 * 0.11142, abs=1e-9)353637class TestMesures:38    def test_thermopompe(self, data):39        m, f = data["mm"]["A"], data["fA"]40        assert m["cout"] == 16500.0 and m["subvention"] == pytest.approx(4320.0) and f["cout_net"] == pytest.approx(12180.0)41        assert m["kwh"] == pytest.approx(3300.0) and f["economie_courante"] == pytest.approx(367.69, abs=0.005)42        assert f["economie_an1"] == pytest.approx(378.72, abs=0.005)43        assert f["van"] == pytest.approx(-7286.54, abs=0.01) and f["tri"] == pytest.approx(-0.0584, abs=5e-5)44        assert f["va_economies"] == pytest.approx(4893.46, abs=0.01) and f["indice_rentabilite"] == pytest.approx(0.402, abs=5e-4)45        assert f["annuite_cout_net"] == pytest.approx(1140.37, abs=0.01)46        assert f["cee_net"] == pytest.approx(0.3456, abs=5e-5) and f["cee_brut"] == pytest.approx(0.4681, abs=5e-5)47        assert f["delai_simple"] is None and f["delai_actualise"] is None4849    def test_isolation(self, data):50        m, f = data["mm"]["B"], data["fB"]51        assert m["cout"] == pytest.approx(4180.0) and f["cout_net"] == pytest.approx(2180.0) and m["kwh"] == pytest.approx(880.0)52        assert f["economie_courante"] == pytest.approx(98.05, abs=0.005) and f["n"] == 3153        assert f["van"] == pytest.approx(224.60, abs=0.01) and f["tri"] == pytest.approx(0.0529, abs=5e-5)54        assert f["delai_simple"] == pytest.approx(16.89, abs=0.005) and f["delai_actualise"] == pytest.approx(27.40, abs=0.005)55        assert f["va_economies"] == pytest.approx(2404.60, abs=0.01) and f["cee_net"] == pytest.approx(0.1512, abs=5e-5)56        assert f["cee_brut"] == pytest.approx(0.2899, abs=5e-5)5758    def test_combinaison_non_additive(self, data):59        mm = data["mm"]60        assert mm["chauffage_kwh"] == pytest.approx(11000.0) and mm["eco_additive_kwh"] == pytest.approx(4180.0)61        assert mm["AB"]["kwh"] == pytest.approx(3916.0) and mm["AB"]["kwh"] < mm["eco_additive_kwh"]62        assert data["fAB"]["van"] == pytest.approx(-8553.09, abs=0.01) and data["fAB"]["va_economies"] == pytest.approx(5806.91, abs=0.01)6364    def test_decision_incrementale(self, data):65        mm, f = data["mm"], data["fI"]66        assert mm["cout_tp_standard"] == pytest.approx(13944.66, abs=0.01) and mm["subvention_tp_standard"] == pytest.approx(1800.0)67        assert mm["surcout_climat_froid"] == pytest.approx(2555.34, abs=0.01) and mm["surcout_net_climat_froid"] == pytest.approx(35.34, abs=0.01)68        assert f["van"] == pytest.approx(3226.97, abs=0.01) and f["va_economies"] == pytest.approx(3262.31, abs=0.01)69        assert f["van"] > 0 and data["fA"]["van"] < 07071    def test_identites(self, data):72        for f in (data["fA"], data["fB"], data["fAB"], data["fI"]):73            # VAN = −coût net + VA des économies ; cumul actualisé final = VAN ; VAN au TRI = 074            assert f["van"] == pytest.approx(-f["cout_net"] + f["va_economies"], abs=1e-9)75            assert f["cumul_actualise"][-1] == pytest.approx(f["van"], abs=1e-9)76            if not math.isnan(f["tri"]): assert fin.van(f["flux"], f["tri"]) == pytest.approx(0.0, abs=1e-6)77            # économies croissantes au taux g78            assert f["flux"][2] / f["flux"][1] == pytest.approx(1 + f["g"], abs=1e-12)79            # annuité : coût net × CRF ; coût de l'énergie économisée = annuité / kWh80            assert f["annuite_cout_net"] == pytest.approx(f["cout_net"] * fin.facteur_recouvrement(f["r"], f["n"]), abs=1e-9)818283class TestSeuilsEtSensibilite:84    def test_seuils_thermopompe(self, data):85        s = cas.seuils(data["mm"]["A"])86        assert s["cout_net_equilibre"] == pytest.approx(data["fA"]["va_economies"], abs=1e-9)87        assert s["subvention_equilibre"] == pytest.approx(11606.54, abs=0.01)88        assert s["kwh_equilibre"] == pytest.approx(8683.0, abs=1.0) and s["fraction_chauffage_equilibre"] == pytest.approx(0.789, abs=5e-4)89        assert s["g_equilibre"] == pytest.approx(0.1440, abs=5e-4)90        assert cas.flux_mesure(data["mm"]["A"], g=s["g_equilibre"])["van"] == pytest.approx(0.0, abs=0.05)9192    def test_grille(self, data):93        G = cas.grille_van(data["mm"]["A"])94        assert G.loc[0.0458, 0.03] == pytest.approx(data["fA"]["van"], abs=1e-9)95        # VAN décroissante dans le taux, croissante dans la croissance du prix96        assert (np.diff(G.values, axis=0) < 0).all() and (np.diff(G.values, axis=1) > 0).all()97        GB = cas.grille_van(data["mm"]["B"])98        assert GB.loc[0.0458, 0.03] == pytest.approx(224.60, abs=0.01) and GB.loc[0.02, 0.0] > 0 and GB.loc[0.10, 0.06] < 099100    def test_duree_et_tornade(self, data):101        D = cas.sensibilite_duree(data["mm"]["A"])102        assert D.loc[15, 0.0458] == pytest.approx(data["fA"]["van"], abs=1e-9) and (np.diff(D.values, axis=0) > 0).all()103        T = cas.sensibilite_tornade(data["mm"]["A"])104        assert len(T) == 7 and all(o["base"] == pytest.approx(data["fA"]["van"], abs=1e-9) for o in T)105        sub = [o for o in T if o["param"].startswith("Subvention")][0]106        assert sub["bas"] == pytest.approx(-11606.54, abs=0.01) and sub["haut"] == pytest.approx(-4906.54, abs=0.01)107108109class TestContribution:110    def test_lectures(self, data):111        L = cas.lectures_contribution(data["mm"]["A"], data["fA"], data["vs"])112        assert data["vs"] == pytest.approx(637952.85, abs=0.01)113        assert L["ratio_va_cout"] == pytest.approx(0.297, abs=5e-4) and L["ratio_va_cout_net"] == pytest.approx(0.402, abs=5e-4)114        assert L["primes_dollars"]["Europe (méta-analyse)"] == pytest.approx(14800.51, abs=0.01)115        assert L["primes_dollars"]["Monde (méta-analyse)"] == pytest.approx(26794.02, abs=0.01)116        assert L["primes_dollars"]["Amérique du Nord (méta-analyse)"] == pytest.approx(34194.27, abs=0.01)117        LB = cas.lectures_contribution(data["mm"]["B"], data["fB"], data["vs"])118        assert LB["ratio_va_cout_net"] == pytest.approx(1.103, abs=5e-4)119120    def test_economies_restantes(self, data):121        m = data["mm"]["A"]122        assert cas.va_economies_restantes(m, 0) == pytest.approx(data["fA"]["va_economies"], abs=1e-9)123        assert cas.va_economies_restantes(m, 5) == pytest.approx(3923.88, abs=0.01)124        assert cas.va_economies_restantes(m, 10) == pytest.approx(2360.94, abs=0.01)125        assert cas.va_economies_restantes(m, 15) == pytest.approx(0.0, abs=1e-9)126127    def test_paires_qualite(self, data):128        P = cas.paires_qualite(data["ventes"], data["modele"])129        assert P["resultat"]["n"] == 30 and len(P["paires"]) == 30130        assert P["mediane_pct"] == pytest.approx(0.0578, abs=5e-5) and P["moyenne_pct"] == pytest.approx(0.0465, abs=5e-5)131        assert P["ecart_type_pct"] == pytest.approx(0.1364, abs=5e-5) and P["erreur_type_pct"] == pytest.approx(0.0249, abs=5e-5)132        assert P["effet_hedonique_pct"] == pytest.approx(0.0630, abs=5e-5) and P["beta_qualite"] == pytest.approx(0.06108, abs=5e-6)133        # chaque vente n'entre que dans une paire ; différence = prix haut − prix bas ajusté134        assert P["paires"]["id_bas"].is_unique and P["paires"]["id_haut"].is_unique135        assert np.allclose(P["paires"]["difference"], P["paires"]["prix_haut"] - P["paires"]["prix_bas_ajuste"])136        C = cas.contribution_renovation(P, data["vs"])137        assert C["contribution_paires"] == pytest.approx(36891.23, abs=0.01) and C["contribution_hedonique"] == pytest.approx(40181.62, abs=0.01)138        assert C["ratio_paires"] == pytest.approx(0.568, abs=5e-4) and C["ratio_hedonique"] == pytest.approx(0.618, abs=5e-4)139        assert C["van_renovation"] == pytest.approx(-28108.77, abs=0.01)140141    def test_fin_de_vie(self):142        F = cas.composantes_fin_de_vie()143        assert len(F) == 5 and list(F["composante"][:2]) == ["Ventilateur récupérateur de chaleur (VRC)", "Entrée asphaltée"]144        assert (F["ratio"] >= 0.90).all() and F["ratio"].iloc[0] == pytest.approx(1.0)145146147@pytest.fixture(scope="module")148def ex():149    return cas.exercices()150151152class TestExercices:153154    def test_ex1(self, ex):155        assert ex["ex1"][18000.0]["total"] == pytest.approx(1578.78, abs=0.005) and ex["ex1"][26000.0]["total"] == pytest.approx(2470.14, abs=0.005)156        assert ex["ex1"][18000.0]["prix_moyen"] == pytest.approx(0.0877, abs=5e-5) and ex["ex1"][26000.0]["prix_moyen"] == pytest.approx(0.0950, abs=5e-5)157        assert ex["ex1"]["economie_1000_kwh_a_26000"] == pytest.approx(111.42, abs=0.005) and ex["ex1"]["economie_1000_kwh_a_15000"] == pytest.approx(86.96, abs=0.005)158159    def test_ex2(self, ex):160        assert ex["ex2"]["standard"] == 1200.0 and ex["ex2"]["froid"] == 2880.0 and ex["ex2"]["froid_60000"] == 6700.0161        assert ex["ex2"]["capacite_plafond_btu"] == pytest.approx(55833.33, abs=0.01)162163    def test_ex3_fenetres(self, ex):164        f = ex["ex3"]["flux"]165        assert ex["ex3"]["mesure"]["subvention"] == 4500.0 and f["cout_net"] == pytest.approx(17811.0)166        assert f["van"] == pytest.approx(-16213.20, abs=0.01) and f["va_economies"] == pytest.approx(1597.80, abs=0.01)167        assert f["cee_net"] == pytest.approx(1.8396, abs=5e-5) and ex["ex3"]["sans_subvention"]["van"] == pytest.approx(-20713.20, abs=0.01)168169    def test_ex4(self, ex):170        assert ex["ex4"]["r458"]["cee_net"] == pytest.approx(0.1512, abs=5e-5) and ex["ex4"]["r458"]["cee_brut"] == pytest.approx(0.2899, abs=5e-5)171        assert ex["ex4"]["r8"]["cee_net"] == pytest.approx(0.2183, abs=5e-5) and ex["ex4"]["sans_sub"]["van"] == pytest.approx(-1775.40, abs=0.01)172173    def test_ex5(self, ex):174        e = ex["ex5"]175        assert e["europe"] == pytest.approx(14800.51, abs=0.01) and e["amerique"] == pytest.approx(34194.27, abs=0.01)176        assert e["va_economies_AB"] == pytest.approx(5806.91, abs=0.01) and e["va_economies_AB_31"] == pytest.approx(10700.48, abs=0.01)177178    def test_ex6(self, ex):179        assert ex["ex6"]["g_equilibre"] == pytest.approx(0.1440, abs=5e-4) and ex["ex6"]["kwh_equilibre"] == pytest.approx(8683.0, abs=1.0)180181    def test_ex7(self, ex):182        assert ex["ex7"]["base"]["resultat"]["n"] == 30 and ex["ex7"]["large"]["resultat"]["n"] == 59 and ex["ex7"]["serre"]["resultat"]["n"] == 4183        assert ex["ex7"]["large"]["mediane_pct"] == pytest.approx(0.0604, abs=5e-5) and ex["ex7"]["serre"]["mediane_pct"] == pytest.approx(0.0092, abs=5e-5)184        assert ex["ex7"]["kennedy"] == pytest.approx(0.06298, abs=5e-6)185
Files · 2a26d365cc23544c8343a62de5e56cfc4c06cb46
Menu

Theme