[tests] Fix python compositionchecker to derive from render checker, fix most python composer tests (fix #9117)

This commit is contained in:
nyalldawson 2013-12-29 09:41:00 +11:00 committed by Nyall Dawson
parent 2e107f23b9
commit 6aed6fee08
13 changed files with 126 additions and 230 deletions

View File

@ -38,4 +38,7 @@ class QgsRenderChecker
bool compareImages( QString theTestName, unsigned int theMismatchCount = 0, QString theRenderedImageFile = "" );
bool isKnownAnomaly( QString theDiffImageFile );
QString expectedImageFile();
};

View File

@ -920,6 +920,29 @@ class QgsVectorLayer : QgsMapLayer
* @note added in 2.0
*/
int layerTransparency() const;
/** Set the Map2pixel simplification threshold for fast rendering of features */
void setSimplifyDrawingTol( float simplifyDrawingTol );
/** Returns the Map2pixel simplification threshold for fast rendering of features */
float simplifyDrawingTol() const;
/** Simplification flags for fast rendering of features */
enum SimplifyHint
{
NoSimplification = 0, //!< No simplification can be applied
GeometrySimplification = 1, //!< The geometries can be simplified using the current map2pixel context state
EnvelopeSimplification = 2, //!< The geometries can be fully simplified by its BoundingBox using the current map2pixel context state
AntialiasingSimplification = 4, //!< The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'
DefaultSimplification = 3, //!< Default simplification hints can be applied ( Geometry + Envelope )
FullSimplification = 7, //!< All simplification hints can be applied ( Geometry + Envelope + AA-disabling )
};
/** Set the Map2pixel simplification hints for fast rendering of features */
void setSimplifyDrawingHints( int simplifyDrawingHints );
/** Returns the Map2pixel simplification hints for fast rendering of features */
int simplifyDrawingHints() const;
/** Returns whether the VectorLayer can apply the specified simplification hint */
bool simplifyDrawingCanbeApplied( int simplifyHint ) const;
public slots:
/**

View File

@ -101,6 +101,8 @@ class CORE_EXPORT QgsRenderChecker
*/
bool isKnownAnomaly( QString theDiffImageFile );
QString expectedImageFile() { return mExpectedImageFile; };
protected:
QString mReport;

View File

@ -21,12 +21,11 @@
#include <QImage>
#include <QPainter>
QgsCompositionChecker::QgsCompositionChecker( const QString& testName, QgsComposition* composition, const QString& expectedImageFile )
QgsCompositionChecker::QgsCompositionChecker( const QString& testName, QgsComposition* composition )
: QgsRenderChecker( ),
mTestName( testName ),
mComposition( composition )
{
Q_UNUSED( expectedImageFile );
}
QgsCompositionChecker::QgsCompositionChecker()
@ -37,12 +36,6 @@ QgsCompositionChecker::~QgsCompositionChecker()
{
}
bool QgsCompositionChecker::testComposition( int page )
{
QString fake;
return testComposition( fake, page );
}
bool QgsCompositionChecker::testComposition( QString &report, int page )
{
if ( !mComposition )

View File

@ -26,11 +26,10 @@ class QImage;
class QgsCompositionChecker : public QgsRenderChecker
{
public:
QgsCompositionChecker( const QString& testName, QgsComposition* composition, const QString& expectedImageFile = QString() );
QgsCompositionChecker( const QString& testName, QgsComposition* composition );
~QgsCompositionChecker();
bool testComposition( QString &report, int page = 0 );
bool testComposition( int page = 0 );
private:
QgsCompositionChecker(); //forbidden

View File

@ -20,35 +20,40 @@ from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
class QgsCompositionChecker:
class QgsCompositionChecker(QgsRenderChecker):
def __init__(self, mTestName, mComposition ):
self.mExpectedImageFile = ""
self.mComposition = mComposition
self.mTestName = mTestName
super(QgsCompositionChecker, self).__init__()
def testComposition(self, mTestName, mComposition, mExpectedImageFile, page=0 ):
if ( mComposition == None):
def testComposition(self, page=0 ):
if ( self.mComposition == None):
myMessage = "Composition not valid"
return False, myMessage
#load expected image
expectedImage = QImage( mExpectedImageFile )
self.setControlName("expected_"+self.mTestName);
expectedImage = QImage( self.expectedImageFile() )
#get width/height, create image and render the composition to it
width = expectedImage.width();
height = expectedImage.height();
outputImage = QImage( QSize( width, height ), QImage.Format_ARGB32 )
mComposition.setPlotStyle( QgsComposition.Print )
self.mComposition.setPlotStyle( QgsComposition.Print )
outputImage.setDotsPerMeterX( expectedImage.dotsPerMeterX() )
outputImage.setDotsPerMeterY( expectedImage.dotsPerMeterX() )
outputImage.fill( 0 )
p = QPainter( outputImage )
mComposition.renderPage( p, page )
self.mComposition.renderPage( p, page )
p.end()
renderedFilePath = QDir.tempPath() + QDir.separator() + QFileInfo( mExpectedImageFile ).baseName() + "_rendered_python.png"
renderedFilePath = QDir.tempPath() + QDir.separator() + QFileInfo(self.mTestName).baseName() + "_rendered.png"
outputImage.save( renderedFilePath, "PNG" )
diffFilePath = QDir.tempPath() + QDir.separator() + QFileInfo( mExpectedImageFile ).baseName() + "_diff_python.png"
testResult = self.compareImages( expectedImage, outputImage, diffFilePath )
diffFilePath = QDir.tempPath() + QDir.separator() + QFileInfo(self.mTestName).baseName() + "_result_diff.png"
testResult = self.compareImages( self.mTestName, 0, renderedFilePath )
myDashMessage = (('<DartMeasurementFile name="Rendered Image '
'%s" type="image/png">'
@ -59,44 +64,15 @@ class QgsCompositionChecker:
'<DartMeasurementFile name="Difference Image '
'%s" type="image/png">'
'%s</DartMeasurementFile>') %
(mTestName, renderedFilePath, mTestName,
mExpectedImageFile, mTestName, diffFilePath )
(self.mTestName, renderedFilePath, self.mTestName,
self.expectedImageFile(), self.mTestName, diffFilePath )
)
qDebug( myDashMessage )
if not testResult:
myMessage = ('Expected: %s\nGot: %s\nDifference: %s\n' %
(mExpectedImageFile, renderedFilePath, diffFilePath))
(self.expectedImageFile(), renderedFilePath, diffFilePath))
else:
myMessage = 'Control and test images matched.'
return testResult, myMessage
def compareImages( self, imgExpected, imgRendered, differenceImagePath ):
if ( imgExpected.width() != imgRendered.width()
or imgExpected.height() != imgRendered.height() ):
return False
imageWidth = imgExpected.width()
imageHeight = imgExpected.height()
mismatchCount = 0
differenceImage = QImage(
imageWidth, imageHeight, QImage.Format_ARGB32_Premultiplied )
differenceImage.fill( qRgb( 152, 219, 249 ) )
pixel1 = QColor().rgb()
pixel2 = QColor().rgb()
for i in range( imageHeight ):
for j in range( imageWidth ):
pixel1 = imgExpected.pixel( j, i )
pixel2 = imgRendered.pixel( j, i )
if ( pixel1 != pixel2 ):
mismatchCount = mismatchCount + 1
differenceImage.setPixel( j, i, qRgb( 255, 0, 0 ) )
if differenceImagePath != "":
differenceImage.save( differenceImagePath, "PNG" )
#allow pixel deviation of 1 percent
pixelCount = imageWidth * imageHeight;
return (float(mismatchCount) / float(pixelCount) ) < 0.01

View File

@ -121,13 +121,10 @@ class TestQgsAtlasComposition(unittest.TestCase):
self.mAtlas.prepareForFeature( i )
self.mLabel1.adjustSizeToText()
checker = QgsCompositionChecker()
res = checker.testComposition( "Atlas autoscale test", self.mComposition, \
self.TEST_DATA_DIR + QDir.separator() + \
"control_images" + QDir.separator() + \
"expected_composermapatlas" + QDir.separator() + \
"autoscale_%d.png" % i )
assert res[0] == True
checker = QgsCompositionChecker('atlas_autoscale%d' % (i + 1), self.mComposition)
myTestResult, myMessage = checker.testComposition()
assert myTestResult == True
self.mAtlas.endRender()
def fixedscale_render_test( self ):
@ -140,13 +137,10 @@ class TestQgsAtlasComposition(unittest.TestCase):
self.mAtlas.prepareForFeature( i )
self.mLabel1.adjustSizeToText()
checker = QgsCompositionChecker()
res = checker.testComposition( "Atlas fixed scale test", self.mComposition, \
self.TEST_DATA_DIR + QDir.separator() + \
"control_images" + QDir.separator() + \
"expected_composermapatlas" + QDir.separator() + \
"fixedscale_%d.png" % i )
assert res[0] == True
checker = QgsCompositionChecker('atlas_fixedscale%d' % (i + 1), self.mComposition)
myTestResult, myMessage = checker.testComposition()
assert myTestResult == True
self.mAtlas.endRender()
def hidden_render_test( self ):
@ -160,13 +154,10 @@ class TestQgsAtlasComposition(unittest.TestCase):
self.mAtlas.prepareForFeature( i )
self.mLabel1.adjustSizeToText()
checker = QgsCompositionChecker()
res = checker.testComposition( "Atlas hidden test", self.mComposition, \
self.TEST_DATA_DIR + QDir.separator() + \
"control_images" + QDir.separator() + \
"expected_composermapatlas" + QDir.separator() + \
"hiding_%d.png" % i )
assert res[0] == True
checker = QgsCompositionChecker('atlas_hiding%d' % (i + 1), self.mComposition)
myTestResult, myMessage = checker.testComposition()
assert myTestResult == True
self.mAtlas.endRender()
def sorting_render_test( self ):
@ -184,13 +175,10 @@ class TestQgsAtlasComposition(unittest.TestCase):
self.mAtlas.prepareForFeature( i )
self.mLabel1.adjustSizeToText()
checker = QgsCompositionChecker()
res = checker.testComposition( "Atlas sorting test", self.mComposition, \
self.TEST_DATA_DIR + QDir.separator() + \
"control_images" + QDir.separator() + \
"expected_composermapatlas" + QDir.separator() + \
"sorting_%d.png" % i )
assert res[0] == True
checker = QgsCompositionChecker('atlas_sorting%d' % (i + 1), self.mComposition)
myTestResult, myMessage = checker.testComposition()
assert myTestResult == True
self.mAtlas.endRender()
def filtering_render_test( self ):
@ -209,13 +197,10 @@ class TestQgsAtlasComposition(unittest.TestCase):
self.mAtlas.prepareForFeature( i )
self.mLabel1.adjustSizeToText()
checker = QgsCompositionChecker()
res = checker.testComposition( "Atlas filtering test", self.mComposition, \
self.TEST_DATA_DIR + QDir.separator() + \
"control_images" + QDir.separator() + \
"expected_composermapatlas" + QDir.separator() + \
"filtering_%d.png" % i )
assert res[0] == True
checker = QgsCompositionChecker('atlas_filtering%d' % (i + 1), self.mComposition)
myTestResult, myMessage = checker.testComposition()
assert myTestResult == True
self.mAtlas.endRender()
if __name__ == '__main__':

View File

@ -66,11 +66,13 @@ class TestQgsBlendModes(TestCase):
# create polygon layer
myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp')
self.mPolygonLayer = QgsVectorLayer(myShpFile, 'Polygons', 'ogr')
self.mPolygonLayer.setSimplifyDrawingHints(QgsVectorLayer.NoSimplification)
self.mMapRegistry.addMapLayer(self.mPolygonLayer)
# create line layer
myShpFile = os.path.join(TEST_DATA_DIR, 'lines.shp')
self.mLineLayer = QgsVectorLayer(myShpFile, 'Lines', 'ogr')
self.mLineLayer.setSimplifyDrawingHints(QgsVectorLayer.NoSimplification)
self.mMapRegistry.addMapLayer(self.mLineLayer)
# create two raster layers

View File

@ -61,13 +61,9 @@ class TestQgsComposerEffects(TestCase):
self.mComposerRect2.setBlendMode(QPainter.CompositionMode_Multiply)
checker = QgsCompositionChecker()
myPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composereffects',
'composereffect_blend.png')
myTestResult, myMessage = checker.testComposition('Composer effects blending',
self.mComposition, myPath)
checker = QgsCompositionChecker('composereffects_blend', self.mComposition)
myTestResult, myMessage = checker.testComposition()
self.mComposerRect2.setBlendMode(QPainter.CompositionMode_SourceOver)
assert myTestResult == True, myMessage
@ -77,13 +73,9 @@ class TestQgsComposerEffects(TestCase):
self.mComposerRect2.setTransparency( 50 )
checker = QgsCompositionChecker()
myPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composereffects',
'composereffect_transparency.png')
myTestResult, myMessage = checker.testComposition('Composer effects transparency',
self.mComposition, myPath)
checker = QgsCompositionChecker('composereffects_transparency', self.mComposition)
myTestResult, myMessage = checker.testComposition()
self.mComposerRect2.setTransparency( 100 )
assert myTestResult == True, myMessage

View File

@ -43,23 +43,13 @@ class TestQgsComposerHtml(TestCase):
"""Run after each test."""
print "Tear down"
def controlImagePath(self, theImageName):
"""Helper to get the path to a control image."""
myPath = os.path.join(TEST_DATA_DIR,
"control_images",
"expected_composerhtml",
theImageName)
assert os.path.exists(myPath)
return myPath
def htmlUrl(self):
"""Helper to get the url of the html doc."""
myPath = os.path.join(TEST_DATA_DIR, "html_table.html")
myUrl = QUrl("file:///%1").arg(myPath)
myUrl = QUrl("file:///" + myPath)
return myUrl
@expectedFailure
def XtestTable(self):
def testTable(self):
"""Test we can render a html table in a single frame."""
composerHtml = QgsComposerHtml(self.mComposition, False)
htmlFrame = QgsComposerFrame(self.mComposition,
@ -67,16 +57,14 @@ class TestQgsComposerHtml(TestCase):
htmlFrame.setFrameEnabled(True)
composerHtml.addFrame(htmlFrame)
composerHtml.setUrl(self.htmlUrl())
checker = QgsCompositionChecker()
myResult, myMessage = checker.testComposition(
"Composer html table",
self.mComposition,
self.controlImagePath("composerhtml_table.png"))
qDebug(myMessage)
assert myResult, myMessage
@expectedFailure
def XtestTableMultiFrame(self):
checker = QgsCompositionChecker('composerhtml_table', self.mComposition)
myTestResult, myMessage = checker.testComposition()
qDebug(myMessage)
assert myTestResult, myMessage
def testTableMultiFrame(self):
"""Test we can render to multiframes."""
composerHtml = QgsComposerHtml(self.mComposition, False)
htmlFrame = QgsComposerFrame(self.mComposition, composerHtml,
@ -87,38 +75,23 @@ class TestQgsComposerHtml(TestCase):
composerHtml.setUrl(self.htmlUrl())
composerHtml.frame(0).setFrameEnabled(True)
myPage = 0
checker1 = QgsCompositionChecker()
myControlImage = self.controlImagePath(
"composerhtml_table_multiframe1.png")
print "Checking page 1"
myResult, myMessage = checker1.testComposition("Composer html table",
self.mComposition,
myControlImage,
myPage)
assert myResult, myMessage
myPage = 0
checker1 = QgsCompositionChecker('composerhtml_multiframe1', self.mComposition)
myTestResult, myMessage = checker1.testComposition( myPage )
assert myTestResult, myMessage
myPage = 1
checker2 = QgsCompositionChecker()
myControlImage = self.controlImagePath(
"composerhtml_table_multiframe2.png")
print "Checking page 2"
myResult, myMessage = checker2.testComposition("Composer html table",
self.mComposition,
myControlImage,
myPage)
assert myResult, myMessage
myPage = 1
checker2 = QgsCompositionChecker('composerhtml_multiframe2', self.mComposition)
myTestResult, myMessage = checker2.testComposition( myPage )
assert myTestResult, myMessage
myPage = 2
checker3 = QgsCompositionChecker()
myControlImage = self.controlImagePath(
"composerhtml_table_multiframe3.png")
myResult, myMessage = checker3.testComposition("Composer html table",
self.mComposition,
myControlImage,
myPage)
print "Checking page 3"
assert myResult, myMessage
myPage = 2
checker3 = QgsCompositionChecker('composerhtml_multiframe3', self.mComposition)
myTestResult, myMessage = checker3.testComposition( myPage )
assert myTestResult, myMessage
def testComposerHtmlAccessor(self):
"""Test that we can retrieve the ComposerHtml instance given an item.

View File

@ -95,13 +95,8 @@ class TestQgsComposerMap(TestCase):
QgsComposerMap.Bottom)
self.mComposerMap.setAnnotationFontColor(QColor(255,0,0,150))
self.mComposerMap.setGridBlendMode(QPainter.CompositionMode_Overlay)
checker = QgsCompositionChecker()
myPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composermap',
'composermap_landsat_grid.png')
myTestResult, myMessage = checker.testComposition('Composer map grid',
self.mComposition, myPath)
checker = QgsCompositionChecker('composermap_grid', self.mComposition)
myTestResult, myMessage = checker.testComposition()
self.mComposerMap.setGridEnabled(False)
self.mComposerMap.setShowGridAnnotation(False)
@ -119,15 +114,8 @@ class TestQgsComposerMap(TestCase):
793062.375, 3350923.125)
overviewMap.setNewExtent(myRectangle2)
overviewMap.setOverviewFrameMap(self.mComposerMap.id())
checker = QgsCompositionChecker()
myPngPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composermap',
'composermap_landsat_overview.png')
myTestResult, myMessage = checker.testComposition(
'Composer map overview',
self.mComposition,
myPngPath)
checker = QgsCompositionChecker('composermap_overview', self.mComposition)
myTestResult, myMessage = checker.testComposition()
self.mComposition.removeComposerItem(overviewMap)
assert myTestResult == True, myMessage
@ -144,15 +132,8 @@ class TestQgsComposerMap(TestCase):
overviewMap.setNewExtent(myRectangle2)
overviewMap.setOverviewFrameMap(self.mComposerMap.id())
overviewMap.setOverviewBlendMode(QPainter.CompositionMode_Multiply)
checker = QgsCompositionChecker()
myPngPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composermap',
'composermap_landsat_overview_blend.png')
myTestResult, myMessage = checker.testComposition(
'Composer map overview blending',
self.mComposition,
myPngPath)
checker = QgsCompositionChecker('composermap_overview_blending', self.mComposition)
myTestResult, myMessage = checker.testComposition()
self.mComposition.removeComposerItem(overviewMap)
assert myTestResult == True, myMessage
@ -169,15 +150,8 @@ class TestQgsComposerMap(TestCase):
overviewMap.setNewExtent(myRectangle2)
overviewMap.setOverviewFrameMap(self.mComposerMap.id())
overviewMap.setOverviewInverted(True)
checker = QgsCompositionChecker()
myPngPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composermap',
'composermap_landsat_overview_invert.png')
myTestResult, myMessage = checker.testComposition(
'Composer map overview inverted',
self.mComposition,
myPngPath)
checker = QgsCompositionChecker('composermap_overview_invert', self.mComposition)
myTestResult, myMessage = checker.testComposition()
self.mComposition.removeComposerItem(overviewMap)
assert myTestResult == True, myMessage
@ -195,15 +169,8 @@ class TestQgsComposerMap(TestCase):
overviewMap.setOverviewFrameMap(self.mComposerMap.id())
overviewMap.setOverviewInverted(False)
overviewMap.setOverviewCentered(True)
checker = QgsCompositionChecker()
myPngPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composermap',
'composermap_landsat_overview_center.png')
myTestResult, myMessage = checker.testComposition(
'Composer map overview centered',
self.mComposition,
myPngPath)
checker = QgsCompositionChecker('composermap_overview_center', self.mComposition)
myTestResult, myMessage = checker.testComposition()
self.mComposition.removeComposerItem(overviewMap)
assert myTestResult == True, myMessage
@ -239,15 +206,16 @@ class TestQgsComposerMap(TestCase):
self.mComposerMap.setGridEnabled(True)
self.mComposerMap.setGridIntervalX(2000)
self.mComposerMap.setGridIntervalY(2000)
checker = QgsCompositionChecker()
myPngPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composermap',
'composermap_zebra_style.png')
testResult, myMessage = checker.testComposition('Composer map zebra',
self.mComposition,
myPngPath)
assert testResult == True, myMessage
self.mComposerMap.setGridFrameWidth( 10 )
self.mComposerMap.setGridFramePenSize( 1 )
self.mComposerMap.setGridPenWidth( 0.5 )
self.mComposerMap.setGridFramePenColor( QColor( 255, 100, 0, 200 ) )
self.mComposerMap.setGridFrameFillColor1( QColor( 50, 90, 50, 100 ) )
self.mComposerMap.setGridFrameFillColor2( QColor( 200, 220, 100, 60 ) )
checker = QgsCompositionChecker('composermap_zebrastyle', self.mComposition)
myTestResult, myMessage = checker.testComposition()
assert myTestResult == True, myMessage
def testWorldFileGeneration( self ):
myRectangle = QgsRectangle(781662.375, 3339523.125, 793062.375, 3345223.125)

View File

@ -53,13 +53,8 @@ class TestQgsComposerShapes(TestCase):
self.mComposerShape.setShapeType(QgsComposerShape.Rectangle)
checker = QgsCompositionChecker()
myPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composershapes',
'composershape_rectangle.png')
myTestResult, myMessage = checker.testComposition('Composer shapes rectangle',
self.mComposition, myPath)
checker = QgsCompositionChecker('composershapes_rectangle', self.mComposition)
myTestResult, myMessage = checker.testComposition()
assert myTestResult == True, myMessage
@ -68,13 +63,8 @@ class TestQgsComposerShapes(TestCase):
self.mComposerShape.setShapeType(QgsComposerShape.Ellipse)
checker = QgsCompositionChecker()
myPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composershapes',
'composershape_ellipse.png')
myTestResult, myMessage = checker.testComposition('Composer shapes ellipse',
self.mComposition, myPath)
checker = QgsCompositionChecker('composershapes_ellipse', self.mComposition)
myTestResult, myMessage = checker.testComposition()
assert myTestResult == True, myMessage
@ -83,13 +73,8 @@ class TestQgsComposerShapes(TestCase):
self.mComposerShape.setShapeType(QgsComposerShape.Triangle)
checker = QgsCompositionChecker()
myPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composershapes',
'composershape_triangle.png')
myTestResult, myMessage = checker.testComposition('Composer shapes triangle',
self.mComposition, myPath)
checker = QgsCompositionChecker('composershapes_triangle', self.mComposition)
myTestResult, myMessage = checker.testComposition()
assert myTestResult == True, myMessage
@ -99,13 +84,8 @@ class TestQgsComposerShapes(TestCase):
self.mComposerShape.setShapeType(QgsComposerShape.Rectangle)
self.mComposerShape.setCornerRadius(30)
checker = QgsCompositionChecker()
myPath = os.path.join(TEST_DATA_DIR,
'control_images',
'expected_composershapes',
'composershape_roundedrectangle.png')
myTestResult, myMessage = checker.testComposition('Composer shapes rounded rectangle',
self.mComposition, myPath)
checker = QgsCompositionChecker('composershapes_roundedrect', self.mComposition)
myTestResult, myMessage = checker.testComposition()
self.mComposerShape.setCornerRadius(0)
assert myTestResult == True, myMessage

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B