Coverage for tests/test_fixed_plant_adjustments.py: 100%

38 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-06-16 23:05 +0000

1"""Tests for fixed plant seasonal adjustment helpers.""" 

2 

3import pandas as pd 

4import pytest 

5from prepare_times_nz.stage_4.electricity.fixed_plant_adjustments import ( 

6 extract_season_from_timeslice, 

7 format_fixed_plant_adjustment_output, 

8 join_fixed_plants_to_renewable_availability, 

9 prepare_renewable_availability_for_join, 

10) 

11 

12 

13def test_extract_season_from_timeslice_handles_full_and_parent_slices(): 

14 """ 

15 TIMES time slices should map cleanly onto the seasonal join key. 

16 """ 

17 

18 assert extract_season_from_timeslice("WIN-WK-P") == "WIN" 

19 assert extract_season_from_timeslice("SPR-") == "SPR" 

20 

21 

22def test_prepare_renewable_availability_for_join_adds_season_and_drops_year_zero(): 

23 """ 

24 Join prep should ignore interpolation rows and retain concrete curve years. 

25 """ 

26 

27 renewable = pd.DataFrame( 

28 { 

29 "TimeSlice": ["WIN-WK-P", "WIN-WE-N"], 

30 "LimType": ["UP", "UP"], 

31 "Attribute": ["NCAP_AF", "NCAP_AF"], 

32 "NI": [0.6, 0.5], 

33 "SI": [0.4, 0.3], 

34 "Pset_PN": ["ELC_HydRR_*", "ELC_HydRR_*"], 

35 "Year": [0, 2024], 

36 } 

37 ) 

38 

39 result = prepare_renewable_availability_for_join(renewable) 

40 

41 assert result["Season"].tolist() == ["WIN"] 

42 assert "Year" not in result.columns 

43 

44 

45def test_join_fixed_plants_to_renewable_availability_matches_on_pset_and_season(): 

46 """ 

47 Fixed-plant season rows should expand to all matching renewable timeslices. 

48 """ 

49 

50 fixed_plants = pd.DataFrame( 

51 { 

52 "TechName": ["Hydro A", "Hydro A", "Hydro B"], 

53 "TechCode": ["HydRR", "HydRR", "HydRR"], 

54 "Pset_PN": ["ELC_HydRR_*", "ELC_HydRR_*", "ELC_HydRR_*"], 

55 "Year": [2030, 2030, 2030], 

56 "Region": ["NI", "NI", "SI"], 

57 "Season": ["WIN", "SPR", "WIN"], 

58 "Share": [1.0, 0.5, 1.0], 

59 } 

60 ) 

61 renewable = pd.DataFrame( 

62 { 

63 "TimeSlice": ["WIN-WK-P", "WIN-WE-N", "SPR-WK-D", "SPR-"], 

64 "LimType": ["UP", "UP", "UP", "UP"], 

65 "Attribute": ["NCAP_AF", "NCAP_AF", "NCAP_AF", "NCAP_AFS"], 

66 "NI": [0.6, 0.5, 0.7, 0.8], 

67 "SI": [0.4, 0.3, 0.6, 0.75], 

68 "Pset_PN": ["ELC_HydRR_*"] * 4, 

69 "Year": [2024, 2024, 2024, 2024], 

70 } 

71 ) 

72 

73 result = join_fixed_plants_to_renewable_availability(fixed_plants, renewable) 

74 

75 assert result["TimeSlice"].tolist() == [ 

76 "SPR-", 

77 "SPR-WK-D", 

78 "WIN-WE-N", 

79 "WIN-WK-P", 

80 "WIN-WE-N", 

81 "WIN-WK-P", 

82 ] 

83 assert result["Season"].tolist() == ["SPR", "SPR", "WIN", "WIN", "WIN", "WIN"] 

84 assert result["Year"].tolist() == [2030, 2030, 2030, 2030, 2030, 2030] 

85 assert result["NI"].tolist() == [0.8, 0.7, 0.5, 0.6, 0.5, 0.6] 

86 assert result["SI"].tolist() == [0.75, 0.6, 0.3, 0.4, 0.3, 0.4] 

87 

88 

89def test_format_fixed_plant_adjustment_output_creates_value_and_drops_helper_columns(): 

90 """ 

91 Downstream formatting should emit a reduced commissioning year and an 

92 unmodified following year, then trim join-only fields. 

93 """ 

94 

95 joined = pd.DataFrame( 

96 { 

97 "TechName": ["Hydro A", "Hydro B"], 

98 "TechCode": ["HydRR", "HydRR"], 

99 "Pset_PN": ["ELC_HydRR_*", "ELC_HydRR_*"], 

100 "Year": [2030, 2030], 

101 "Region": ["NI", "SI"], 

102 "Season": ["WIN", "WIN"], 

103 "Share": [0.5, 0.25], 

104 "TimeSlice": ["WIN-WK-P", "WIN-WK-P"], 

105 "LimType": ["UP", "UP"], 

106 "Attribute": ["NCAP_AF", "NCAP_AF"], 

107 "NI": [0.6, 0.6], 

108 "SI": [0.4, 0.4], 

109 } 

110 ) 

111 

112 result = format_fixed_plant_adjustment_output(joined) 

113 

114 assert result["TechName"].tolist() == ["Hydro A", "Hydro A", "Hydro B", "Hydro B"] 

115 assert result["Year"].tolist() == [2030, 2031, 2030, 2031] 

116 assert result["Region"].tolist() == ["NI", "NI", "SI", "SI"] 

117 assert result["Value"].tolist() == [0.3, 0.6, 0.1, 0.4] 

118 assert "NI" not in result.columns 

119 assert "SI" not in result.columns 

120 assert "Pset_PN" not in result.columns 

121 assert "TechCode" not in result.columns 

122 assert "Season" not in result.columns 

123 assert "Share" not in result.columns 

124 

125 

126def test_join_fixed_plants_to_renewable_availability_raises_on_missing_match(): 

127 """ 

128 A missing seasonal renewable curve should fail loudly. 

129 """ 

130 

131 fixed_plants = pd.DataFrame( 

132 { 

133 "TechName": ["Solar A"], 

134 "TechCode": ["SolarTrack"], 

135 "Pset_PN": ["ELC_SolarTrack_*"], 

136 "Year": [2030], 

137 "Region": ["NI"], 

138 "Season": ["SUM"], 

139 "Share": [1.0], 

140 } 

141 ) 

142 renewable = pd.DataFrame( 

143 { 

144 "TimeSlice": ["WIN-WK-P"], 

145 "LimType": ["FX"], 

146 "Attribute": ["NCAP_AF"], 

147 "NI": [0.9], 

148 "SI": [0.8], 

149 "Pset_PN": ["ELC_SolarTrack_*"], 

150 "Year": [2024], 

151 } 

152 ) 

153 

154 with pytest.raises(ValueError, match="could not be matched"): 

155 join_fixed_plants_to_renewable_availability(fixed_plants, renewable)