mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-26 00:02:08 -05:00
Added a helper class for unit tests that will compare an image with a maprender product and return true or false based on their equiality or on the time it takes to render the output. It will also produce a difference image so that dissimilar areas in the two images can easily be identified. Lastly it generates a simple report as an html snippet for easy inclusion of results in a test report in a web browser.
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@8016 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
6e4cfb4d15
commit
0290817030
191
tests/src/core/qgsrenderchecker.cpp
Normal file
191
tests/src/core/qgsrenderchecker.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
/***************************************************************************
|
||||
qgsrenderchecker.cpp
|
||||
--------------------------------------
|
||||
Date : 18 Jan 2008
|
||||
Copyright : (C) 2008 by Tim Sutton
|
||||
Email : tim @ linfiniti.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsrenderchecker.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QColor>
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
#include <QTime>
|
||||
|
||||
|
||||
QgsRenderChecker::QgsRenderChecker( ) :
|
||||
mReport(""),
|
||||
mExpectedImageFile(""),
|
||||
mMismatchCount(0),
|
||||
mMatchTarget(0),
|
||||
mElapsedTime(0),
|
||||
mElapsedTimeTarget(0),
|
||||
mpMapRenderer(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
bool QgsRenderChecker::runTest( QString theTestName )
|
||||
{
|
||||
if (mExpectedImageFile.isEmpty())
|
||||
{
|
||||
qDebug("QgsRenderChecker::runTest failed - Expected Image File not set.");
|
||||
mReport= "<table>"
|
||||
"<tr><td>Test Result:</td><td>Expected Result:</td></tr>\n"
|
||||
"<tr><td>Nothing rendered</td>\n<td>Failed because Expected "
|
||||
"Image File not set.</td></tr></table>\n";
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Load the expected result pixmap
|
||||
//
|
||||
QImage myExpectedImage (mExpectedImageFile);
|
||||
mMatchTarget = myExpectedImage.width() * myExpectedImage.height();
|
||||
//
|
||||
// Now render our layers onto a pixmap
|
||||
//
|
||||
QImage myImage( myExpectedImage.width() , myExpectedImage.height(), QImage::Format_RGB32 );
|
||||
QImage myDifferenceImage( myExpectedImage.width() , myExpectedImage.height(), QImage::Format_RGB32);
|
||||
QString myResultDiffImage = QDir::tempPath() + QDir::separator() + theTestName + "_result_diff.png";
|
||||
myImage.fill ( QColor ( "#98dbf9" ).pixel() );
|
||||
myDifferenceImage.fill ( QColor ( "#98dbf9" ).pixel() );
|
||||
QPainter myPainter( &myImage );
|
||||
mpMapRenderer->setOutputSize( QSize ( myExpectedImage.width(),myExpectedImage.height() ),72 );
|
||||
QTime myTime;
|
||||
myTime.start();
|
||||
mpMapRenderer->render( &myPainter );
|
||||
mElapsedTime = myTime.elapsed();
|
||||
myPainter.end();
|
||||
//
|
||||
// Save the pixmap to disk so the user can make a
|
||||
// visual assessment if needed
|
||||
//
|
||||
QString myResultImage = QDir::tempPath() + QDir::separator() + theTestName + "_result.png";
|
||||
myImage.save (myResultImage);
|
||||
//
|
||||
// Set pixel count score and target
|
||||
//
|
||||
mMatchTarget = myExpectedImage.width() * myExpectedImage.height();
|
||||
int myPixelCount = myImage.width() * myImage.height();
|
||||
//
|
||||
// Set the report with the result
|
||||
//
|
||||
mReport= "<table>";
|
||||
mReport += "<tr><td colspan=2>";
|
||||
mReport += "Test image and result image for " + theTestName + "<br>"
|
||||
"Expected size: " + QString::number(myExpectedImage.width()).toLocal8Bit() + "w x " +
|
||||
QString::number(myExpectedImage.width()).toLocal8Bit() + "h (" +
|
||||
QString::number(mMatchTarget).toLocal8Bit() + " pixels)<br>"
|
||||
"Actual size: " + QString::number(myImage.width()).toLocal8Bit() + "w x " +
|
||||
QString::number(myImage.width()).toLocal8Bit() + "h (" +
|
||||
QString::number(myPixelCount).toLocal8Bit() + " pixels)";
|
||||
mReport += "</td></tr>";
|
||||
mReport += "<tr><td colspan = 2>\n";
|
||||
mReport += "Expected Duration : <= " + QString::number(mElapsedTimeTarget) +
|
||||
"ms (0 indicates not specified)<br>";
|
||||
mReport += "Actual Duration : " + QString::number(mElapsedTime) + "ms<br>";
|
||||
QString myImagesString= "</td></tr>"
|
||||
"<tr><td>Test Result:</td><td>Expected Result:</td><td>Difference (all blue is good, any red is bad)</td></tr>\n"
|
||||
"<tr><td><img src=\"" +
|
||||
myResultImage +
|
||||
"\"></td>\n<td><img src=\"" +
|
||||
mExpectedImageFile +
|
||||
"\"></td><td><img src=\"" +
|
||||
myResultDiffImage +
|
||||
"\"></td>\n</tr>\n</table>";
|
||||
//
|
||||
// Put the same info to debug too
|
||||
//
|
||||
qDebug ("Expected size: " + QString::number(myExpectedImage.width()).toLocal8Bit() + + "w x " +
|
||||
QString::number(myExpectedImage.width()).toLocal8Bit() + + "h");
|
||||
qDebug ("Actual size: " + QString::number(myImage.width()).toLocal8Bit() + + "w x " +
|
||||
QString::number(myImage.width()).toLocal8Bit() + + "h");
|
||||
//
|
||||
// Now load the renderered image and the expected image
|
||||
// and then iterate through them counting how many
|
||||
// dissimilar pixel values there are
|
||||
//
|
||||
|
||||
if (mMatchTarget!= myPixelCount )
|
||||
{
|
||||
qDebug ("Test image and result image for " + theTestName + " are different - FAILING!");
|
||||
mReport += "<tr><td colspan=3>";
|
||||
mReport += "<font color=red>Expected image and result image for " + theTestName + " are different dimensions - FAILING!</font>";
|
||||
mReport += "</td></tr>";
|
||||
mReport += myImagesString;
|
||||
return false;
|
||||
}
|
||||
mMismatchCount = 0;
|
||||
for (int x = 0; x < myExpectedImage.width(); ++x)
|
||||
{
|
||||
for (int y = 0; y < myExpectedImage.height(); ++y)
|
||||
{
|
||||
QRgb myExpectedPixel = myExpectedImage.pixel(x,y);
|
||||
QRgb myActualPixel = myImage.pixel(x,y);
|
||||
if (myExpectedPixel != myActualPixel)
|
||||
{
|
||||
++mMismatchCount;
|
||||
myDifferenceImage.setPixel(x,y,QColor (255,0,0).pixel());
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
//save the diff image to disk
|
||||
//
|
||||
myDifferenceImage.save (myResultDiffImage);
|
||||
|
||||
//
|
||||
// Send match result to debug
|
||||
//
|
||||
qDebug (QString::number(mMismatchCount).toLocal8Bit() + "/" +
|
||||
QString::number(mMatchTarget).toLocal8Bit() +
|
||||
" pixels mismatched");;
|
||||
|
||||
//
|
||||
// Send match result to report
|
||||
//
|
||||
mReport += "<tr><td colspan=3>" +
|
||||
QString::number(mMismatchCount) + "/" +
|
||||
QString::number(mMatchTarget) +
|
||||
" pixels mismatched";
|
||||
mReport += "</td></tr>";
|
||||
|
||||
|
||||
if ( mMismatchCount==0 )
|
||||
{
|
||||
mReport += "<tr><td colspan = 3>\n";
|
||||
mReport += "Test image and result image for " + theTestName + " are matched<br>";
|
||||
mReport += "</td></tr>";
|
||||
if (mElapsedTimeTarget != 0 && mElapsedTimeTarget < mElapsedTime)
|
||||
{
|
||||
//test failed because it took too long...
|
||||
qDebug("Test failed because render step took too long");
|
||||
mReport += "<tr><td colspan = 3>\n";
|
||||
mReport += "<font color=red>Test failed because render step took too long</font>";
|
||||
mReport += "</td></tr>";
|
||||
mReport += myImagesString;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReport += myImagesString;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mReport += "<tr><td colspan = 3>\n";
|
||||
mReport += "<font color=red>Test image and result image for " + theTestName + " are mismatched</font><br>";
|
||||
mReport += "</td></tr>";
|
||||
mReport += myImagesString;
|
||||
return false;
|
||||
}
|
||||
}
|
65
tests/src/core/qgsrenderchecker.h
Normal file
65
tests/src/core/qgsrenderchecker.h
Normal file
@ -0,0 +1,65 @@
|
||||
/***************************************************************************
|
||||
qgsrenderchecker.h - check maprender output against an expected image
|
||||
--------------------------------------
|
||||
Date : 18 Jan 2008
|
||||
Copyright : (C) 2008 by Tim Sutton
|
||||
email : tim @ linfiniti.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
/* $Id: qgsfield.h 6833 2007-03-24 22:40:10Z wonder $ */
|
||||
|
||||
#ifndef QGSRENDERCHECKER_H
|
||||
#define QGSRENDERCHECKER_H
|
||||
|
||||
#include <QString>
|
||||
#include <qgsmaprender.h>
|
||||
|
||||
|
||||
/** \ingroup UnitTests
|
||||
* This is a helper class for unit tests that need to
|
||||
* write an image and compare it to an expected result
|
||||
* or render time.
|
||||
*/
|
||||
class QgsRenderChecker
|
||||
{
|
||||
public:
|
||||
|
||||
QgsRenderChecker();
|
||||
|
||||
//! Destructor
|
||||
~QgsRenderChecker(){};
|
||||
|
||||
QString report() { return mReport; };
|
||||
float matchPercent() { return static_cast<float>(mMismatchCount) /
|
||||
static_cast<float>(mMatchTarget) * 100; };
|
||||
unsigned int mismatchCount() { return mMismatchCount; };
|
||||
unsigned int matchTarget() { return mMatchTarget; };
|
||||
//only records time for actual render part
|
||||
int elapsedTime() { return mElapsedTime; };
|
||||
void setElapsedTimeTarget(int theTarget) { mElapsedTimeTarget = theTarget; };
|
||||
void setExpectedImage (QString theImageFileName) { mExpectedImageFile = theImageFileName; };
|
||||
void setMapRenderer ( QgsMapRender * thepMapRenderer) { mpMapRenderer = thepMapRenderer; };
|
||||
/**
|
||||
* @param theTestName - to be used as the basis for writing a file to
|
||||
* /tmp/theTestName.png
|
||||
*/
|
||||
bool runTest( QString theTestName );
|
||||
|
||||
private:
|
||||
QString mReport;
|
||||
QString mExpectedImageFile;
|
||||
unsigned int mMismatchCount;
|
||||
unsigned int mMatchTarget;
|
||||
int mElapsedTime;
|
||||
int mElapsedTimeTarget;
|
||||
QgsMapRender * mpMapRenderer;
|
||||
|
||||
}; // class QgsRenderChecker
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user