X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPythonAPI%2Fmodel%2Ftests%2Ftests.py;h=e088f7c749723377713df2a22937eb330ffa068c;hb=77ce6d35ac8d2f0fdaecb4f23e0870bf74e36103;hp=ce6c3933288a6944447620e92cdccd649407128d;hpb=b3695c3af5289903f1c0fa01bbb7c40203c5e544;p=modules%2Fshaper.git diff --git a/src/PythonAPI/model/tests/tests.py b/src/PythonAPI/model/tests/tests.py index ce6c39332..e088f7c74 100644 --- a/src/PythonAPI/model/tests/tests.py +++ b/src/PythonAPI/model/tests/tests.py @@ -1,27 +1,27 @@ -## Copyright (C) 2014-2017 CEA/DEN, EDF R&D -## -## This library is free software; you can redistribute it and/or -## modify it under the terms of the GNU Lesser General Public -## License as published by the Free Software Foundation; either -## version 2.1 of the License, or (at your option) any later version. -## -## This library is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## Lesser General Public License for more details. -## -## You should have received a copy of the GNU Lesser General Public -## License along with this library; if not, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -## -## See http:##www.salome-platform.org/ or -## email : webmaster.salome@opencascade.com -## +# Copyright (C) 2014-2024 CEA, EDF +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# from GeomAlgoAPI import * from GeomAPI import * from GeomDataAPI import * -from ModelAPI import ModelAPI_Feature +from ModelAPI import ModelAPI_Feature, ModelAPI_Session, objectToFeature +from ModelHighAPI import * import math from salome.shaper.model import sketcher @@ -42,14 +42,14 @@ def generateTests(theFeature, theFeatureName, theTestsList = []): """ if "testNbResults" in theTestsList or len(theTestsList) == 0: aNbResults = len(theFeature.results()) - print "model.testNbResults({}, {})".format(theFeatureName, aNbResults) + print("model.testNbResults({}, {})".format(theFeatureName, aNbResults)) if "testNbSubResults" in theTestsList or len(theTestsList) == 0: aNbResults = len(theFeature.results()) aNbSubResults = [] for anIndex in range(0, aNbResults): aNbSubResults.append(theFeature.results()[anIndex].numberOfSubs()) - print "model.testNbSubResults({}, {})".format(theFeatureName, aNbSubResults) + print("model.testNbSubResults({}, {})".format(theFeatureName, aNbSubResults)) if "testNbSubShapes" in theTestsList or len(theTestsList) == 0: aNbResults = len(theFeature.results()) @@ -61,16 +61,23 @@ def generateTests(theFeature, theFeatureName, theTestsList = []): aShapeExplorer = GeomAPI_ShapeExplorer(aShape, aShapeType) while aShapeExplorer.more(): aNbResultSubShapes += 1 - aShapeExplorer.next(); + aShapeExplorer.next() aNbSubShapes.append(aNbResultSubShapes) - print "model.testNbSubShapes({}, {}, {})".format(theFeatureName, aShapeTypes[aShapeType], aNbSubShapes) + print("model.testNbSubShapes({}, {}, {})".format(theFeatureName, aShapeTypes[aShapeType], aNbSubShapes)) if "testResultsVolumes" in theTestsList or len(theTestsList) == 0: aNbResults = len(theFeature.results()) aResultsVolumes = [] for anIndex in range(0, aNbResults): - aResultsVolumes.append(GeomAlgoAPI_ShapeTools_volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape())) - print "model.testResultsVolumes({}, [{}])".format(theFeatureName, ", ".join("{:0.27f}".format(i) for i in aResultsVolumes)) + aResultsVolumes.append(GeomAlgoAPI_ShapeTools.volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape())) + print("model.testResultsVolumes({}, [{}])".format(theFeatureName, ", ".join("{:0.27f}".format(i) for i in aResultsVolumes))) + + if "testResultsAreas" in theTestsList or len(theTestsList) == 0: + aNbResults = len(theFeature.results()) + aResultsAreas = [] + for anIndex in range(0, aNbResults): + aResultsAreas.append(GeomAlgoAPI_ShapeTools.area(theFeature.results()[anIndex].resultSubShapePair()[0].shape())) + print("model.testResultsAreas({}, [{}])".format(theFeatureName, ", ".join("{:0.27f}".format(i) for i in aResultsAreas))) def testNbResults(theFeature, theExpectedNbResults): @@ -112,10 +119,68 @@ def testNbSubShapes(theFeature, theShapeType, theExpectedNbSubShapes): aShapeExplorer = GeomAPI_ShapeExplorer(aShape, theShapeType) while aShapeExplorer.more(): aNbResultSubShapes += 1 - aShapeExplorer.next(); + aShapeExplorer.next() + assert (aNbResultSubShapes == anExpectedNbSubShapes), "Number of sub-shapes of type {} for result[{}]: {}. Expected: {}.".format(aShapeTypes[theShapeType], anIndex, aNbResultSubShapes, anExpectedNbSubShapes) + + +def testNbUniqueSubShapes(theFeature, theShapeType, theExpectedNbSubShapes): + """ Tests number of unique feature sub-shapes of passed type for each result. + :param theFeature: feature to test. + :param theShapeType: shape type of sub-shapes to test. + :param theExpectedNbSubShapes: list of sub-shapes numbers. Size of list should be equal to len(theFeature.results()). + """ + aResults = theFeature.feature().results() + aNbResults = len(aResults) + aListSize = len(theExpectedNbSubShapes) + assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize) + for anIndex in range(0, aNbResults): + aNbResultSubShapes = 0 + anExpectedNbSubShapes = theExpectedNbSubShapes[anIndex] + aNbResultSubShapes = aResults[anIndex].shape().subShapes(theShapeType, True).size() assert (aNbResultSubShapes == anExpectedNbSubShapes), "Number of sub-shapes of type {} for result[{}]: {}. Expected: {}.".format(aShapeTypes[theShapeType], anIndex, aNbResultSubShapes, anExpectedNbSubShapes) +def testCompound(theFeature, NbSubRes, NbSolid, NbFace, NbEdge, NbVertex): + """ Tests number of unique sub-shapes in compound result + """ + aResults = theFeature.feature().results() + aNbResults = len(aResults) + assert (aNbResults == 1), "Number of results: {} not equal to 1.".format(aNbResults) + assert aResults[0].shape().isCompound(), "Result shape type: {}. Expected: COMPOUND.".format(aResults[0].shape().shapeTypeStr()) + testNbSubResults(theFeature, NbSubRes) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.SOLID, NbSolid) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex) + + +def testCompSolid(theFeature, NbSubRes, NbSolid, NbFace, NbEdge, NbVertex): + """ Tests number of unique sub-shapes in compsolid result + """ + aResults = theFeature.feature().results() + aNbResults = len(aResults) + assert (aNbResults == 1), "Number of results: {} not equal to 1.".format(aNbResults) + assert aResults[0].shape().isCompSolid(), "Result shape type: {}. Expected: COMPSOLID.".format(aResults[0].shape().shapeTypeStr()) + testNbSubResults(theFeature, NbSubRes) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.SOLID, NbSolid) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex) + + +def testResults(theFeature, NbRes, NbSubRes, NbShell, NbFace, NbEdge, NbVertex): + """ Tests numbers of unique sub-shapes in the results + """ + aResults = theFeature.feature().results() + aNbResults = len(aResults) + assert (aNbResults == NbRes), "Number of results: {} not equal to {}}.".format(aNbResults, NbRes) + testNbSubResults(theFeature, NbSubRes) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.SHELL, NbShell) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge) + testNbUniqueSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex) + + def testResultsVolumes(theFeature, theExpectedResultsVolumes, theNbSignificantDigits = 7): """ Tests results volumes. :param theFeature: feature to test. @@ -126,11 +191,29 @@ def testResultsVolumes(theFeature, theExpectedResultsVolumes, theNbSignificantDi aListSize = len(theExpectedResultsVolumes) assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize) for anIndex in range(0, aNbResults): - aResultVolume = GeomAlgoAPI_ShapeTools_volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape()) + aResultVolume = GeomAlgoAPI_ShapeTools.volume(theFeature.results()[anIndex].resultSubShapePair()[0].shape()) + aResultVolumeStr = "{:0.27f}".format(aResultVolume).lstrip("0").lstrip(".").lstrip("0") + anExpectedResultVolume = theExpectedResultsVolumes[anIndex] + anExpectedResultVolumeStr = "{:0.27f}".format(anExpectedResultVolume).lstrip("0").lstrip(".").lstrip("0") + assert math.fabs(aResultVolume - anExpectedResultVolume) <= aTolerance * math.fabs(anExpectedResultVolume), "Volume of result[{}]: {:0.27f}. Expected: {:0.27f}. The first {} significant digits not equal.".format(anIndex, aResultVolume, anExpectedResultVolume, theNbSignificantDigits) + + +def testResultsAreas(theFeature, theExpectedResultsVolumes, theNbSignificantDigits = 7): + """ Tests results areas. + :param theFeature: feature to test. + :param theExpectedResultsAreas: list of results areas. Size of list should be equal to len(theFeature.results()). + """ + aTolerance = 10**(-theNbSignificantDigits) + aNbResults = len(theFeature.results()) + aListSize = len(theExpectedResultsVolumes) + assert (aNbResults == aListSize), "Number of results: {} not equal to list size: {}.".format(aNbResults, aListSize) + for anIndex in range(0, aNbResults): + aResultVolume = GeomAlgoAPI_ShapeTools.area(theFeature.results()[anIndex].resultSubShapePair()[0].shape()) aResultVolumeStr = "{:0.27f}".format(aResultVolume).lstrip("0").lstrip(".").lstrip("0") anExpectedResultVolume = theExpectedResultsVolumes[anIndex] anExpectedResultVolumeStr = "{:0.27f}".format(anExpectedResultVolume).lstrip("0").lstrip(".").lstrip("0") - assert math.fabs(aResultVolume - anExpectedResultVolume) < aTolerance * anExpectedResultVolume, "Volume of result[{}]: {:0.27f}. Expected: {:0.27f}. The first {} significant digits not equal.".format(anIndex, aResultVolume, anExpectedResultVolume, theNbSignificantDigits) + assert math.fabs(aResultVolume - anExpectedResultVolume) <= aTolerance * math.fabs(anExpectedResultVolume), "Area of result[{}]: {:0.27f}. Expected: {:0.27f}. The first {} significant digits not equal.".format(anIndex, aResultVolume, anExpectedResultVolume, theNbSignificantDigits) + def testHaveNamingFaces(theFeature, theModel, thePartDoc) : """ Tests if all faces of result have a name @@ -166,7 +249,7 @@ def testHaveNamingFaces(theFeature, theModel, thePartDoc) : assert(name != ""), "String empty" def testHaveNamingEdges(theFeature, theModel, thePartDoc) : - """ Tests if all faces of result have a name + """ Tests if all edges of result have a name :param theFeature: feature to test. """ # Get feature result/sub-result @@ -198,6 +281,75 @@ def testHaveNamingEdges(theFeature, theModel, thePartDoc) : assert(shape.isEdge()) assert(name != ""), "String empty" +def lowerLevelSubResults(theResult, theList): + """ Collects in a list all lover level sub-results (without children). + Auxiliary method for context correct definition. + """ + nbSubs = theResult.numberOfSubs() + if nbSubs == 0: + theList.append(theResult) + else: + for sub in range(0, nbSubs): + lowerLevelSubResults(theResult.subResult(sub), theList) + +def testHaveNamingByType(theFeature, theModel, thePartDoc, theSubshapeType) : + """ Tests if all sub-shapes of result have a unique name + :param theFeature: feature to test. + :param theSubshapeType: type of sub-shape + """ + if not theFeature.results(): + return + aFirstRes = theFeature.results()[0] + aResList = [] + lowerLevelSubResults(aFirstRes, aResList) + + selectionList = [] + shapesList = [] # to append only unique shapes (not isSame) + for aR in aResList: + # Get feature result/sub-result + aResult = aR.resultSubShapePair()[0] + # Get result/sub-result shape + shape = aResult.shape() + # Create shape explorer with desired shape type + shapeExplorer = GeomAPI_ShapeExplorer(shape, theSubshapeType) + # Create list, and store selections in it + while shapeExplorer.more(): + current = shapeExplorer.current() + if current.isEdge() and GeomAPI.GeomAPI_Edge(current).isDegenerated(): # skip degenerative edges because they are not selected + shapeExplorer.next() + continue + aDuplicate = False + for alreadyThere in shapesList: + if alreadyThere.isSame(current): + aDuplicate = True + if aDuplicate: + shapeExplorer.next() + continue + shapesList.append(current) + selection = theModel.selection(aResult, current) # First argument should be result/sub-result, second is sub-shape on this result/sub-result + selectionList.append(selection) + shapeExplorer.next() + # Create group with this selection list + # (do not create group if nothing is selected) + if (len(selectionList) == 0): + return + Group_1 = theModel.addGroup(thePartDoc, selectionList) + theModel.do() + + groupSelectionList = Group_1.feature().selectionList("group_list") + assert(groupSelectionList.size() == len(selectionList)) + + # Check that all selected shapes in group have right shape type and unique name. + checkGroup(Group_1, theSubshapeType) + +def testHaveNamingSubshapes(theFeature, theModel, thePartDoc) : + """ Tests if all vertices/edges/faces of result have a unique name + :param theFeature: feature to test. + """ + assert(len(theFeature.results()) > 0) + testHaveNamingByType(theFeature, theModel, thePartDoc, GeomAPI_Shape.VERTEX) + testHaveNamingByType(theFeature, theModel, thePartDoc, GeomAPI_Shape.EDGE) + testHaveNamingByType(theFeature, theModel, thePartDoc, GeomAPI_Shape.FACE) def testNbSubFeatures(theComposite, theKindOfSub, theExpectedCount): """ Tests number of sub-features of the given type @@ -223,3 +375,101 @@ def assertSketchArc(theArcFeature): aDistCE = sketcher.tools.distancePointPoint(aCenterPnt, aEndPnt) assert math.fabs(aDistCS - aDistCE) < TOLERANCE, "Wrong arc: center-start distance {}, center-end distance {}".format(aDistCS, aDistCE) assert math.fabs(aRadius.value() -aDistCS) < TOLERANCE, "Wrong arc: radius is {0}, expected {1}".format(aRadius.value(), aDistCS) + +def checkResult(theFeature,theModel,NbRes,NbSubRes,NbSolid,NbFace,NbEdge,NbVertex): + """ Tests numbers of sub-shapes in results + """ + theModel.testNbResults(theFeature, NbRes) + theModel.testNbSubResults(theFeature, NbSubRes) + theModel.testNbSubShapes(theFeature, GeomAPI_Shape.SOLID, NbSolid) + theModel.testNbSubShapes(theFeature, GeomAPI_Shape.FACE, NbFace) + theModel.testNbSubShapes(theFeature, GeomAPI_Shape.EDGE, NbEdge) + theModel.testNbSubShapes(theFeature, GeomAPI_Shape.VERTEX, NbVertex) + +def checkGroup(theGroup, theShapeType): + """ Check that all selected shapes in group have correct shape type and unique name + """ + groupFeature = theGroup.feature() + groupSelectionList = groupFeature.selectionList("group_list") + presented_names = set() + for index in range(0, groupSelectionList.size()): + attrSelection = groupSelectionList.value(index) + shape = attrSelection.value() + name = attrSelection.namingName() + if theShapeType == GeomAPI_Shape.VERTEX: + assert(shape.isVertex()) + elif theShapeType == GeomAPI_Shape.EDGE: + assert(shape.isEdge()) + elif theShapeType == GeomAPI_Shape.FACE: + assert(shape.isFace()) + assert(name != ""), "String empty" + presented_names.add(name) + assert(len(presented_names) == groupSelectionList.size()), "Some names are not unique" + +def createSubShape(thePartDoc, theModel, theSelection): + """ Create feature according to the type of the given subshape + """ + if theSelection.shapeType() == "VERTEX": + return theModel.addVertex(thePartDoc, [theSelection]) + elif theSelection.shapeType() == "EDGE": + return theModel.addEdge(thePartDoc, [theSelection]) + elif theSelection.shapeType() == "FACE": + return theModel.addFace(thePartDoc, [theSelection]) + +def checkFilter(thePartDoc, theModel, theFilter, theShapesList): + """ Check filter's work on specified shape. + Shapes given as a dictionary of selection and expected result. + """ + aFiltersFactory = ModelAPI_Session.get().filters() + for sel, res in theShapesList.items(): + needUndo = False + shapeName = "" + shapeType = "UNKNOWN" + if sel.variantType() == ModelHighAPI_Selection.VT_ResultSubShapePair: + parent = sel.resultSubShapePair()[0] + shape = sel.resultSubShapePair()[1] + if shape.isNull(): + shape = sel.resultSubShapePair()[0].shape() + shapeName = sel.name() + shapeType = shape.shapeTypeStr() + else: + needUndo = True + theModel.begin() + subShapeFeature = createSubShape(thePartDoc, theModel, sel) + theModel.end() + parent = subShapeFeature.results()[0].resultSubShapePair()[0] + shape = subShapeFeature.results()[0].resultSubShapePair()[0].shape() + shapeType = sel.typeSubShapeNamePair()[0] + shapeName = sel.typeSubShapeNamePair()[1] + assert aFiltersFactory.isValid(theFilter.feature(), parent, shape) == res, "Filter result for {} \"{}\" incorrect. Expected {}.".format(shapeType, shapeName, res) + if needUndo: + theModel.undo() + +def checkFeaturesValidity(thePartDoc): + """ Check that the features are not in error + """ + aFactory = ModelAPI_Session.get().validators() + + nbFeatures = thePartDoc.size("Features") + + assert nbFeatures>0, "No features found in part doc" + + for i in range(nbFeatures): + partObject = thePartDoc.object("Features", i) + # Check the data + partObjectData = partObject.data() + name = partObjectData.name() + error = partObjectData.error() + # raise the error message if there is one + assert error == '', "The feature data {0} is in error: {1}".format(name, error) + # raise an error if the the feature is not valid (without error message) + assert partObject.data().isValid(), "The feature data {0} is in error.".format(name) + # Same checks for the feature itself + feature = objectToFeature(partObject) + if feature is None: + # Folders are not real features + continue + # raise the error message if there is one + assert error == '', "The feature {0} is in error: {1}".format(name, error) + # raise an error if the the feature is not valid (without error message) + assert aFactory.validate(feature), "The feature {0} is in error.".format(name)