Skip to content

Commit 7beded8

Browse files
authored
Merge pull request #37912 from mantidproject/ewm5044-ornl-next-2
changes to mantid's `assert_almost_equal` test fixture - `ornl-next`
2 parents 6d29f35 + 1097f77 commit 7beded8

File tree

4 files changed

+134
-24
lines changed

4 files changed

+134
-24
lines changed

Framework/PythonInterface/mantid/_testing/AssertAlmostEqual.py

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
from mantid.simpleapi import CompareWorkspaces
99
from mantid.kernel import Property
1010

11+
# the absolute tolerance to be used if neither atol nor rtol specified
12+
DEFAULT_ABS_TOLERANCE = 1.0e-10
13+
1114

1215
def assert_almost_equal(Workspace1, Workspace2, rtol=Property.EMPTY_DBL, atol=Property.EMPTY_DBL, **kwargs):
1316
"""
@@ -27,26 +30,52 @@ def assert_almost_equal(Workspace1, Workspace2, rtol=Property.EMPTY_DBL, atol=Pr
2730
AssertionError
2831
If Workspace1 and Workspace2 are not equal up to specified precision
2932
ValueError
30-
If atol and rtol are both not provided
33+
If atol or rtol are below zero
34+
ValueError
35+
If kwargs contains keys that cshould instead be set by atol or rtol
3136
3237
"""
3338
# check arguments
34-
if len(set(kwargs.keys()).intersection({"Workspace1", "Workspace2", "Tolerance", "ToleranceRelErr"})):
35-
raise ValueError("Workspace1, Workspace2, Tolerance, ToleranceRelErr cannot be passed as additional parameters")
39+
if len(set(kwargs.keys()).intersection({"Tolerance", "ToleranceRelErr"})):
40+
raise ValueError("Tolerance, ToleranceRelErr cannot be passed as additional parameters: set atol or rtol instead")
41+
if atol < 0.0:
42+
raise ValueError("Absolute tolerance must be nonnegative")
43+
if rtol < 0.0:
44+
raise ValueError("Relative tolerance must be nonnegative")
3645

37-
if rtol == Property.EMPTY_DBL and atol == Property.EMPTY_DBL:
38-
raise ValueError("Specify rtol or atol")
46+
use_relative = rtol != Property.EMPTY_DBL
47+
use_absolute = atol != Property.EMPTY_DBL
3948

40-
if rtol > Property.EMPTY_DBL:
41-
result, message = CompareWorkspaces(Workspace1, Workspace2, Tolerance=rtol, ToleranceRelErr=True, **kwargs)
42-
msg_dict = message.toDict()
43-
if not result:
44-
msg = ", ".join(msg_dict["Message"]) + f", Workspaces are not within relative tolerance ({rtol})"
45-
raise AssertionError(msg)
49+
# perform the required comparisons
4650

47-
if atol > Property.EMPTY_DBL:
48-
result, message = CompareWorkspaces(Workspace1, Workspace2, Tolerance=atol, ToleranceRelErr=False, **kwargs)
51+
# if neither set, do simple absolute comparison
52+
if not use_absolute and not use_relative:
53+
res, message = CompareWorkspaces(Workspace1, Workspace2, Tolerance=DEFAULT_ABS_TOLERANCE, ToleranceRelErr=False, **kwargs)
4954
msg_dict = message.toDict()
50-
if not result:
51-
msg = ", ".join(msg_dict["Message"]) + f", Workspaces are not within absolute tolerance ({atol})"
55+
if res:
56+
return
57+
else:
58+
msg = ", ".join(msg_dict["Message"]) + f", Workspaces are not within default tolerance ({DEFAULT_ABS_TOLERANCE})"
5259
raise AssertionError(msg)
60+
61+
# if rtol set, perform relative comparison
62+
rel_res, rel_msg = True, {}
63+
if use_relative:
64+
rel_res, message = CompareWorkspaces(Workspace1, Workspace2, Tolerance=rtol, ToleranceRelErr=True, **kwargs)
65+
rel_msg = message.toDict()
66+
67+
# if atol set, perform absolute comparison
68+
abs_res, abs_msg = True, {}
69+
if use_absolute:
70+
abs_res, message = CompareWorkspaces(Workspace1, Workspace2, Tolerance=atol, ToleranceRelErr=False, **kwargs)
71+
abs_msg = message.toDict()
72+
73+
# validate the comparison results
74+
75+
msg = ""
76+
if not rel_res:
77+
msg += ", ".join(rel_msg["Message"]) + f", Workspaces are not within relative tolerance ({rtol})"
78+
if not abs_res:
79+
msg += ", ".join(abs_msg["Message"]) + f", Workspaces are not within absolute tolerance ({atol})"
80+
if not rel_res or not abs_res:
81+
raise AssertionError(msg)

Framework/PythonInterface/test/python/mantid/_testing/AssertAlmostEqualTest.py

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import unittest
99
from unittest import mock
1010
from mantid.testing import assert_almost_equal
11-
from mantid.simpleapi import CreateWorkspace
11+
from mantid.simpleapi import CreateWorkspace, CreateSingleValuedWorkspace
1212

1313

1414
class AssertAlmostEqualTest(unittest.TestCase):
@@ -21,8 +21,16 @@ def setUpClass(self):
2121
self.ws2 = ws2
2222
self.ws3 = ws3
2323

24+
# SIMPLE CASES
25+
26+
def test_noargs(self):
27+
# compare (ws1 - ws2) < 1e-10
28+
another1 = self.ws1.clone()
29+
assert_almost_equal(self.ws1, another1)
30+
2431
def test_simple(self):
25-
assert_almost_equal(self.ws1, self.ws2, atol=1, rtol=1)
32+
# simple test with wide tolerances to always pass
33+
assert_almost_equal(self.ws1, self.ws2, atol=1, rtol=2)
2634

2735
def test_atol(self):
2836
# compare (ws1 - ws2) < atol
@@ -32,10 +40,82 @@ def test_rtol(self):
3240
# compare (ws1 - ws2) / (0.5 * (ws1 + ws2)) < rtol
3341
assert_almost_equal(self.ws1, self.ws3, rtol=0.7)
3442

35-
def test_raises(self):
43+
# VALIDATION TESTS
44+
45+
def test_validate_forbidden_keys(self):
46+
with self.assertRaises(TypeError):
47+
assert_almost_equal(self.ws1, self.ws1, Workspace1=self.ws3)
48+
with self.assertRaises(TypeError):
49+
assert_almost_equal(self.ws1, self.ws1, Workspace2=self.ws3)
50+
with self.assertRaises(ValueError):
51+
assert_almost_equal(self.ws1, self.ws1, Tolerance=0.01)
52+
with self.assertRaises(ValueError):
53+
assert_almost_equal(self.ws1, self.ws1, ToleranceRelErr=True)
54+
55+
def test_validate_atol(self):
56+
with self.assertRaises(ValueError):
57+
assert_almost_equal(self.ws1, self.ws2, atol=-1.0, rtol=1.0)
58+
59+
def test_validate_rtol(self):
3660
with self.assertRaises(ValueError):
61+
assert_almost_equal(self.ws1, self.ws2, ato1=1.0, rtol=-1.0)
62+
63+
# NEGATIVE TESTS
64+
65+
def test_fail_unequal(self):
66+
with self.assertRaises(AssertionError):
3767
assert_almost_equal(self.ws1, self.ws2)
3868

69+
def test_fail_absolute(self):
70+
with self.assertRaises(AssertionError):
71+
assert_almost_equal(self.ws1, self.ws2, atol=1e-3)
72+
73+
def test_fail_relative(self):
74+
with self.assertRaises(AssertionError):
75+
assert_almost_equal(self.ws1, self.ws2, rtol=1.0e-4)
76+
77+
# MIXED CASES
78+
79+
def test_both_atol_fails(self):
80+
atol = 0.01
81+
rtol = 0.01
82+
ts1 = CreateSingleValuedWorkspace(1000000.1)
83+
ts2 = CreateSingleValuedWorkspace(1000000.0)
84+
# ensure rtol passes, atol fails separately
85+
assert_almost_equal(ts1, ts2, rtol=rtol)
86+
with self.assertRaises(AssertionError):
87+
assert_almost_equal(ts1, ts2, atol=atol)
88+
# ensure both fail
89+
with self.assertRaises(AssertionError):
90+
assert_almost_equal(ts1, ts2, atol=atol, rtol=rtol)
91+
92+
def test_both_rtol_fails(self):
93+
atol = 0.01
94+
rtol = 0.01
95+
tes1 = CreateSingleValuedWorkspace(0.00001)
96+
tes2 = CreateSingleValuedWorkspace(0.00010)
97+
# ensure atol passes, rtol fails separately
98+
assert_almost_equal(tes1, tes2, atol=atol)
99+
with self.assertRaises(AssertionError):
100+
assert_almost_equal(tes1, tes2, rtol=rtol)
101+
# ensure both fail
102+
with self.assertRaises(AssertionError):
103+
assert_almost_equal(tes1, tes2, atol=atol, rtol=rtol)
104+
105+
def test_both_both_fail(self):
106+
atol = 0.01
107+
rtol = 0.01
108+
ts1 = CreateSingleValuedWorkspace(100.01)
109+
ts2 = CreateSingleValuedWorkspace(200.02)
110+
# ensure rtol, atol fail separately
111+
with self.assertRaises(AssertionError):
112+
assert_almost_equal(ts1, ts2, atol=atol)
113+
with self.assertRaises(AssertionError):
114+
assert_almost_equal(ts1, ts2, rtol=rtol)
115+
# ensure both fail
116+
with self.assertRaises(AssertionError):
117+
assert_almost_equal(ts1, ts2, atol=atol, rtol=rtol)
118+
39119

40120
if __name__ == "__main__":
41121
unittest.main()

docs/source/api/python/mantid/testing/assert_almost_equal.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
=====================
66

77
This is a Python function for testing if two modules are within a tolerance.
8-
At least ``rtol`` or ``atol`` parameters should be specified. Neither being
9-
specified generates a ``ValueError`` exception. Both being specified runs
10-
the underlying :ref:`algm-CompareWorkspaces` algorithm
11-
twice, with relative tolerance being first.
12-
13-
8+
If ``rtol`` is specified, will compare using the relative difference.
9+
If ``atol`` is specified, will compare using the absolute difference.
10+
One or both of ``rtol`` and ``atol`` may be specified.
11+
Will run the underlying :ref:`algm-CompareWorkspaces` algorithm for each
12+
case specified, and fail if any of the comparisons fail.
13+
If neither ``rtol`` nor ``atol`` is specified, will perform an absolute compatison to within 1.e-10.
1414

1515
.. module:`mantid.testing`
1616
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Fix python fuction ``assert_almost_equal`` to fail for non-equal workspaces

0 commit comments

Comments
 (0)