← Back to team overview

oship-dev team mailing list archive

[Branch ~oship-dev/oship/devel] Rev 488: Fixed bug #610972 .

 

Merge authors:
  Diego Manhães Pinheiro (dmpinheiro)
------------------------------------------------------------
revno: 488 [merge]
fixes bug(s): https://launchpad.net/bugs/610972
committer: Diego Manhães Pinheiro <dmpinheiro@xxxxxxxxx>
branch nick: trunk
timestamp: Thu 2010-09-16 17:25:44 -0300
message:
  Fixed bug #610972 .
added:
  src/oship/openehr/rm/datatypes/quantity/tests/dvamount.txt
modified:
  src/oship/openehr/rm/datatypes/quantity/__init__.py
  src/oship/openehr/rm/datatypes/quantity/interfaces.py
  src/oship/openehr/rm/datatypes/quantity/tests/dvquantified.py


--
lp:oship
https://code.launchpad.net/~oship-dev/oship/devel

Your team OSHIP Development Team is subscribed to branch lp:oship.
To unsubscribe from this branch go to https://code.launchpad.net/~oship-dev/oship/devel/+edit-subscription
=== modified file 'src/oship/openehr/rm/datatypes/quantity/__init__.py'
--- src/oship/openehr/rm/datatypes/quantity/__init__.py	2010-09-07 21:28:23 +0000
+++ src/oship/openehr/rm/datatypes/quantity/__init__.py	2010-09-16 20:21:31 +0000
@@ -1,5 +1,7 @@
 # -*- coding: UTF-8 -*-
 
+
+import copy
 from zope.schema.fieldproperty import FieldProperty
 import grok
 
@@ -7,7 +9,6 @@
 from oship.openehr.rm.datatypes.text import DvCodedText, DvText
 from oship.openehr.rm.support import Interval
 
-
 from interfaces import *
 
 
@@ -17,8 +18,6 @@
 
 
 class DvOrdered(DataValue):
-    
-
     grok.implements(IDvOrdered)
 
     normal_range = FieldProperty(IDvOrdered['normal_range'])
@@ -120,88 +119,97 @@
 
 
 class DvQuantified(DvOrdered):
-    """
-    Abstract class defining the concept of true quantified values, i.e. values which are
-    not only ordered, but which have a precise magnitude.
-    """
-
     grok.implements(IDvQuantified)
 
-    def __init__(self,magnitude,accuracy,normalRange,otherReferenceRanges,normalStatus, magnitudeStatus=None):
+
+
+
+    def __init__(self, magnitude, accuracy=None, normal_range=None, other_reference_ranges=None, normal_status=None, magnitude_status=None):
         self.magnitude=magnitude
         self.accuracy=accuracy
-        if magnitudeStatus is not None:
-            if self.validMagnitudeStatus(magnitudeStatus):
-                self.magnitudeStatus = magnitudeStatus
+        if magnitude_status is not None:
+            if self.valid_magnitude_status(magnitude_status):
+                self.magnitude_status = magnitude_status
             else:
-                raise ValueError(u"magnitudeStatus must be '=', '>', '<', '<=', '>=', '~' or None")
+                raise ValueError(u"magnitude status must be '=', '>', '<', '<=', '>=', '~' or None")
         else:
-            self.magnitudeStatus = None
-        DvOrdered.__init__(self,normalRange,otherReferenceRanges,normalStatus)
+            self.magnitude_status = None
+        super(DvQuantified,self).__init__(normal_range, other_reference_ranges, normal_status)
 
-    def validMagnitudeStatus(self,val):
-        """
-        Test whether a string 'val' is one of the valid values for the magnitude_status attribute.
-        """
+    def valid_magnitude_status(self,val):
         return val in ['=','>','<','<=','>=','~']
 
+    def accuracy_unknown(self):
+        raise NotImplementedError("This method must be implemented on the class.")
+
 
 class DvAbsoluteQuantity(DvQuantified):
-    """
-    Abstract class defining the concept of quantified entities whose values are abso-
-    lute with respect to an origin. Dates and Times are the main example.
-    """
-
     grok.implements(IDvAbsoluteQuantity)
 
 
-    def __init__(self,magnitude,accuracy,normalRange,otherReferenceRanges,normalStatus,magnitudeStatus=None):
+    def __init__(self,magnitude,accuracy=None,normal_range=None,other_reference_ranges=None,normal_status=None,magnitude_status=None):
         self.accuracy = accuracy
-        DvQuantified.__init__(self,magnitude,accuracy,normalRange,otherReferenceRanges,normalStatus,magnitudeStatus)
-
-
-    def accuracyUnknown(self):
-        """ True if accuracy is None """
+        super(DvAbsoluteQuantity,self).__init__(magnitude,accuracy,normal_range,other_reference_ranges,normal_status,magnitude_status)
+
+    def accuracy_unknown(self):
         return self.accuracy is None
 
 
 class DvAmount(DvQuantified):
-    u"""
-    Abstract class defining the concept of relative quantified 'amounts'. For relative
-    quantities, the '+' and '-' operators are defined (unlike descendants of
-    DV_ABSOLUTE_QUANTITY, such as the date/time types).
-    """
+    UNKNOWN_ACCURACY_VALUE = -1.0
 
     grok.implements(IDvAmount)
 
-    def __init__(self,accuracy,accuracyIsPercent,magnitude,normalRange,otherReferenceRanges,normalStatus):
-        if accuracy is None:
-            self.accuracy = -1
-        else:
-            self.accuracy = accuracy
-        self.accuracyIsPercent = accuracyIsPercent
-        DvQuantified.__init__(self,magnitude,accuracy,normalRange,otherReferenceRanges,normalStatus)
-
-        # constant
-        self.unknownAccuracyValue = -1.0
-
-    def validPercentage(val):
-        u"""
-        Test whether a number is a valid percentage,i.e. between 0 and 100.
-        ensure
-        Result implies val >= 0.0 and val <= 100.0
-        """
-
+    accuracy = FieldProperty(IDvAmount['accuracy'])
+
+    def __init__(self,magnitude,accuracy=UNKNOWN_ACCURACY_VALUE,accuracy_is_percent=False,magnitude_status=u"=",normal_range=None,other_reference_ranges=None,normal_status=None):
+        self.accuracy_is_percent = accuracy_is_percent
+        super(DvAmount,self).__init__(magnitude,accuracy,normal_range,other_reference_ranges,normal_status,magnitude_status)
+
+    def valid_percentage(self,val):
         return val >= 0.0 and val <= 100.0
 
-    def accuracyUnknown(self):
-        """
-        Accuracy wasn't known or wasn't recorded.
-        """
-        if self.accuracy == -1:
-            return True
+    def accuracy_unknown(self):
+        return self.accuracy == self.UNKNOWN_ACCURACY_VALUE
+
+    def __add__(self,other):
+        assert self.is_strictly_comparable_to(other)
+        klass = type(self)
+        return self._do_arithmetic_expression(other,klass,"+")
+
+    def __sub__(self,other):
+        assert self.is_strictly_comparable_to(other)
+        klass = type(self)
+        return self._do_arithmetic_expression(other,klass,"-")
+
+    def __neg__(self):
+        negated_copy = copy.copy(self)
+        negated_copy.magnitude = -self.magnitude
+        return negated_copy
+
+    def _do_arithmetic_expression(self,other,klass,operator):
+        has_ac_unknown = self.accuracy_unknown()
+        other_has_ac_unknown = other.accuracy_unknown()
+        other_has_percent = other.accuracy_is_percent
+        has_percent = self.accuracy_is_percent
+        new_obj_data = {}
+        if has_ac_unknown or other_has_ac_unknown:
+             new_obj_data['accuracy'] = self.UNKNOWN_ACCURACY_VALUE
+        elif has_percent^other_has_percent:
+            chosen_accuracy = max(self.accuracy,other.accuracy)
+            new_obj_data['accuracy_is_percent'] = False
+            if chosen_accuracy == other.accuracy and other.accuracy_is_percent:
+                new_obj_data['accuracy_is_percent'] = True
+            elif chosen_accuracy == self.accuracy and self.accuracy_is_percent:
+                new_obj_data['accuracy_is_percent'] = True
+            new_obj_data['accuracy'] = chosen_accuracy
         else:
-            return False
+            new_accuracy = eval("float(self.accuracy"+operator+"other.accuracy)")
+            new_obj_data['accuracy'] = new_accuracy
+            
+        new_obj_data['magnitude'] = eval("self.magnitude"+ operator + "other.magnitude")
+        obj = klass(**new_obj_data)
+        return obj
 
 
 class DvCount(DvAmount):
@@ -240,9 +248,6 @@
         return DvCount(-self.magnitude, self.accuracy, self.accuracyIsPercent, self.magnitudeStatus, self.normalStatus, self.normalRange, self.otherReferenceRanges)
 
 
-
-
-
 class DvInterval(DataValue,Interval):
     """
     Used to define intervals of dates, times, quantities (whose units match) and so on.
@@ -344,7 +349,6 @@
         return self.numerator / self.denominator
 
 
-
 class DvProportion(DvAmount,ProportionKind):
     """
               Models a ratio of values, i.e. where the numerator and denominator are both pure
@@ -401,7 +405,6 @@
         return self.numerator / self.denominator
 
 
-
 class DvQuantity(DvAmount):
     """
     Quantitified type representing "scientific" quantities, i.e. quantities expressed as a
@@ -470,3 +473,4 @@
         """
         return self.range_.has(val)
 
+

=== modified file 'src/oship/openehr/rm/datatypes/quantity/interfaces.py'
--- src/oship/openehr/rm/datatypes/quantity/interfaces.py	2010-09-07 19:39:42 +0000
+++ src/oship/openehr/rm/datatypes/quantity/interfaces.py	2010-09-16 20:21:31 +0000
@@ -1,13 +1,14 @@
 # -*- coding: UTF-8 -*-
 
+
 from zope.interface import Interface, Attribute, invariant, Invalid
 from zope.schema import (Text, Bool, TextLine, Int, Field,
-     BytesLine, Float, List, URI, Choice, Object)
+              BytesLine, Float, List, URI, Choice, Object)
 from zope.i18nmessageid.message import MessageFactory
 
 from oship.openehr.rm.datatypes.basic.interfaces import IDataValue
 from oship.openehr.rm.datatypes.text.interfaces import (IDvText, IDvCodedText,
-                                                ICodePhrase)
+                                                        ICodePhrase)
 
 
 _ = MessageFactory('oship')
@@ -33,6 +34,7 @@
     """
     pass
 
+
 class IReferenceRange(Interface):
     """
     Defines a named range to be associated with any ORDERED datum. Each such
@@ -118,7 +120,9 @@
         """
 
     def is_strictly_comparable_to(other):
-        pass
+        """
+        Test if two instances are strictly comparable.
+        """
 
     @invariant
     def other_reference_ranges_validity(obj):
@@ -148,14 +152,14 @@
         pass
 
 
-class IDvQuantified(Interface):
+class IDvQuantified(IDvOrdered):
     """
     Abstract class defining the concept of true quantified values, i.e. values which are
     not only ordered, but which have a precise magnitude.
     """
 
-    magnitude = Float(
-        title=_(u"magnitude"),
+    magnitude = Field(
+        title=_(u"Magnitude"),
         description=_(u"""Numeric value of the quantity in canonical (i.e. single value)
                           form. Implemented as constant, function or attribute in subtypes as
                           appropriate. The type OrdereNumeric is mapped to the available
@@ -163,12 +167,10 @@
         required=True
     )
 
-    accuracy = Field(
-        title = _(u"accuracy"),
-    )
+    accuracy = Attribute(_(u"Accuracy"))
 
-    magnitudeStatus = TextLine(
-        title=_(u"magnitudeStatus"),
+    magnitude_status = TextLine(
+        title=_(u"Magnitude status"),
         description=_(u"""Optional status of magnitude with values:
                                 = : magnitude is a point value
                                 < : value is < magnitude
@@ -181,16 +183,25 @@
     )
 
 
-    def validMagnitudeStatus(val):
+    def valid_magnitude_status(val):
         """
         Test whether a string 'val' is one of the valid values for the magnitude_status attribute.
         """
 
-    def accuracyUnknown():
+    def accuracy_unknown():
         """
         True if accuracy is not known.
         """
+    @invariant
+    def magnitude_exists(obj):
+        if obj.magnitude is None:
+            raise Invalid("The magnitude attribute cannot be None.")
 
+    @invariant
+    def valid_status_valid(obj):
+        if obj.magnitude_status is not None:
+            if not obj.valid_magnitude_status(obj.magnitude_status):
+                raise Invalid("The magnitude is not valid.")
 
 class IDvOrdinal(Interface):
     """
@@ -230,52 +241,72 @@
         Returns DvOrdinal.
         """
 
-    def isStrictlyComparableTo(other):
-        """
-        True if symbols come from same vocabulary,assuming the vocabulary is a
-        subset or value range, e.g. urine:protein.
-
-        (other: like Current): Boolean
-        ensure
-        symbol.is_comparable (other.symbol) implies Result
-        """
-
-
-class IDvAmount(Interface):
-    """
-    Abstract class defining the concept of relative quantified amounts. For relative
-    quantities, the + and - operators are defined (unlike descendants of
-    DV_ABSOLUTE_QUANTITY, such as the date/time types).
-    """
-
-    accuracy = Int(
-        title=_(u"accuracy"),
-        description=_(u"""Accuracy of measurement, expressed either as a half-range
-                         percent value (accuracyIsPercent = True) or a half-range
-                         quantity. A value of 0 means that accuracy was not recorded."""),
-        required=False
-    )
-
-
-    accuracyIsPercent = Bool(
-        title=_(u"accuracyIsPercent"),
-        description=_(u"""If True, indicates that when this object was created, accuracy was recorded
-                    as a percent value; if False, as an absolute quantity value."""),
-        required=False
-    )
-
-
-    def validPercentage(val):
-        """
-        Test whether a number is a valid percentage,i.e. between 0 and 100.
-        ensure
-        Result implies val >= 0.0 and val <= 100.0
-        """
-
+
+class IDvAmount(IDvQuantified):
+    """
+    Abstract interface defining the concept of relative quantified amounts. 
+    For relative quantities, the + and - operators are defined (unlike 
+    descendants of IDvAbsoluteQuantity, such as the date/time types).
+    """
+
+    UNKNOWN_ACCURACY_VALUE = Attribute(("Special value for accuracy "
+                                       "indicating no accuracy recorded."))
+
+    accuracy = Float(
+        title=_(u"Accuracy"),
+        description=_((u"Accuracy of measurement, expressed either as a "
+                       "half-range percent value or a half-range quantity.")),
+        required=False
+    )
+
+    accuracy_is_percent = Bool(
+        title=_(u"Percent"),
+        description=_((u"Indicates that accuracy was recorded "
+                        "as a percent value or as an absolute "
+                        "quantity value.")),
+        required=False
+    )
+
+    def valid_percentage(val):
+        """
+        Test whether a number is a valid percentage, i.e. between 0 and 100.
+        """
+
+    def __neg__():
+        """
+        Negated version of current object, such as
+        used for representing a difference.
+        """
+
+    def __add__(other):
+        """
+        Sum of this quantity and another quantity of
+        the same concrete type.
+        """
+
+    def __sub__(other):
+        """
+        Difference of this quantity and another quantity
+        of the same concrete type.
+        """
+
+    @invariant
+    def accuracy_is_percent_validity(obj):
+        if obj.accuracy == 0:
+            if obj.accuracy_is_percent:
+                raise Invalid("The percentage accuracy cannot be zero.")
+
+    @invariant
+    def accuracy_validity(obj):
+        if obj.accuracy_is_percent:
+            if not obj.valid_percentage(obj.accuracy):
+                raise Invalid("The percentage accuracy is not valid.")
+        
 
 class IDvAbsoluteQuantity(Interface):
     """
-    Abstract class defining the concept of quantified entities whose values are absolute with respect to an origin. Dates and Times are the main example.
+    Abstract class defining the concept of quantified entities whose values are
+    absolute with respect to an origin. Dates and Times are the main example.
     """
 
     accuracy = Field(
@@ -342,6 +373,7 @@
         True if n is one of the defined types.
         """
 
+
 class IDvProportion(Interface):
     """
               Models a ratio of values, i.e. where the numerator and denominator are both pure

=== added file 'src/oship/openehr/rm/datatypes/quantity/tests/dvamount.txt'
--- src/oship/openehr/rm/datatypes/quantity/tests/dvamount.txt	1970-01-01 00:00:00 +0000
+++ src/oship/openehr/rm/datatypes/quantity/tests/dvamount.txt	2010-09-16 20:21:31 +0000
@@ -0,0 +1,183 @@
+Defining quantity amounts with DvAmount
+=======================================
+
+:Test-Layer: unit
+
+
+An `DvAmount` class represents relative quantified 'amounts'.  The amount here
+means amounts about something, which allows defines either a physical property,
+such as a mass, or items in general(cigarettes, for example).  The arithmetic
+operators(+, - , * and /) and any other in the mathematical field act here as a
+true numbers. In case two relative quantities are evaluated using these
+operators and they have the same measured property, it should create other relative
+quantity of the same type. If was executed a subtraction as an arithmetic operation,
+the scenario happens in the same way : another object is created.
+The only mandatory attributes to create a `DvAmount` is the magnitude attribute,
+which is the number that corresponds how amount will be represented.  The
+optional attributes are the magnitude_status and accuracy following the
+`IDvQuantified` interface and normal_range, other_reference_ranges and
+normal_status attributes specified by `IDvOrdered` interface.  In order to
+exercise it's operations which are defined on the abstract class, concrete
+classes must be defined.  The DvAmount is a abstract class, which means that
+object cannot be a direct instance of it. All antecessors parameters
+and behaviors still valid::
+
+    >>> import grok
+    >>> from oship.openehr.rm.datatypes.quantity import DvAmount
+    >>> from oship.openehr.rm.datatypes.quantity.interfaces import IDvAmount
+    >>> class Amount(DvAmount):
+    ...   def is_strictly_comparable_to(self,other):
+    ...     if other.__class__ == self.__class__:
+    ...       return True
+    ...     return False
+    ...   def __lt__(self,other):
+    ...     assert self.is_strictly_comparable_to(other)
+    ...     return self.magnitude < other.magnitude
+    >>> class AnotherAmount(DvAmount):
+    ...   pass
+    >>> box_quantity = Amount(7)
+    >>> str(box_quantity.normal_range)
+    'None'
+    >>> str(box_quantity.other_reference_ranges)
+    'None'
+    >>> str(box_quantity.normal_status)
+    'None'
+    >>> box_quantity.accuracy
+    -1.0
+    >>> box_quantity.magnitude_status
+    u'='
+    >>> box_quantity.magnitude
+    7
+    >>> box_quantity.is_normal()
+    Traceback (most recent call last):
+    ...
+    TypeError: The object doesn't have any normal range.
+    >>> box_quantity.is_simple()
+    True
+    >>> box_quantity.valid_magnitude_status(u"=")
+    True
+    >>> weird_amount = AnotherAmount(2)
+    >>> weird_amount + box_quantity
+    Traceback (most recent call last):
+    ...
+    NotImplementedError: The class AnotherAmount must implement this method.
+
+The only mandatory methods that must be implemented to pass on all abstract
+restrictions are is_strictly_comparable_to, and __lt__ which is the < operator.
+The is_strictly_comparable_to is used by other methods to verify if two object
+can be compared correctly.
+The Amount class defined here for test purposes, have all requirements to a true
+`DvAmout` concrete class::
+
+    >>> other_box_quantity = Amount(5)
+    >>> box_quantity < other_box_quantity 
+    False
+    >>> all_boxes = box_quantity + other_box_quantity
+    >>> all_boxes.magnitude
+    12
+    >>> negated_box_quantity= -all_boxes
+    >>> negated_box_quantity.magnitude
+    -12
+
+
+Setting accuracy in a DvAmount object
+-------------------------------------
+
+The *accuracy* of a value usually isn't included in a model for quantified
+values. In the realistic health domain, it's required for statistical purposes
+allowing make queries which the measurement error can be disambiguated from a
+true correlation. For practical purposes, a (in)accuracy corresponds to a range
+of possible values.  A value of 0 in either case indicates 100% accuracy, i.e.
+no error in measurement. The method unknown_accuracy verifies if the accuracy
+was measured::
+
+    >>> main_room_brightlight = Amount(magnitude=200,accuracy=200.0)
+    >>> main_room_brightlight.accuracy_is_percent
+    False
+    >>> wait_room_brightlight = Amount(magnitude=300,accuracy=150.0)
+    >>> sheets_of_paper = Amount(500)
+    >>> sheets_of_paper.accuracy_unknown()
+    True
+    >>> more_sheets_of_papers = Amount(70,0.0)
+    >>> more_sheets_of_papers.accuracy_unknown()
+    False
+    >>> a_set_of_simple_chairs = Amount(magnitude=50,accuracy=80.0,accuracy_is_percent=True)
+    >>> a_set_of_simple_chairs.accuracy_unknown()
+    False
+    >>> a_set_of_elegant_chairs = Amount(70,300.0)
+    >>> a_set_of_elegant_chairs.accuracy_is_percent
+    False
+
+
+Where accuracy is not recorded in a quantity, it is represented by a special
+value. In `DvAmount`, the `UNKNOWN_ACCURACY_VALUE` value is used for this
+purpose.  In addition, the class `DvAmount`, provides a attribute called
+accuracy_is_percent: A boolean to indicate if accuracy value is to be understood
+as a percentage, or an absolute value.
+
+
+When two compatible quantities are added or subtracted using the + or -
+operators (`DvAmount` descendants), the accuracy behaves in the following way:
+
+* if accuracies are present in both quantities, they are added in the result,
+for both addition and subtraction operations::
+
+    >>> total_bright = main_room_brightlight + wait_room_brightlight
+    >>> total_bright.magnitude
+    500
+    >>> total_bright.accuracy
+    350.0
+    
+    >>> turn_wait_room_lights_off = main_room_brightlight - wait_room_brightlight
+    >>> turn_wait_room_lights_off.magnitude
+    -100
+    >>> turn_wait_room_lights_off.accuracy
+    50.0
+
+* if either or both quantities has an unknown accuracy, the accuracy of the
+result is also unknown::
+
+    >>> total_sheets = sheets_of_paper + more_sheets_of_papers 
+    >>> total_sheets.magnitude
+    570
+    >>> total_sheets.accuracy_unknown()
+    True
+    >>> the_best_sheets = sheets_of_paper - more_sheets_of_papers
+    >>> the_best_sheets.magnitude
+    430
+    >>> the_best_sheets.accuracy_unknown()
+    True
+
+* if two `DvAmount` descendants are added or subtracted, and only one has
+accuracy_is_percent equals True, accuracy is expressed in the form used
+in the larger of the two quantities::
+
+    >>> all_chairs = a_set_of_simple_chairs + a_set_of_elegant_chairs
+    >>> all_chairs.magnitude
+    120
+    >>> all_chairs.accuracy
+    300.0
+
+
+
+Validating Invariants
+---------------------
+
+The `IDvAmount` have two invariants:
+
+* The first one verifies if the accuracy is zero and is a percentage accuracy::
+
+    >>> a_set_of_cars = Amount(magnitude=70,accuracy=0.0,accuracy_is_percent=True)
+    >>> IDvAmount.validateInvariants(a_set_of_cars)
+    Traceback (most recent call last):
+    ...
+    Invalid: The percentage accuracy cannot be zero. 
+
+* The second and last invariant check the percentage validity: it must be a
+value between 0 and 100::
+
+    >>> a_set_of_computers = Amount(magnitude=70,accuracy=120.0,accuracy_is_percent=True)
+    >>> IDvAmount.validateInvariants(a_set_of_computers)
+    Traceback (most recent call last):
+    ...
+    Invalid: The percentage accuracy is not valid.

=== modified file 'src/oship/openehr/rm/datatypes/quantity/tests/dvquantified.py'
--- src/oship/openehr/rm/datatypes/quantity/tests/dvquantified.py	2010-08-08 19:19:54 +0000
+++ src/oship/openehr/rm/datatypes/quantity/tests/dvquantified.py	2010-09-16 20:21:31 +0000
@@ -5,39 +5,65 @@
 """
 import unittest
 import grok
+from zope.interface import Invalid
 
 from oship.openehr.rm.datatypes.quantity import DvQuantified
+from oship.openehr.rm.datatypes.quantity.interfaces import IDvQuantified
+
+
+
+
+class SimpleDvQuantified(DvQuantified):
+    pass
+
+
 
 class DvQuantifiedTest(unittest.TestCase):
 
     def setUp(self):
-        self.aDvQuantified = SimpleDvQuantified(None,None,None,None,None,None)
-        self.validMagnitudeStatus = ('=','>','<','<=','>=','~') 
-
-    def tearDown(self):
-        self.aDvQuantified = None
-
-    def testValidMagnitudeStatusWithValidValues(self):
-        for status in self.validMagnitudeStatus:
-           self.assertEqual(True, self.aDvQuantified.validMagnitudeStatus(status))
-
-    def testValidMagnitudeStatusWithInvalidValues(self):
-        self.assertEqual(False, self.aDvQuantified.validMagnitudeStatus('a'))
-        self.assertEqual(False, self.aDvQuantified.validMagnitudeStatus(''))
-        self.assertEqual(False, self.aDvQuantified.validMagnitudeStatus(None))
-
-    def testConstructorWithInvalidMagnitudeStatus(self):
-        self.assertRaises(ValueError, SimpleDvQuantified, None,None,None,None,None,'a')
-        self.assertRaises(ValueError, SimpleDvQuantified, None,None,None,None,None,'')
-
-    def testContructorWithValidMagnitudeStatus(self):
-        for status in self.validMagnitudeStatus:
-            dvQuantified = SimpleDvQuantified(None,None,None,None,None,status)
-            self.assertEqual(status, dvQuantified.magnitudeStatus)
-
-    def testConstructurWithANoneMagnitudeStatus(self):
-        dvQuantified = SimpleDvQuantified(None,None,None,None,None,None)
-        self.assertEquals(None, dvQuantified.magnitudeStatus)
-
-class SimpleDvQuantified(DvQuantified):
-    pass
+        self.a_quantity = SimpleDvQuantified(2)
+        self.valid_magnitude_status = ('=','>','<','<=','>=','~',)
+
+    def test_commom_properties(self):
+        self.assertTrue(self.a_quantity.normal_status is None)
+        self.assertTrue(self.a_quantity.normal_range is None)
+        self.assertTrue(self.a_quantity.other_reference_ranges is None)
+        self.assertEquals(self.a_quantity.magnitude, 2)
+        self.assertTrue(self.a_quantity.accuracy is None)
+        self.assertTrue(self.a_quantity.magnitude_status  is None)
+        self.assertRaises(NotImplementedError, self.a_quantity.accuracy_unknown)
+
+
+    def test_valid_magnitude_status_with_valid_values(self):
+        for status in self.valid_magnitude_status:
+           self.assertTrue(self.a_quantity.valid_magnitude_status(status))
+
+    def test_valid_magnitude_status_with_invalid_values(self):
+        self.assertFalse(self.a_quantity.valid_magnitude_status('a'))
+        self.assertFalse(self.a_quantity.valid_magnitude_status(''))
+        self.assertFalse(self.a_quantity.valid_magnitude_status(None))
+
+    def test_constructor_with_invalid_magnitude_status(self):
+        self.assertRaises(ValueError, SimpleDvQuantified,2,magnitude_status='a')
+        self.assertRaises(ValueError, SimpleDvQuantified,3,magnitude_status='')
+
+    def test_constructor_with_valid_magnitude_status(self):
+        for status in self.valid_magnitude_status:
+            another_quantity = SimpleDvQuantified(6,magnitude_status=status)
+            self.assertEqual(status, another_quantity.magnitude_status)
+
+    def test_constructor_with_a_None_magnitude_status(self):
+        a_quantity = SimpleDvQuantified(78)
+        self.assertEquals(None, a_quantity.magnitude_status)
+
+    def test_magnitude_invariant(self):
+        a_simple_quantity = SimpleDvQuantified(None)
+        assert a_simple_quantity.magnitude is None
+        self.assertRaises(Invalid, IDvQuantified.validateInvariants, a_simple_quantity)
+
+    def test_magnitude_status_invariant(self):
+        a_simple_quantity = SimpleDvQuantified(42, "=")
+        a_simple_quantity.magnitude_status = "doh!"
+        self.assertRaises(Invalid, IDvQuantified.validateInvariants, a_simple_quantity)
+
+