diff --git a/product/ERP5/Document/FloatEquivalenceTester.py b/product/ERP5/Document/FloatEquivalenceTester.py index a36aa9bd3612bf7ff11f6e71b5d554c97bded562..e30c4ed746cf50472ada76ac39596f1975e4c639 100644 --- a/product/ERP5/Document/FloatEquivalenceTester.py +++ b/product/ERP5/Document/FloatEquivalenceTester.py @@ -33,6 +33,9 @@ from Products.ERP5Type.Core.Predicate import Predicate from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5.mixin.equivalence_tester import EquivalenceTesterMixin +# On Python >= 2.6, we could compute a value based on sys.float_info.epsilon +DEFAULT_PRECISION = 1e-12 + class FloatEquivalenceTester(Predicate, EquivalenceTesterMixin): """ Compare float values, with support for rounding. """ @@ -79,12 +82,20 @@ class FloatEquivalenceTester(Predicate, EquivalenceTesterMixin): prevision_value = self._round(prevision_value) delta = decision_value - prevision_value + if type(delta) is float: + # XXX: What if prevision or decision is 0 ? + # How to know if the other value is negligible or not ? + epsilon = abs(prevision_value * DEFAULT_PRECISION) + __lt__ = lambda a, b: a < b - epsilon + else: + from operator import __lt__ + # XXX we should use appropriate property sheets and getter methods # for these properties. # Maybe, but beware of default values of quantity when doing so absolute_tolerance_min = self.getProperty('quantity_range_min') if absolute_tolerance_min is not None and \ - delta < absolute_tolerance_min: + __lt__(delta, absolute_tolerance_min): return ( prevision_value, decision_value, 'The difference of ${property_name} between decision and prevision is less than ${value}.', @@ -92,7 +103,7 @@ class FloatEquivalenceTester(Predicate, EquivalenceTesterMixin): value=absolute_tolerance_min)) absolute_tolerance_max = self.getProperty('quantity_range_max') if absolute_tolerance_max is not None and \ - delta > absolute_tolerance_max: + __lt__(absolute_tolerance_max, delta): return ( prevision_value, decision_value, 'The difference of ${property_name} between decision and prevision is larger than ${value}.', diff --git a/product/ERP5/tests/testDivergenceTester.py b/product/ERP5/tests/testDivergenceTester.py index da284a53ef99e2b88d56f1c976f0523b87a9fe16..204d040a9d56485d36bcac07b865b186188ac0a5 100644 --- a/product/ERP5/tests/testDivergenceTester.py +++ b/product/ERP5/tests/testDivergenceTester.py @@ -139,6 +139,15 @@ class TestDivergenceTester(TestPackingListMixin, ERP5TypeTestCase): movement = sequence.get('movement') movement.setQuantity(sim_mvt.getQuantity()) + def stepSetPreviousQuantityWithEpsilon(self, sequence=None, + sequence_list=None, **kw): + sim_mvt = sequence.get('sim_mvt') + movement = sequence.get('movement') + prevision = sim_mvt.getQuantity() + decision = prevision * (1 + 1e-15) + self.assertNotEqual(prevision, decision) + movement.setQuantity(decision) + def stepAddQuantityDivergenceTester(self, sequence=None, sequence_list=None, **kw): """ @@ -155,17 +164,19 @@ class TestDivergenceTester(TestPackingListMixin, ERP5TypeTestCase): if not run: return sequence_list = SequenceList() # Create a clean packing list - sequence_string = ' \ - stepGetPackingList \ - stepCheckPackingListIsNotDivergent \ - stepSetNewQuantity \ - stepCheckPackingListIsNotDivergent \ - stepAddQuantityDivergenceTester \ - stepCheckPackingListIsDivergent \ - stepSetPreviousQuantity \ - stepCheckPackingListIsNotDivergent \ - Tic \ - ' + sequence_string = """ + GetPackingList + CheckPackingListIsNotDivergent + SetNewQuantity + CheckPackingListIsNotDivergent + AddQuantityDivergenceTester + CheckPackingListIsDivergent + SetPreviousQuantity + CheckPackingListIsNotDivergent + SetPreviousQuantityWithEpsilon + CheckPackingListIsNotDivergent + Tic + """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self, quiet=self.quiet) @@ -211,19 +222,19 @@ class TestDivergenceTester(TestPackingListMixin, ERP5TypeTestCase): if not run: return sequence_list = SequenceList() # Create a clean packing list - sequence_string = ' \ - stepGetPackingList \ - stepCheckPackingListIsNotDivergent \ - stepSetNewSource \ - stepCheckPackingListIsNotDivergent \ - stepAddCategoryDivergenceTester \ - stepCheckPackingListIsNotDivergent \ - stepConfigureCategoryDivergenceTesterForSource \ - stepCheckPackingListIsDivergent \ - stepSetPreviousSource \ - stepCheckPackingListIsNotDivergent \ - Tic \ - ' + sequence_string = """ + GetPackingList + CheckPackingListIsNotDivergent + SetNewSource + CheckPackingListIsNotDivergent + AddCategoryDivergenceTester + CheckPackingListIsNotDivergent + ConfigureCategoryDivergenceTesterForSource + CheckPackingListIsDivergent + SetPreviousSource + CheckPackingListIsNotDivergent + Tic + """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self, quiet=self.quiet) @@ -269,19 +280,19 @@ class TestDivergenceTester(TestPackingListMixin, ERP5TypeTestCase): if not run: return sequence_list = SequenceList() # Create a clean packing list - sequence_string = ' \ - stepGetPackingList \ - stepCheckPackingListIsNotDivergent \ - stepSetNewStartDate \ - stepCheckPackingListIsNotDivergent \ - stepAddPropertyDivergenceTester \ - stepCheckPackingListIsNotDivergent \ - stepConfigurePropertyDivergenceTesterForStartDate \ - stepCheckPackingListIsDivergent \ - stepSetPreviousStartDate \ - stepCheckPackingListIsNotDivergent \ - Tic \ - ' + sequence_string = """ + GetPackingList + CheckPackingListIsNotDivergent + SetNewStartDate + CheckPackingListIsNotDivergent + AddPropertyDivergenceTester + CheckPackingListIsNotDivergent + ConfigurePropertyDivergenceTesterForStartDate + CheckPackingListIsDivergent + SetPreviousStartDate + CheckPackingListIsNotDivergent + Tic + """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self, quiet=self.quiet) @@ -319,19 +330,19 @@ class TestDivergenceTester(TestPackingListMixin, ERP5TypeTestCase): if not run: return sequence_list = SequenceList() # Create a clean packing list - sequence_string = ' \ - stepGetPackingList \ - stepCheckPackingListIsNotDivergent \ - stepSetNewAggregate \ - stepCheckPackingListIsNotDivergent \ - stepAddCategoryDivergenceTester \ - stepCheckPackingListIsNotDivergent \ - stepConfigureCategoryDivergenceTesterForAggregate \ - stepCheckPackingListIsDivergent \ - stepSetPreviousAggregate \ - stepCheckPackingListIsNotDivergent \ - Tic \ - ' + sequence_string = """ + GetPackingList + CheckPackingListIsNotDivergent + SetNewAggregate + CheckPackingListIsNotDivergent + AddCategoryDivergenceTester + CheckPackingListIsNotDivergent + ConfigureCategoryDivergenceTesterForAggregate + CheckPackingListIsDivergent + SetPreviousAggregate + CheckPackingListIsNotDivergent + Tic + """ sequence_list.addSequenceString(sequence_string) sequence_list.play(self, quiet=self.quiet) diff --git a/product/ERP5Legacy/Document/PropertyDivergenceTester.py b/product/ERP5Legacy/Document/PropertyDivergenceTester.py index fa22cff9d18ae21a1db1b9bc8ca66bc61d13f6e9..b8bbf107240df3af7c7fa0f0c571dbc09318d388 100644 --- a/product/ERP5Legacy/Document/PropertyDivergenceTester.py +++ b/product/ERP5Legacy/Document/PropertyDivergenceTester.py @@ -33,6 +33,7 @@ from AccessControl import ClassSecurityInfo from Products.ERP5Type.XMLObject import XMLObject from Products.ERP5Type.DivergenceMessage import DivergenceMessage from Products.ERP5Type import Permissions, PropertySheet, interfaces +from Products.ERP5.Document.FloatEquivalenceTester import DEFAULT_PRECISION class PropertyDivergenceTester(XMLObject): """ @@ -88,6 +89,13 @@ class PropertyDivergenceTester(XMLObject): delivery_mvt_property = delivery_mvt_getProperty(tested_property_id) simulation_mvt_property = simulation_movement_getProperty(tested_property_id) if delivery_mvt_property != simulation_mvt_property: + try: + # XXX: What if prevision or decision is 0 ? + if abs(delivery_mvt_property - simulation_mvt_property) <= \ + abs(simulation_mvt_property * DEFAULT_PRECISION): + continue + except TypeError: + pass message = DivergenceMessage( divergence_scope='property', object_relative_url=delivery_mvt.getRelativeUrl(), diff --git a/product/ERP5Legacy/Document/QuantityDivergenceTester.py b/product/ERP5Legacy/Document/QuantityDivergenceTester.py index df85d6379026f8d2703697a181bd24fca57e3041..032b89c89f3113f1964c2e97d474dad216f7459d 100644 --- a/product/ERP5Legacy/Document/QuantityDivergenceTester.py +++ b/product/ERP5Legacy/Document/QuantityDivergenceTester.py @@ -32,6 +32,7 @@ from AccessControl import ClassSecurityInfo from Products.ERP5Type.DivergenceMessage import DivergenceMessage from Products.ERP5Type import Permissions, PropertySheet, Constraint, interfaces +from Products.ERP5.Document.FloatEquivalenceTester import DEFAULT_PRECISION from Products.ERP5Legacy.Document.PropertyDivergenceTester import \ PropertyDivergenceTester @@ -150,8 +151,7 @@ class QuantityDivergenceTester(PropertyDivergenceTester): == Decimal(str(y)).quantize(Decimal(self.getDecimalExponent()), rounding=rounding_option)) - else: - return x==y + return abs(x - y) <= abs(y * DEFAULT_PRECISION) # XXX: What if x or y is 0 ? def getTestedProperty(self, default=None): """ diff --git a/product/ERP5Legacy/tests/testLegacyTradeModelLine.py b/product/ERP5Legacy/tests/testLegacyTradeModelLine.py index b1da83bfe964ecf8d9648c97552bc7129c4ec6c7..4d61c844bea811bcf3f4a342e884f4ada91ed1ca 100644 --- a/product/ERP5Legacy/tests/testLegacyTradeModelLine.py +++ b/product/ERP5Legacy/tests/testLegacyTradeModelLine.py @@ -133,7 +133,7 @@ def checkTradeModelRuleSimulationExpand(self, delivery): total_price = expected_result_dict[use].get(line.getId()) if total_price: sm = result_dict.pop(use) - self.assertEqual(sm.getTotalPrice(), total_price) + self.assertEqual(str(sm.getTotalPrice()), str(total_price)) self.assertEqual(1, len(sm.getCausalityValueList())) self.assertEqual(1, len(sm.getCausalityValueList( portal_type='Business Path')))