Source code for pyuseocl.assertion

# coding=utf-8

"""
Add support for "assertions" in USE OCL.
Assertions can be added in soil files in the form of comments like the
following::

    -- @assert MyClass::MyInvariant1 OK
    -- @assert MyClass::MyInvariant2 Failed
    -- @assert MyClass::MyInvariant6 OK

    ... the rest of the soil file ...

The "tester" engine will extract any assertion in the soil file and check
if the expected results conform to what USE OCL interpreter return.
This module is to be used with the 'tester' module.
"""

import re


[docs]class InvariantAssertionEvaluation(object): """ The evaluation of an InvariantAssertion against a model if thr assertion is correct. If the assertion is incorrect then the evaluation is a failure. The status can therefore have three values: - 'OK': the assertion is correct and it evaluate to the expected result, - 'KO': the assertion is correct and it evaluate to a unepected result, - 'Failure': the assertion is incorrect """ def __init__(self, invariantAssertion, actualResult): self.assertion = invariantAssertion if self.assertion.isCorrect: if actualResult == self.assertion.expectedResult: status = 'OK' else: status = 'KO' else: status = 'Failure' self.actualResult = actualResult self.status = status def __repr__(self): if self.status == 'Failure': return 'Assert(%s,%s)' % ( self.assertion, self.status ) else: return 'Assert(%s=%s,%s)' % ( self.assertion.invariant, self.assertion.expectedResult, self.status )
[docs]class InvariantAssertion(object): """ An InvariantAssertion bound to an invariant of a given model or an invalid InvariantAssertion if the invariant cannot be found. Just indicates what is the expected result for this invariant. """ def __init__(self, useModel, stateFile, className, invariantName, expectedResult): self.stateFile = stateFile self.className = className self.invariantName = invariantName self.useModel = useModel try: # TODO: improve to support None as class name self.invariant = useModel.findInvariant(className, invariantName) except: self.invariant = None self.isCorrect = self.invariant is not None """ bool """ self.expectedResult = expectedResult """ bool """ def __repr__(self): if self.isCorrect: return 'Assert(%s,%s)' % (self.invariant, self.expectedResult) else: return ('Assert(INCORRECT:%s::%s,%s)' % (self.className, self.invariantName, self.expectedResult))
def _extractAssertionsFromFile(useModel, soilFile): """ Extract assertions objects from a soil file and a given model. :param useModel: the model to which the soil file may reference :type useModel: pyuse.model.Model :param soilFile: path to the soil file :type soilFile: str :return: list of InvariantAssertion :rtype: [pyuseocl.model.Invariant] """ _ = [] triples = _extractAssertionStringsFromFile(soilFile) for (class_name, inv_name, result) in triples: ia=InvariantAssertion(useModel, soilFile, class_name, inv_name, result) _.append(ia) return _ def _extractAssertionStringsFromFile(soilFile): """ Extract the assertion statement from a soil file. Returns a list of triplet with - the class name (optional), - the short name of invariant, - the expected result as a boolean """ def _asBoolean(s): return {'ok': True, 'ko': False, 'failed': False}[s.lower()] with open(soilFile) as f: text = f.read() regexp = r'--\ *@\s*(?:assert|validate)\s+' \ r'(?:(\w+)[:_][:_])?(\w+)\s+' \ r'(OK|KO|Failed)' triples = re.findall(regexp, text, re.IGNORECASE) return [(class_, inv, _asBoolean(result)) for (class_, inv, result) in triples]