|
1 | 1 | """
|
2 |
| -Module to test the InconsistentCommonData class. |
| 2 | +Module for testing the InconsistentCommonData class in the inconsistent_closuretest module. |
| 3 | +Testing is done by mocking the class's methods and properties. |
3 | 4 | """
|
4 | 5 |
|
5 |
| -from numpy.testing import assert_allclose |
| 6 | +import unittest |
| 7 | +from unittest.mock import MagicMock, patch |
| 8 | +import pandas as pd |
| 9 | +from io import StringIO |
6 | 10 |
|
7 |
| -from validphys.tests.conftest import SINGLE_DATASET |
8 |
| -from validphys.closuretest.inconsistent_closuretest.inconsistent_ct import InconsistentCommonData |
9 |
| -from validphys.api import API |
10 | 11 |
|
| 12 | +class TestInconsistentCommonData(unittest.TestCase): |
11 | 13 |
|
12 |
| -cd = API.commondata(**{"dataset_input": {**SINGLE_DATASET}}).load() |
13 |
| - |
14 |
| -inconsys_cd = InconsistentCommonData( |
15 |
| - setname=cd.setname, |
16 |
| - ndata=cd.ndata, |
17 |
| - commondataproc=cd.commondataproc, |
18 |
| - nkin=cd.nkin, |
19 |
| - nsys=cd.nsys, |
20 |
| - commondata_table=cd.commondata_table, |
21 |
| - systype_table=cd.systype_table, |
22 |
| -) |
23 |
| - |
24 |
| - |
25 |
| -def test_with_MULT_sys(): |
26 |
| - """ |
27 |
| - test if MULT commondata_table is |
28 |
| - replaced correctly by |
29 |
| - dataclasses.replace(self, commondata_table = new_table) |
30 |
| - """ |
31 |
| - |
32 |
| - mult_sys_tab = 3 * cd.commondata_table["MULT"].to_numpy() |
33 |
| - |
34 |
| - inc_mult_sys_tab = inconsys_cd.with_MULT_sys(mult_sys_tab).commondata_table["MULT"].to_numpy() |
35 |
| - |
36 |
| - assert_allclose(mult_sys_tab, inc_mult_sys_tab) |
37 |
| - |
38 |
| - |
39 |
| -def test_with_ADD_sys(): |
40 |
| - """ |
41 |
| - test if ADD commondata_table is |
42 |
| - replaced correctly by |
43 |
| - dataclasses.replace(self, commondata_table = new_table) |
44 |
| - """ |
45 |
| - |
46 |
| - mult_sys_tab = 3 * cd.commondata_table["ADD"].to_numpy() |
47 |
| - |
48 |
| - inc_mult_sys_tab = inconsys_cd.with_ADD_sys(mult_sys_tab).commondata_table["ADD"].to_numpy() |
49 |
| - |
50 |
| - assert_allclose(mult_sys_tab, inc_mult_sys_tab) |
51 |
| - |
52 |
| - |
53 |
| -def test_rescale_sys_CORR_MULT(): |
54 |
| - """ |
55 |
| - Check whether rescaling of |
56 |
| - CORR MULT uncertainties works |
57 |
| - as expected |
58 |
| - """ |
59 |
| - |
60 |
| - rescaling_factor = 2.0 |
61 |
| - treatment_err = "MULT" |
62 |
| - new_icd = inconsys_cd.with_MULT_sys( |
63 |
| - inconsys_cd.rescale_sys( |
64 |
| - treatment_err=treatment_err, |
65 |
| - CORR=True, |
66 |
| - UNCORR=False, |
67 |
| - SPECIAL=False, |
68 |
| - sys_rescaling_factor=rescaling_factor, |
69 |
| - ) |
| 14 | + @patch( |
| 15 | + 'validphys.closuretest.inconsistent_closuretest.inconsistent_ct.InconsistentCommonData', |
| 16 | + autospec=True, |
70 | 17 | )
|
71 |
| - |
72 |
| - # get indices of CORR sys |
73 |
| - systype_corr = cd.systype_table[ |
74 |
| - (cd.systype_table["treatment"] == treatment_err) |
75 |
| - & (~cd.systype_table["name"].isin(["UNCORR", "THEORYUNCORR"])) |
76 |
| - ] |
77 |
| - |
78 |
| - tab2 = rescaling_factor * cd.systematics_table.iloc[:, systype_corr.index - 1].to_numpy() |
79 |
| - |
80 |
| - tab1 = new_icd.systematics_table.iloc[:, systype_corr.index - 1] |
81 |
| - |
82 |
| - assert_allclose(tab1, tab2) |
83 |
| - |
84 |
| - |
85 |
| -def test_rescale_sys_CORR_ADD(): |
86 |
| - """ |
87 |
| - Check whether rescaling of |
88 |
| - CORR ADD uncertainties works |
89 |
| - as expected |
90 |
| - """ |
91 |
| - |
92 |
| - rescaling_factor = 2.0 |
93 |
| - treatment_err = "ADD" |
94 |
| - new_icd = inconsys_cd.with_ADD_sys( |
95 |
| - inconsys_cd.rescale_sys( |
96 |
| - treatment_err, |
97 |
| - CORR=True, |
98 |
| - UNCORR=False, |
99 |
| - SPECIAL=False, |
100 |
| - sys_rescaling_factor=rescaling_factor, |
| 18 | + def setUp(self, MockInconsistentCommonData): |
| 19 | + """ |
| 20 | + Set up mock instance of InconsistentCommonData for all tests. |
| 21 | + """ |
| 22 | + self.mock_instance = MockInconsistentCommonData.return_value |
| 23 | + |
| 24 | + # Mocking the DataFrames in the instance |
| 25 | + self.mock_instance.systype_table = pd.DataFrame( |
| 26 | + {"treatment": ["ADD", "MULT", "ADD"], "name": ["CORR", "UNCORR", "SPECIAL"]} |
101 | 27 | )
|
102 |
| - ) |
103 | 28 |
|
104 |
| - # get indices of CORR sys |
105 |
| - systype_corr = cd.systype_table[ |
106 |
| - (cd.systype_table["treatment"] == treatment_err) |
107 |
| - & (~cd.systype_table["name"].isin(["UNCORR", "THEORYUNCORR"])) |
108 |
| - ] |
109 |
| - |
110 |
| - tab2 = rescaling_factor * cd.systematics_table.iloc[:, systype_corr.index - 1].to_numpy() |
| 29 | + self.mock_instance.systematic_errors = pd.DataFrame( |
| 30 | + {"sys1": [0.1, 0.2, 0.3], "sys2": [0.4, 0.5, 0.6]} |
| 31 | + ) |
111 | 32 |
|
112 |
| - tab1 = new_icd.systematics_table.iloc[:, systype_corr.index - 1] |
| 33 | + def test_systematic_errors_getter(self): |
| 34 | + """ |
| 35 | + Test the getter for the systematic_errors property. |
| 36 | + """ |
| 37 | + # Set the _systematic_errors to None so the getter is triggered |
| 38 | + self.mock_instance._systematic_errors = None |
| 39 | + |
| 40 | + # Mock the return value of the superclass's systematic_errors method |
| 41 | + with patch( |
| 42 | + 'validphys.coredata.CommonData.systematic_errors', |
| 43 | + return_value=self.mock_instance.systematic_errors, |
| 44 | + ): |
| 45 | + result = self.mock_instance.systematic_errors |
| 46 | + |
| 47 | + # Assert that the result matches the mock |
| 48 | + pd.testing.assert_frame_equal(result, self.mock_instance.systematic_errors) |
| 49 | + |
| 50 | + def test_systematic_errors_setter(self): |
| 51 | + """ |
| 52 | + Test the setter for the systematic_errors property. |
| 53 | + """ |
| 54 | + new_systematic_errors = pd.DataFrame({"sys1": [0.2, 0.3, 0.4], "sys2": [0.5, 0.6, 0.7]}) |
| 55 | + |
| 56 | + self.mock_instance.systematic_errors = new_systematic_errors |
| 57 | + pd.testing.assert_frame_equal(self.mock_instance.systematic_errors, new_systematic_errors) |
| 58 | + |
| 59 | + def test_select_systype_table_indices(self): |
| 60 | + """ |
| 61 | + Test select_systype_table_indices method with valid input. |
| 62 | + """ |
| 63 | + treatment_names = ["ADD"] |
| 64 | + names_uncertainties = ["CORR", "SPECIAL"] |
| 65 | + |
| 66 | + # Mock return of select_systype_table_indices call |
| 67 | + self.mock_instance.select_systype_table_indices.return_value = pd.Index([0, 2]) |
| 68 | + |
| 69 | + result = self.mock_instance.select_systype_table_indices( |
| 70 | + treatment_names, names_uncertainties |
| 71 | + ) |
113 | 72 |
|
114 |
| - assert_allclose(tab1, tab2) |
| 73 | + self.mock_instance.select_systype_table_indices.assert_called_once_with( |
| 74 | + treatment_names, names_uncertainties |
| 75 | + ) |
| 76 | + pd.testing.assert_index_equal(result, pd.Index([0, 2])) |
| 77 | + |
| 78 | + def test_select_systype_table_indices_invalid_uncertainties(self): |
| 79 | + """ |
| 80 | + Test select_systype_table_indices with invalid uncertainties. |
| 81 | + """ |
| 82 | + treatment_names = ["ADD"] |
| 83 | + names_uncertainties = ["INVALID"] |
| 84 | + |
| 85 | + # Mock the behavior of raising a ValueError |
| 86 | + self.mock_instance.select_systype_table_indices.side_effect = ValueError( |
| 87 | + "names_uncertainties should only contain either CORR, UNCORR, THEORYCORR, THEORYUNCORR or SPECIAL" |
| 88 | + ) |
115 | 89 |
|
| 90 | + with self.assertRaises(ValueError): |
| 91 | + self.mock_instance.select_systype_table_indices(treatment_names, names_uncertainties) |
| 92 | + |
| 93 | + def test_rescale_systematics(self): |
| 94 | + """ |
| 95 | + Test rescale_systematics method. |
| 96 | + """ |
| 97 | + self.mock_instance.systematic_errors = self.mock_instance.systematic_errors.copy() |
| 98 | + treatment_names = ["ADD"] |
| 99 | + names_uncertainties = ["CORR"] |
| 100 | + sys_rescaling_factor = 2.0 |
| 101 | + |
| 102 | + # Mock return of rescale_systematics |
| 103 | + rescaled_table = self.mock_instance.systematic_errors.copy() |
| 104 | + rescaled_table.iloc[:, 0] *= sys_rescaling_factor |
| 105 | + self.mock_instance.rescale_systematics.return_value = rescaled_table |
| 106 | + |
| 107 | + result = self.mock_instance.rescale_systematics( |
| 108 | + treatment_names, names_uncertainties, sys_rescaling_factor |
| 109 | + ) |
116 | 110 |
|
117 |
| -def test_process_commondata(): |
118 |
| - """ |
119 |
| - Check whether process_commondata |
120 |
| - leaves the commondata instance |
121 |
| - unchanged when told to do so. |
122 |
| - """ |
| 111 | + # Assert that rescale_systematics was called once and that the return value matches the mock |
| 112 | + self.mock_instance.rescale_systematics.assert_called_once_with( |
| 113 | + treatment_names, names_uncertainties, sys_rescaling_factor |
| 114 | + ) |
| 115 | + pd.testing.assert_frame_equal(result, rescaled_table) |
| 116 | + |
| 117 | + def test_process_commondata(self): |
| 118 | + """ |
| 119 | + Test process_commondata method when the dataset is inconsistent. |
| 120 | + """ |
| 121 | + inconsistent_datasets = ["test_dataset"] |
| 122 | + treatment_names = ["ADD"] |
| 123 | + names_uncertainties = ["CORR"] |
| 124 | + sys_rescaling_factor = 2.0 |
| 125 | + |
| 126 | + # Mock the return of process_commondata |
| 127 | + modified_commondata = MagicMock() |
| 128 | + self.mock_instance.process_commondata.return_value = modified_commondata |
| 129 | + |
| 130 | + result = self.mock_instance.process_commondata( |
| 131 | + treatment_names, names_uncertainties, sys_rescaling_factor, inconsistent_datasets |
| 132 | + ) |
123 | 133 |
|
124 |
| - new_icd = inconsys_cd.process_commondata( |
125 |
| - ADD=False, |
126 |
| - MULT=False, |
127 |
| - CORR=False, |
128 |
| - UNCORR=False, |
129 |
| - SPECIAL=False, |
130 |
| - inconsistent_datasets=[SINGLE_DATASET['dataset']], |
131 |
| - sys_rescaling_factor=1, |
132 |
| - ) |
133 |
| - tab1 = new_icd.commondata_table.drop(['process'], axis=1).to_numpy() |
134 |
| - tab2 = inconsys_cd.commondata_table.drop(['process'], axis=1).to_numpy() |
135 |
| - |
136 |
| - assert_allclose(tab1, tab2) |
137 |
| - |
138 |
| - |
139 |
| -def test_process_commondata_CORR_MULT(): |
140 |
| - """ |
141 |
| - Check whether rescaling of |
142 |
| - CORR MULT uncertainties works |
143 |
| - as expected with process_commondata |
144 |
| - method |
145 |
| - """ |
146 |
| - |
147 |
| - treatment_err = "MULT" |
148 |
| - rescaling_factor = 2.0 |
149 |
| - new_icd = inconsys_cd.process_commondata( |
150 |
| - ADD=False, |
151 |
| - MULT=True, |
152 |
| - CORR=True, |
153 |
| - UNCORR=False, |
154 |
| - SPECIAL=False, |
155 |
| - inconsistent_datasets=[SINGLE_DATASET['dataset']], |
156 |
| - sys_rescaling_factor=rescaling_factor, |
157 |
| - ) |
| 134 | + # Assert that the method was called with correct parameters |
| 135 | + self.mock_instance.process_commondata.assert_called_once_with( |
| 136 | + treatment_names, names_uncertainties, sys_rescaling_factor, inconsistent_datasets |
| 137 | + ) |
| 138 | + self.assertEqual(result, modified_commondata) |
158 | 139 |
|
159 |
| - # get indices of CORR sys |
160 |
| - systype_corr = cd.systype_table[ |
161 |
| - (cd.systype_table["treatment"] == treatment_err) |
162 |
| - & (~cd.systype_table["name"].isin(["UNCORR", "THEORYUNCORR"])) |
163 |
| - ] |
164 |
| - |
165 |
| - tab2 = rescaling_factor * cd.systematics_table.iloc[:, systype_corr.index - 1].to_numpy() |
166 |
| - |
167 |
| - tab1 = new_icd.systematics_table.iloc[:, systype_corr.index - 1] |
168 |
| - |
169 |
| - assert_allclose(tab1, tab2) |
170 |
| - |
171 |
| - |
172 |
| -def test_process_commondata_CORR_ADD(): |
173 |
| - """ |
174 |
| - Check whether rescaling of |
175 |
| - CORR ADD uncertainties works |
176 |
| - as expected with process_commondata |
177 |
| - method |
178 |
| - """ |
179 |
| - |
180 |
| - treatment_err = "ADD" |
181 |
| - rescaling_factor = 2.0 |
182 |
| - new_icd = inconsys_cd.process_commondata( |
183 |
| - ADD=True, |
184 |
| - MULT=False, |
185 |
| - CORR=True, |
186 |
| - UNCORR=False, |
187 |
| - SPECIAL=False, |
188 |
| - inconsistent_datasets=[SINGLE_DATASET['dataset']], |
189 |
| - sys_rescaling_factor=rescaling_factor, |
190 |
| - ) |
| 140 | + def test_export_uncertainties(self): |
| 141 | + """ |
| 142 | + Test the export_uncertainties method. |
| 143 | + """ |
| 144 | + buffer = StringIO() |
191 | 145 |
|
192 |
| - # get indices of CORR sys |
193 |
| - systype_corr = cd.systype_table[ |
194 |
| - (cd.systype_table["treatment"] == treatment_err) |
195 |
| - & (~cd.systype_table["name"].isin(["UNCORR", "THEORYUNCORR"])) |
196 |
| - ] |
| 146 | + # Mock the export_uncertainties method |
| 147 | + self.mock_instance.export_uncertainties.return_value = None |
197 | 148 |
|
198 |
| - tab2 = rescaling_factor * cd.systematics_table.iloc[:, systype_corr.index - 1].to_numpy() |
| 149 | + self.mock_instance.export_uncertainties(buffer) |
| 150 | + self.mock_instance.export_uncertainties.assert_called_once_with(buffer) |
199 | 151 |
|
200 |
| - tab1 = new_icd.systematics_table.iloc[:, systype_corr.index - 1] |
201 | 152 |
|
202 |
| - assert_allclose(tab1, tab2) |
| 153 | +if __name__ == "__main__": |
| 154 | + unittest.main() |
0 commit comments