Skip to content

Commit a6022ee

Browse files
committed
Expand test of .ssp.transport.main()
1 parent 25fffc9 commit a6022ee

File tree

1 file changed

+94
-2
lines changed

1 file changed

+94
-2
lines changed

message_ix_models/tests/project/ssp/test_transport.py

+94-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from typing import TYPE_CHECKING
22

3+
import pandas as pd
34
import pytest
45

56
from message_ix_models.project.ssp.transport import main
7+
from message_ix_models.tests.tools.iea.test_web import user_local_data # noqa: F401
68
from message_ix_models.util import package_data_path
79

810
if TYPE_CHECKING:
@@ -33,19 +35,109 @@ def input_xlsx_path(tmp_path_factory, input_csv_path) -> "pathlib.Path":
3335
return result
3436

3537

38+
# Enumeration/flags for codes appearing in VARIABLE
39+
IN_ = 1 # Data appears in the input file only
40+
OUT = 2 # Data appears in the output file *and* with a modified magnitude
41+
I_O = IN_ | OUT # Both
42+
43+
edt = "Energy|Demand|Transportation"
44+
45+
#: IAMC 'Variable' codes appearing in the input file and/or output file.
46+
VARIABLE = {
47+
(0, f"Emissions|CH4|{edt}"),
48+
(OUT, f"Emissions|CH4|{edt}|Aviation"),
49+
(0, f"Emissions|CH4|{edt}|Aviation|International"),
50+
(I_O, f"Emissions|CH4|{edt}|Road Rail and Domestic Shipping"),
51+
# No emissions factors available for BC
52+
(IN_, f"Emissions|BC|{edt}"),
53+
(IN_, f"Emissions|BC|{edt}|Aviation"),
54+
(IN_, f"Emissions|BC|{edt}|Aviation|International"),
55+
#
56+
(I_O, f"Emissions|CO|{edt}|Aviation"),
57+
(I_O, f"Emissions|CO|{edt}|Road Rail and Domestic Shipping"),
58+
#
59+
(OUT, f"Emissions|N2O|{edt}|Aviation"),
60+
(I_O, f"Emissions|N2O|{edt}|Road Rail and Domestic Shipping"),
61+
#
62+
(IN_, f"Emissions|NH3|{edt}"),
63+
(IN_, f"Emissions|NH3|{edt}|Aviation"),
64+
(IN_, f"Emissions|NH3|{edt}|Aviation|International"),
65+
#
66+
(I_O, f"Emissions|NOx|{edt}|Aviation"),
67+
(I_O, f"Emissions|NOx|{edt}|Road Rail and Domestic Shipping"),
68+
#
69+
(IN_, f"Emissions|OC|{edt}"),
70+
(IN_, f"Emissions|OC|{edt}|Aviation"),
71+
(IN_, f"Emissions|OC|{edt}|Aviation|International"),
72+
# FIXME Should be OUT
73+
(0, f"Emissions|Sulfur|{edt}|Aviation"),
74+
#
75+
(IN_, f"Emissions|VOC|{edt}"),
76+
(I_O, f"Emissions|VOC|{edt}|Aviation"),
77+
(IN_, f"Emissions|VOC|{edt}|Aviation|International"),
78+
(I_O, f"Emissions|VOC|{edt}|Road Rail and Domestic Shipping"),
79+
}
80+
81+
3682
@main.minimum_version
37-
def test_main(tmp_path, input_csv_path) -> None:
83+
# @pytest.mark.usefixtures("user_local_data")
84+
@pytest.mark.parametrize("method", ("A", "B"))
85+
def test_main(tmp_path, test_context, input_csv_path, method) -> None:
3886
"""Code can be called from Python."""
3987
# Locate a temporary data file
4088
path_in = input_csv_path
4189
path_out = tmp_path.joinpath("output.csv")
4290

4391
# Code runs
44-
main(path_in=path_in, path_out=path_out)
92+
main(path_in=path_in, path_out=path_out, method=method)
4593

4694
# Output path exists
4795
assert path_out.exists()
4896

97+
# Read input file
98+
df_in = pd.read_csv(path_in)
99+
100+
# Identify dimension columns
101+
dims_wide = list(df_in.columns)[:5] # …in 'wide' layout
102+
dims = dims_wide + ["Year"] # …in 'long' layout
103+
104+
# Convert wide to long; sort
105+
df_in = df_in.melt(dims_wide, var_name="Year").sort_values(dims)
106+
107+
# Input data already contains the variable names to be modified
108+
exp = {v[1] for v in VARIABLE if IN_ & v[0]}
109+
assert exp <= set(df_in["Variable"].unique())
110+
region = set(df_in["Region"].unique())
111+
112+
# Read output file
113+
df_out = pd.read_csv(path_out).melt(dims_wide, var_name="Year")
114+
115+
# Data have the same length
116+
assert len(df_in) == len(df_out)
117+
118+
# Output has the same set of region codes as input
119+
assert region == set(df_out["Region"].unique())
120+
121+
# Diff data:
122+
# - Outer merge.
123+
# - Compute diff and select rows where diff is larger than a certain value
124+
df = df_in.merge(df_out, how="outer", on=dims).query(
125+
"abs(value_y - value_x) > 1e-16"
126+
)
127+
128+
# df.to_csv("debug0.csv") # DEBUG Dump to file
129+
# print(df.to_string(max_rows=50)) # DEBUG Show in test output
130+
131+
# All of the expected 'variable' codes have been modified
132+
exp = {v[1] for v in VARIABLE if OUT & v[0]}
133+
assert exp == set(df["Variable"].unique())
134+
135+
cond = df.query("value_y < 0")
136+
if len(cond):
137+
msg = "Negative emissions totals after processing"
138+
print(f"\n{msg}:", cond.to_string(), sep="\n")
139+
assert False, msg
140+
49141

50142
@main.minimum_version
51143
def test_cli(tmp_path, mix_models_cli, input_xlsx_path) -> None:

0 commit comments

Comments
 (0)