1+ """Common fixtures for water module tests.
2+
3+ This conftest provides shared fixtures to reduce test boilerplate and ensure
4+ consistent scenario and context setup across water module tests.
5+ """
6+
7+ import pandas as pd
8+ import pytest
9+ from message_ix import Scenario
10+
11+ from message_ix_models import ScenarioInfo
12+ from message_ix_models .model .structure import get_codes
13+ from message_ix_models .util import package_data_path
14+
15+
16+ @pytest .fixture (scope = "function" )
17+ def water_scenario (request , test_context ):
18+ """Create a water module test scenario with standardized setup.
19+
20+ This fixture handles common setup for water module tests:
21+ - Creates a basic scenario with standard sets
22+ - Configures context with water-specific parameters
23+ - Computes nodes from region codelists
24+ - Sets up basin mappings when needed
25+
26+ Parameters are passed via indirect parametrization:
27+
28+ @pytest.mark.parametrize(
29+ "water_scenario",
30+ [
31+ {"regions": "R12", "type_reg": "global", "RCP": "6p0"},
32+ {"regions": "ZMB", "type_reg": "country", "SDG": "baseline"},
33+ ],
34+ indirect=True,
35+ )
36+ def test_something(water_scenario):
37+ scenario = water_scenario["scenario"]
38+ context = water_scenario["context"]
39+
40+ Supported parameters:
41+ - regions: str, default "R12" (e.g., "R11", "R12", "ZMB", "R14")
42+ - type_reg: str, default "global" (options: "global", "country")
43+ - time: str, default "year" (options: "year", "month")
44+ - RCP: str, optional (e.g., "2p6", "6p0", "7p0", "no_climate")
45+ - REL: str, optional (e.g., "low", "med", "high")
46+ - SDG: str/bool, optional (e.g., "baseline", "not_baseline", "ambitious", True)
47+ - nexus_set: str, optional (e.g., "nexus", "cooling")
48+ - setup_basins: bool, default False - whether to setup valid_basins
49+
50+ Returns
51+ -------
52+ dict
53+ Dictionary with keys:
54+ - "scenario": message_ix.Scenario
55+ - "context": message_ix_models.Context
56+ """
57+ # Extract parameters from request.param or use defaults
58+ if hasattr (request , "param" ):
59+ params = request .param if isinstance (request .param , dict ) else {}
60+ else :
61+ params = {}
62+
63+ regions = params .get ("regions" , "R12" )
64+ type_reg = params .get ("type_reg" , "global" )
65+ time = params .get ("time" , "year" )
66+ RCP = params .get ("RCP" )
67+ REL = params .get ("REL" )
68+ SDG = params .get ("SDG" )
69+ nexus_set = params .get ("nexus_set" )
70+ setup_basins = params .get ("setup_basins" , False )
71+
72+ # Setup context
73+ test_context .type_reg = type_reg
74+ test_context .regions = regions
75+ test_context .time = time
76+
77+ if RCP is not None :
78+ test_context .RCP = RCP
79+ if REL is not None :
80+ test_context .REL = REL
81+ if SDG is not None :
82+ test_context .SDG = SDG
83+ if nexus_set is not None :
84+ test_context .nexus_set = nexus_set
85+
86+ # Compute nodes from codes
87+ nodes = get_codes (f"node/{ regions } " )
88+ nodes = list (map (str , nodes [nodes .index ("World" )].child ))
89+ test_context .map_ISO_c = {regions : nodes [0 ]}
90+
91+ # Setup valid basins if requested
92+ if setup_basins :
93+ basin_file = f"basins_by_region_simpl_{ regions } .csv"
94+ basin_path = package_data_path ("water" , "delineation" , basin_file )
95+ df_basins = pd .read_csv (basin_path )
96+ test_context .valid_basins = set (df_basins ["BCU_name" ].astype (str ))
97+
98+ # Create scenario
99+ mp = test_context .get_platform ()
100+ scenario_info = {
101+ "mp" : mp ,
102+ "model" : f"{ request .node .name } /test water model" ,
103+ "scenario" : f"{ request .node .name } /test water scenario" ,
104+ "version" : "new" ,
105+ }
106+ s = Scenario (** scenario_info )
107+ s .add_horizon (year = [2020 , 2030 , 2040 ])
108+ s .add_set ("technology" , ["tech1" , "tech2" ])
109+ s .add_set ("year" , [2020 , 2030 , 2040 ])
110+ s .commit (comment = "basic water test model" )
111+
112+ test_context .set_scenario (s )
113+ test_context ["water build info" ] = ScenarioInfo (s )
114+
115+ return {"scenario" : s , "context" : test_context }
0 commit comments