From 08afe8200d916ed2e1da2d194ef72f5f2b7ee769 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 4 Oct 2023 10:26:41 +1000 Subject: [PATCH] Cleanup c++ layout tests - Use common methods - Ensure all tests pass under memory sanitiser builds without issues --- src/core/qgsmultirenderchecker.cpp | 3 + src/test/qgstest.h | 6 +- tests/src/core/testqgslayoutatlas.cpp | 40 ++--- tests/src/core/testqgslayoutcontext.cpp | 6 + tests/src/core/testqgslayoutexporter.cpp | 15 +- tests/src/core/testqgslayouthtml.cpp | 53 ++----- tests/src/core/testqgslayoutitem.cpp | 79 ++++------ tests/src/core/testqgslayoutitemgroup.cpp | 6 +- tests/src/core/testqgslayoutlabel.cpp | 23 +-- tests/src/core/testqgslayoutmanualtable.cpp | 28 +--- tests/src/core/testqgslayoutmap.cpp | 38 ++--- tests/src/core/testqgslayoutmapgrid.cpp | 146 +++++------------- tests/src/core/testqgslayoutmapoverview.cpp | 39 +---- tests/src/core/testqgslayoutmodel.cpp | 18 +-- tests/src/core/testqgslayoutobject.cpp | 6 + tests/src/core/testqgslayoutpage.cpp | 31 ++-- tests/src/core/testqgslayoutpicture.cpp | 87 +++-------- tests/src/core/testqgslayoutpolyline.cpp | 23 +-- tests/src/core/testqgslayoutscalebar.cpp | 78 +++------- tests/src/core/testqgslayoutshapes.cpp | 31 ++-- tests/src/core/testqgslayouttable.cpp | 80 ++-------- tests/src/core/testqgslayoutunits.cpp | 4 +- tests/src/core/testqgslayoututils.cpp | 38 ++--- ...ibutetable_conditionalstyles_text_mask.png | Bin 25326 -> 25349 bytes 24 files changed, 260 insertions(+), 618 deletions(-) diff --git a/src/core/qgsmultirenderchecker.cpp b/src/core/qgsmultirenderchecker.cpp index 1ca95f5b1dd5..ccb8a233c0d5 100644 --- a/src/core/qgsmultirenderchecker.cpp +++ b/src/core/qgsmultirenderchecker.cpp @@ -242,6 +242,9 @@ bool QgsLayoutChecker::testLayout( QString &checkedReport, int page, int pixelDi p.end(); QString renderedFilePath = QDir::tempPath() + '/' + QFileInfo( mTestName ).baseName() + "_rendered.png"; + if ( QFile::exists( renderedFilePath ) ) + QFile::remove( renderedFilePath ); + outputImage.save( renderedFilePath, "PNG" ); setRenderedImage( renderedFilePath ); diff --git a/src/test/qgstest.h b/src/test/qgstest.h index 76e180042807..92f52f65d85e 100644 --- a/src/test/qgstest.h +++ b/src/test/qgstest.h @@ -201,10 +201,14 @@ class TEST_EXPORT QgsTest : public QObject return result; } - bool layoutCheck( const QString &name, QgsLayout *layout, int page = 0, int allowedMismatch = 0 ) + bool layoutCheck( const QString &name, QgsLayout *layout, int page = 0, int allowedMismatch = 0, const QSize size = QSize(), int colorTolerance = 0 ) { QgsLayoutChecker checker( name, layout ); checker.setControlPathPrefix( mControlPathPrefix ); + if ( size.isValid() ) + checker.setSize( size ); + if ( colorTolerance > 0 ) + checker.setColorTolerance( colorTolerance ); QString report; const bool result = checker.testLayout( report, page, allowedMismatch ); diff --git a/tests/src/core/testqgslayoutatlas.cpp b/tests/src/core/testqgslayoutatlas.cpp index e7b61ce686d5..b335641cb4df 100644 --- a/tests/src/core/testqgslayoutatlas.cpp +++ b/tests/src/core/testqgslayoutatlas.cpp @@ -16,7 +16,6 @@ ***************************************************************************/ #include "qgsapplication.h" -#include "qgsmultirenderchecker.h" #include "qgslayoutitemmap.h" #include "qgslayoutitemmapoverview.h" #include "qgslayoutatlas.h" @@ -39,13 +38,14 @@ class TestQgsLayoutAtlas : public QgsTest Q_OBJECT public: - TestQgsLayoutAtlas() : QgsTest( QStringLiteral( "Layout Atlas Tests" ) ) {} + TestQgsLayoutAtlas() + : QgsTest( QStringLiteral( "Layout Atlas Tests" ), QStringLiteral( "atlas" ) ) {} private slots: - void initTestCase();// will be called before the first testfunction is executed. - void cleanupTestCase();// will be called after the last testfunction was executed. - void init();// will be called before each testfunction is executed. - void cleanup();// will be called after every testfunction. + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); // test filename pattern evaluation void filename(); @@ -215,9 +215,7 @@ void TestQgsLayoutAtlas::autoscale_render() mAtlas->seekTo( fit ); mLabel1->adjustSizeToText(); - QgsLayoutChecker checker( QStringLiteral( "atlas_autoscale%1" ).arg( ( ( int )fit ) + 1 ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "atlas" ) ); - QVERIFY( checker.testLayout( mReport, 0, 100 ) ); + QVERIFY( layoutCheck( QStringLiteral( "atlas_autoscale%1" ).arg( ( ( int )fit ) + 1 ), mLayout, 0, 100 ) ); } mAtlas->endRender(); } @@ -237,9 +235,7 @@ void TestQgsLayoutAtlas::fixedscale_render() mAtlas->seekTo( fit ); mLabel1->adjustSizeToText(); - QgsLayoutChecker checker( QStringLiteral( "atlas_fixedscale%1" ).arg( ( ( int )fit ) + 1 ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "atlas" ) ); - QVERIFY( checker.testLayout( mReport, 0, 100 ) ); + QVERIFY( layoutCheck( QStringLiteral( "atlas_fixedscale%1" ).arg( ( ( int )fit ) + 1 ), mLayout, 0, 100 ) ); } mAtlas->endRender(); } @@ -271,9 +267,7 @@ void TestQgsLayoutAtlas::predefinedscales_render() mAtlas->seekTo( fit ); mLabel1->adjustSizeToText(); - QgsLayoutChecker checker( QStringLiteral( "atlas_predefinedscales%1" ).arg( ( ( int )fit ) + 1 ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "atlas" ) ); - QVERIFY( checker.testLayout( mReport, 0, 100 ) ); + QVERIFY( layoutCheck( QStringLiteral( "atlas_predefinedscales%1" ).arg( ( ( int )fit ) + 1 ), mLayout, 0, 100 ) ); } mAtlas->endRender(); } @@ -295,9 +289,7 @@ void TestQgsLayoutAtlas::two_map_autoscale_render() mAtlas->seekTo( fit ); mLabel1->adjustSizeToText(); - QgsLayoutChecker checker( QStringLiteral( "atlas_two_maps%1" ).arg( ( ( int )fit ) + 1 ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "atlas" ) ); - QVERIFY( checker.testLayout( mReport, 0, 100 ) ); + QVERIFY( layoutCheck( QStringLiteral( "atlas_two_maps%1" ).arg( ( ( int )fit ) + 1 ), mLayout, 0, 100 ) ); } mAtlas->endRender(); } @@ -316,9 +308,7 @@ void TestQgsLayoutAtlas::hiding_render() mAtlas->seekTo( fit ); mLabel1->adjustSizeToText(); - QgsLayoutChecker checker( QStringLiteral( "atlas_hiding%1" ).arg( ( ( int )fit ) + 1 ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "atlas" ) ); - QVERIFY( checker.testLayout( mReport, 0, 100 ) ); + QVERIFY( layoutCheck( QStringLiteral( "atlas_hiding%1" ).arg( ( ( int )fit ) + 1 ), mLayout, 0, 100 ) ); } mAtlas->endRender(); } @@ -341,9 +331,7 @@ void TestQgsLayoutAtlas::sorting_render() mAtlas->seekTo( fit ); mLabel1->adjustSizeToText(); - QgsLayoutChecker checker( QStringLiteral( "atlas_sorting%1" ).arg( ( ( int )fit ) + 1 ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "atlas" ) ); - QVERIFY( checker.testLayout( mReport, 0, 100 ) ); + QVERIFY( layoutCheck( QStringLiteral( "atlas_sorting%1" ).arg( ( ( int )fit ) + 1 ), mLayout, 0, 100 ) ); } mAtlas->endRender(); } @@ -368,9 +356,7 @@ void TestQgsLayoutAtlas::filtering_render() mAtlas->seekTo( fit ); mLabel1->adjustSizeToText(); - QgsLayoutChecker checker( QStringLiteral( "atlas_filtering%1" ).arg( ( ( int )fit ) + 1 ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "atlas" ) ); - QVERIFY( checker.testLayout( mReport, 0, 100 ) ); + QVERIFY( layoutCheck( QStringLiteral( "atlas_filtering%1" ).arg( ( ( int )fit ) + 1 ), mLayout, 0, 100 ) ); } mAtlas->endRender(); } diff --git a/tests/src/core/testqgslayoutcontext.cpp b/tests/src/core/testqgslayoutcontext.cpp index 21ec4c4ea638..e5750917dfba 100644 --- a/tests/src/core/testqgslayoutcontext.cpp +++ b/tests/src/core/testqgslayoutcontext.cpp @@ -37,6 +37,7 @@ class TestQgsLayoutContext: public QgsTest private slots: + void cleanupTestCase(); void creation(); //test creation of QgsLayout void flags(); //test QgsLayout flags void feature(); @@ -51,6 +52,11 @@ class TestQgsLayoutContext: public QgsTest }; +void TestQgsLayoutContext::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + void TestQgsLayoutContext::creation() { QgsLayoutRenderContext *context = new QgsLayoutRenderContext( nullptr ); diff --git a/tests/src/core/testqgslayoutexporter.cpp b/tests/src/core/testqgslayoutexporter.cpp index 4d3fc1b135ca..67f8898981a3 100644 --- a/tests/src/core/testqgslayoutexporter.cpp +++ b/tests/src/core/testqgslayoutexporter.cpp @@ -26,15 +26,19 @@ #include "qgsvectorlayer.h" #include "qgslayoutitemlegend.h" -class TestQgsLayoutExporter: public QObject +class TestQgsLayoutExporter: public QgsTest { Q_OBJECT + public: + TestQgsLayoutExporter() + : QgsTest( QStringLiteral( "Layout Exporter Tests" ) ) {} + private slots: - void initTestCase();// will be called before the first testfunction is executed. - void cleanupTestCase();// will be called after the last testfunction was executed. - void init();// will be called before each testfunction is executed. - void cleanup();// will be called after every testfunction. + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); void testHandleLayeredExport(); }; @@ -47,6 +51,7 @@ void TestQgsLayoutExporter::initTestCase() void TestQgsLayoutExporter::cleanupTestCase() { + QgsApplication::exitQgis(); } void TestQgsLayoutExporter::init() diff --git a/tests/src/core/testqgslayouthtml.cpp b/tests/src/core/testqgslayouthtml.cpp index 3a3ade1ebe9d..1ba38cc90b26 100644 --- a/tests/src/core/testqgslayouthtml.cpp +++ b/tests/src/core/testqgslayouthtml.cpp @@ -18,7 +18,6 @@ #include "qgsapplication.h" #include "qgslayoutitemhtml.h" #include "qgslayoutframe.h" -#include "qgsmultirenderchecker.h" #include "qgsfontutils.h" #include "qgsvectorlayer.h" #include "qgsrelationmanager.h" @@ -35,7 +34,7 @@ class TestQgsLayoutHtml : public QgsTest Q_OBJECT public: - TestQgsLayoutHtml() : QgsTest( QStringLiteral( "Layout HTML Tests" ) ) {} + TestQgsLayoutHtml() : QgsTest( QStringLiteral( "Layout HTML Tests" ), QStringLiteral( "composer_html" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -80,10 +79,7 @@ void TestQgsLayoutHtml::sourceMode() htmlItem->setHtml( QStringLiteral( "
" ) ); htmlItem->loadHtml(); - QgsLayoutChecker checker( QStringLiteral( "composerhtml_manual" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - const bool result = checker.testLayout( mReport, 0, 100 ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_manual" ), &l, 0, 100 ) ); } void TestQgsLayoutHtml::userStylesheets() @@ -103,10 +99,7 @@ void TestQgsLayoutHtml::userStylesheets() //setting user stylesheet enabled automatically loads html htmlItem->setUserStylesheetEnabled( true ); - QgsLayoutChecker checker( QStringLiteral( "composerhtml_userstylesheet" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - const bool result = checker.testLayout( mReport, 0, 100 ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_userstylesheet" ), &l, 0, 100 ) ); } void TestQgsLayoutHtml::evalExpressions() @@ -124,10 +117,7 @@ void TestQgsLayoutHtml::evalExpressions() htmlItem->loadHtml(); - QgsLayoutChecker checker( QStringLiteral( "composerhtml_expressions_enabled" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_expressions_enabled" ), &l ) ); } void TestQgsLayoutHtml::evalExpressionsOff() @@ -143,10 +133,7 @@ void TestQgsLayoutHtml::evalExpressionsOff() htmlItem->setHtml( QStringLiteral( "
" ) ); htmlItem->loadHtml(); - QgsLayoutChecker checker( QStringLiteral( "composerhtml_expressions_disabled" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_expressions_disabled" ), &l ) ); } void TestQgsLayoutHtml::table() @@ -159,10 +146,7 @@ void TestQgsLayoutHtml::table() htmlItem->addFrame( htmlFrame ); htmlItem->setUrl( QUrl( QStringLiteral( "file:///%1/test_html.html" ).arg( TEST_DATA_DIR ) ) ); - QgsLayoutChecker checker( QStringLiteral( "composerhtml_table" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_table" ), &l ) ); } void TestQgsLayoutHtml::tableMultiFrame() @@ -179,16 +163,10 @@ void TestQgsLayoutHtml::tableMultiFrame() //page1 htmlItem->setUrl( QUrl( QStringLiteral( "file:///%1/test_html.html" ).arg( TEST_DATA_DIR ) ) ); htmlItem->frame( 0 )->setFrameEnabled( true ); - QgsLayoutChecker checker1( QStringLiteral( "composerhtml_multiframe1" ), &l ); - checker1.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - bool result = checker1.testLayout( mReport ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_multiframe1" ), &l ) ); //page2 - QgsLayoutChecker checker2( QStringLiteral( "composerhtml_multiframe2" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - result = checker2.testLayout( mReport, 1 ) && result; - - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_multiframe2" ), &l, 1 ) ); } void TestQgsLayoutHtml::htmlMultiFrameSmartBreak() @@ -205,16 +183,10 @@ void TestQgsLayoutHtml::htmlMultiFrameSmartBreak() //page1 htmlItem->setUrl( QUrl( QStringLiteral( "file:///%1/test_html.html" ).arg( TEST_DATA_DIR ) ) ); htmlItem->frame( 0 )->setFrameEnabled( true ); - QgsLayoutChecker checker1( QStringLiteral( "composerhtml_smartbreaks1" ), &l ); - checker1.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - bool result = checker1.testLayout( mReport, 0, 200 ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_smartbreaks1" ), &l, 0, 200 ) ); //page2 - QgsLayoutChecker checker2( QStringLiteral( "composerhtml_smartbreaks2" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - result = checker2.testLayout( mReport, 1, 200 ) && result; - - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_smartbreaks2" ), &l, 1, 200 ) ); } void TestQgsLayoutHtml::javascriptSetFeature() @@ -285,10 +257,7 @@ void TestQgsLayoutHtml::javascriptSetFeature() htmlItem->loadHtml(); - QgsLayoutChecker checker( QStringLiteral( "composerhtml_setfeature" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_html" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerhtml_setfeature" ), &l ) ); QgsProject::instance()->removeMapLayers( QList() << childLayer << parentLayer ); } diff --git a/tests/src/core/testqgslayoutitem.cpp b/tests/src/core/testqgslayoutitem.cpp index 4817c797b2a8..4d664bea0fde 100644 --- a/tests/src/core/testqgslayoutitem.cpp +++ b/tests/src/core/testqgslayoutitem.cpp @@ -18,11 +18,9 @@ #include "qgslayoutitem.h" #include "qgslayoutitemregistry.h" #include "qgslayout.h" -#include "qgsmultirenderchecker.h" #include "qgstest.h" #include "qgsproject.h" #include "qgsreadwritecontext.h" -#include "qgslayoutitemundocommand.h" #include "qgslayoutitemmap.h" #include "qgslayoutitemlabel.h" #include "qgslayoutitemshape.h" @@ -139,6 +137,7 @@ class TestQgsLayoutItem: public QgsTest TestQgsLayoutItem() : QgsTest( QStringLiteral( "Layout Item Tests" ) ) {} private slots: + void cleanupTestCase(); void creation(); //test creation of QgsLayoutItem void uuid(); void id(); @@ -179,12 +178,15 @@ class TestQgsLayoutItem: public QgsTest private: - bool renderCheck( QString testName, QImage &image, int mismatchCount ); - std::unique_ptr< QgsLayoutItem > createCopyViaXml( QgsLayout *layout, QgsLayoutItem *original ); }; +void TestQgsLayoutItem::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + void TestQgsLayoutItem::creation() { QgsProject p; @@ -331,8 +333,8 @@ void TestQgsLayoutItem::debugRect() l.render( &painter ); painter.end(); - const bool result = renderCheck( QStringLiteral( "layoutitem_debugrect" ), image, 0 ); - QVERIFY( result ); + mControlPathPrefix = QStringLiteral( "layouts" ); + QVERIFY( imageCheck( QStringLiteral( "layoutitem_debugrect" ), QStringLiteral( "layoutitem_debugrect" ), image, QString(), 0 ) ); } void TestQgsLayoutItem::draw() @@ -350,22 +352,8 @@ void TestQgsLayoutItem::draw() QPainter painter( &image ); l.render( &painter ); painter.end(); - const bool result = renderCheck( QStringLiteral( "layoutitem_draw" ), image, 0 ); - QVERIFY( result ); -} - -bool TestQgsLayoutItem::renderCheck( QString testName, QImage &image, int mismatchCount ) -{ - const QString myTmpDir = QDir::tempPath() + QDir::separator(); - const QString myFileName = myTmpDir + testName + ".png"; - image.save( myFileName, "PNG" ); - QgsRenderChecker myChecker; - myChecker.setControlPathPrefix( QStringLiteral( "layouts" ) ); - myChecker.setControlName( "expected_" + testName ); - myChecker.setRenderedImage( myFileName ); - const bool myResultFlag = myChecker.compareImages( testName, mismatchCount ); - mReport += myChecker.report(); - return myResultFlag; + mControlPathPrefix = QStringLiteral( "layouts" ); + QVERIFY( imageCheck( QStringLiteral( "layoutitem_draw" ), QStringLiteral( "layoutitem_draw" ), image, QString(), 0 ) ); } void TestQgsLayoutItem::positionWithUnits() @@ -1425,19 +1413,19 @@ void TestQgsLayoutItem::variables() { QgsLayout l( QgsProject::instance() ); - QgsLayoutItemMap *map = new QgsLayoutItemMap( &l ); - std::unique_ptr< QgsExpressionContextScope > scope( QgsExpressionContextUtils::layoutItemScope( map ) ); + std::unique_ptr< QgsLayoutItemMap > map = std::make_unique< QgsLayoutItemMap >( &l ); + std::unique_ptr< QgsExpressionContextScope > scope( QgsExpressionContextUtils::layoutItemScope( map.get() ) ); const int before = scope->variableCount(); - QgsExpressionContextUtils::setLayoutItemVariable( map, QStringLiteral( "var" ), 5 ); - scope.reset( QgsExpressionContextUtils::layoutItemScope( map ) ); + QgsExpressionContextUtils::setLayoutItemVariable( map.get(), QStringLiteral( "var" ), 5 ); + scope.reset( QgsExpressionContextUtils::layoutItemScope( map.get() ) ); QCOMPARE( scope->variableCount(), before + 1 ); QCOMPARE( scope->variable( QStringLiteral( "var" ) ).toInt(), 5 ); QVariantMap vars; vars.insert( QStringLiteral( "var2" ), 7 ); - QgsExpressionContextUtils::setLayoutItemVariables( map, vars ); - scope.reset( QgsExpressionContextUtils::layoutItemScope( map ) ); + QgsExpressionContextUtils::setLayoutItemVariables( map.get(), vars ); + scope.reset( QgsExpressionContextUtils::layoutItemScope( map.get() ) ); QCOMPARE( scope->variableCount(), before + 1 ); QVERIFY( !scope->hasVariable( QStringLiteral( "var" ) ) ); QCOMPARE( scope->variable( QStringLiteral( "var2" ) ).toInt(), 7 ); @@ -1670,9 +1658,8 @@ void TestQgsLayoutItem::rotation() l.render( &painter ); painter.end(); - const bool result = renderCheck( QStringLiteral( "layoutitem_rotation" ), image, 0 ); + QVERIFY( imageCheck( QStringLiteral( "layoutitem_rotation" ), QStringLiteral( "layoutitem_rotation" ), image, QString(), 0 ) ); delete item; - QVERIFY( result ); } //TODO rotation tests: @@ -1988,9 +1975,8 @@ void TestQgsLayoutItem::blendMode() mComposerRect2->setBlendMode( QPainter::CompositionMode_Multiply ); - QgsLayoutChecker checker( QStringLiteral( "composereffects_blend" ), &l2 ); - checker.setControlPathPrefix( QStringLiteral( "composer_effects" ) ); - QVERIFY( checker.testLayout( mReport ) ); + mControlPathPrefix = QStringLiteral( "composer_effects" ); + QVERIFY( layoutCheck( QStringLiteral( "composereffects_blend" ), &l2 ) ); } void TestQgsLayoutItem::opacity() @@ -2008,7 +1994,7 @@ void TestQgsLayoutItem::opacity() QgsLayoutItemShape *item = new QgsLayoutItemShape( &l ); item->setShapeType( QgsLayoutItemShape::Rectangle ); item->attemptSetSceneRect( QRectF( 50, 50, 150, 100 ) ); - item->setSymbol( fillSymbol->clone() ); + item->setSymbol( fillSymbol ); l.addLayoutItem( item ); @@ -2018,18 +2004,15 @@ void TestQgsLayoutItem::opacity() // we handle opacity ourselves, so QGraphicsItem opacity should never be set QCOMPARE( item->opacity(), 1.0 ); - QgsLayoutChecker checker( QStringLiteral( "composereffects_transparency75" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_effects" ) ); - QVERIFY( checker.testLayout( mReport ) ); + mControlPathPrefix = QStringLiteral( "composer_effects" ); + QVERIFY( layoutCheck( QStringLiteral( "composereffects_transparency75" ), &l ) ); item->dataDefinedProperties().setProperty( QgsLayoutObject::Opacity, QgsProperty::fromExpression( "35" ) ); item->refreshDataDefinedProperty(); QCOMPARE( item->itemOpacity(), 0.75 ); // should not change QCOMPARE( item->opacity(), 1.0 ); - checker = QgsLayoutChecker( QStringLiteral( "composereffects_transparency35" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_effects" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composereffects_transparency35" ), &l ) ); // with background and frame l.removeLayoutItem( item ); @@ -2042,16 +2025,14 @@ void TestQgsLayoutItem::opacity() labelItem->setFrameEnabled( true ); labelItem->setFrameStrokeColor( QColor( 40, 30, 20 ) ); labelItem->setItemOpacity( 0.5 ); - checker = QgsLayoutChecker( QStringLiteral( "composereffects_transparency_bgframe" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_effects" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composereffects_transparency_bgframe" ), &l ) ); QgsLayout l2( QgsProject::instance() ); l2.initializeDefaults(); QgsLayoutItemShape *mComposerRect1 = new QgsLayoutItemShape( &l2 ); mComposerRect1->attemptSetSceneRect( QRectF( 20, 20, 150, 100 ) ); mComposerRect1->setShapeType( QgsLayoutItemShape::Rectangle ); - mComposerRect1->setSymbol( fillSymbol->clone() ); + mComposerRect1->setSymbol( fillSymbol ); delete fillSymbol; l2.addLayoutItem( mComposerRect1 ); @@ -2069,9 +2050,7 @@ void TestQgsLayoutItem::opacity() mComposerRect2->setItemOpacity( 0.5 ); - checker = QgsLayoutChecker( QStringLiteral( "composereffects_transparency" ), &l2 ); - checker.setControlPathPrefix( QStringLiteral( "composer_effects" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composereffects_transparency" ), &l2 ) ); } void TestQgsLayoutItem::excludeFromExports() @@ -2107,10 +2086,8 @@ void TestQgsLayoutItem::excludeFromExports() item->attemptResize( QgsLayoutSize( 200, 200 ) ); l.updateBounds(); - QgsLayoutChecker checker( QStringLiteral( "layoutitem_excluded" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layouts" ) ); - checker.setSize( QSize( 400, 400 ) ); - QVERIFY( checker.testLayout( mReport ) ); + mControlPathPrefix = QStringLiteral( "layouts" ); + QVERIFY( layoutCheck( QStringLiteral( "layoutitem_excluded" ), &l, 0, 0, QSize( 400, 400 ) ) ); } std::unique_ptr TestQgsLayoutItem::createCopyViaXml( QgsLayout *layout, QgsLayoutItem *original ) diff --git a/tests/src/core/testqgslayoutitemgroup.cpp b/tests/src/core/testqgslayoutitemgroup.cpp index 2d2906a4794e..ee4ba0d53576 100644 --- a/tests/src/core/testqgslayoutitemgroup.cpp +++ b/tests/src/core/testqgslayoutitemgroup.cpp @@ -18,23 +18,21 @@ #include "qgslayoutitemgroup.h" #include "qgslayout.h" #include "qgslayoutitemshape.h" -#include "qgsmultirenderchecker.h" #include "qgsapplication.h" #include "qgslogger.h" #include "qgsproject.h" -#include "qgsfillsymbollayer.h" #include "qgslayoutundostack.h" #include #include #include "qgstest.h" -class TestQgsLayoutItemGroup : public QObject +class TestQgsLayoutItemGroup : public QgsTest { Q_OBJECT public: - TestQgsLayoutItemGroup() = default; + TestQgsLayoutItemGroup() : QgsTest( QStringLiteral( "Layout Group Item" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. diff --git a/tests/src/core/testqgslayoutlabel.cpp b/tests/src/core/testqgslayoutlabel.cpp index 7df029e424be..e0e9ad35626a 100644 --- a/tests/src/core/testqgslayoutlabel.cpp +++ b/tests/src/core/testqgslayoutlabel.cpp @@ -38,7 +38,7 @@ class TestQgsLayoutLabel : public QgsTest Q_OBJECT public: - TestQgsLayoutLabel() : QgsTest( QStringLiteral( "Layout Label Tests" ) ) {} + TestQgsLayoutLabel() : QgsTest( QStringLiteral( "Layout Label Tests" ), QStringLiteral( "composer_label" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -284,9 +284,7 @@ void TestQgsLayoutLabel::render() label->attemptMove( QgsLayoutPoint( 70, 70 ) ); label->adjustSizeToText(); - QgsLayoutChecker checker( QStringLiteral( "composerlabel_render" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_label" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerlabel_render" ), &l ) ); } void TestQgsLayoutLabel::renderAsHtml() @@ -312,9 +310,7 @@ void TestQgsLayoutLabel::renderAsHtml() label->setMode( QgsLayoutItemLabel::ModeHtml ); label->update(); - QgsLayoutChecker checker( QStringLiteral( "composerlabel_renderhtml" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_label" ) ); - QVERIFY( checker.testLayout( mReport, 0, 10 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerlabel_renderhtml" ), &l, 0, 10 ) ); } #ifdef WITH_QTWEBKIT @@ -329,9 +325,7 @@ void TestQgsLayoutLabel::convertToHtml() QgsLayoutMultiFrame *html = layout->multiFrames().at( 0 ); QVERIFY( html ); - QgsLayoutChecker checker( QStringLiteral( "composerlabel_converttohtml" ), layout ); - checker.setControlPathPrefix( QStringLiteral( "composer_label" ) ); - QVERIFY( checker.testLayout( mReport, 0, 10 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerlabel_converttohtml" ), layout, 0, 10 ) ); } void TestQgsLayoutLabel::renderAsHtmlRelative() @@ -358,9 +352,7 @@ void TestQgsLayoutLabel::renderAsHtmlRelative() label->setMode( QgsLayoutItemLabel::ModeHtml ); label->update(); - QgsLayoutChecker checker( QStringLiteral( "composerlabel_renderhtmlrelative" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_label" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerlabel_renderhtmlrelative" ), &l ) ); } #endif @@ -385,9 +377,8 @@ void TestQgsLayoutLabel::labelRotation() label->setBackgroundEnabled( true ); label->setItemRotation( 135 ); - QgsLayoutChecker checker( QStringLiteral( "layoutrotation_label" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_items" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + mControlPathPrefix = QStringLiteral( "composer_items" ); + QVERIFY( layoutCheck( QStringLiteral( "layoutrotation_label" ), &l ) ); } QGSTEST_MAIN( TestQgsLayoutLabel ) diff --git a/tests/src/core/testqgslayoutmanualtable.cpp b/tests/src/core/testqgslayoutmanualtable.cpp index 5c30fac7cc90..860b01dc3272 100644 --- a/tests/src/core/testqgslayoutmanualtable.cpp +++ b/tests/src/core/testqgslayoutmanualtable.cpp @@ -24,7 +24,6 @@ #include "qgsreadwritecontext.h" #include "qgsprintlayout.h" #include "qgscurrencynumericformat.h" -#include "qgsmultirenderchecker.h" #include "qgsfontutils.h" #include @@ -35,7 +34,7 @@ class TestQgsLayoutManualTable : public QgsTest Q_OBJECT public: - TestQgsLayoutManualTable() : QgsTest( QStringLiteral( "Layout Manual Table Tests" ) ) {} + TestQgsLayoutManualTable() : QgsTest( QStringLiteral( "Layout Manual Table Tests" ), QStringLiteral( "layout_manual_table" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -386,10 +385,7 @@ void TestQgsLayoutManualTable::rowHeight() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "A" ) ) << QgsTableCell( QStringLiteral( "B" ) ) << QgsTableCell( QStringLiteral( "C" ) ) ) ); table->setRowHeights( QList< double >() << 0 << 40.0 ); - QgsLayoutChecker checker( QStringLiteral( "manualtable_rowheight" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_manual_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "manualtable_rowheight" ), &l ) ); } void TestQgsLayoutManualTable::columnWidth() @@ -414,10 +410,7 @@ void TestQgsLayoutManualTable::columnWidth() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "A" ) ) << QgsTableCell( QStringLiteral( "B" ) ) << QgsTableCell( QStringLiteral( "C" ) ) ) ); table->setColumnWidths( QList< double >() << 0 << 10.0 << 30.0 ); - QgsLayoutChecker checker( QStringLiteral( "manualtable_columnwidth" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_manual_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "manualtable_columnwidth" ), &l ) ); } void TestQgsLayoutManualTable::headers() @@ -448,10 +441,7 @@ void TestQgsLayoutManualTable::headers() << QgsLayoutTableColumn( QStringLiteral( "h2" ) ) << QgsLayoutTableColumn( QStringLiteral( "header 3" ) ) ); - QgsLayoutChecker checker( QStringLiteral( "manualtable_headers" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_manual_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "manualtable_headers" ), &l ) ); } void TestQgsLayoutManualTable::cellTextFormat() @@ -500,10 +490,7 @@ void TestQgsLayoutManualTable::cellTextFormat() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "A" ) ) << c5 << QgsTableCell( QStringLiteral( "C" ) ) ) ); table->setColumnWidths( QList< double >() << 0 << 0.0 << 30.0 ); - QgsLayoutChecker checker( QStringLiteral( "manualtable_textformat" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_manual_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "manualtable_textformat" ), &l ) ); } void TestQgsLayoutManualTable::cellTextAlignment() @@ -540,10 +527,7 @@ void TestQgsLayoutManualTable::cellTextAlignment() << ( QgsTableRow() << QgsTableCell( QStringLiteral( "A" ) ) << c5 << QgsTableCell( QStringLiteral( "C" ) ) ) ); table->setColumnWidths( QList< double >() << 0 << 0.0 << 30.0 ); - QgsLayoutChecker checker( QStringLiteral( "manualtable_textalign" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_manual_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "manualtable_textalign" ), &l ) ); } QGSTEST_MAIN( TestQgsLayoutManualTable ) diff --git a/tests/src/core/testqgslayoutmap.cpp b/tests/src/core/testqgslayoutmap.cpp index 0a6d4f4372e5..67b7a0eefca6 100644 --- a/tests/src/core/testqgslayoutmap.cpp +++ b/tests/src/core/testqgslayoutmap.cpp @@ -17,7 +17,6 @@ #include "qgsapplication.h" #include "qgslayout.h" -#include "qgsmultirenderchecker.h" #include "qgslayoutitemmap.h" #include "qgsmultibandcolorrenderer.h" #include "qgsrasterlayer.h" @@ -48,7 +47,7 @@ class TestQgsLayoutMap : public QgsTest Q_OBJECT public: - TestQgsLayoutMap() : QgsTest( QStringLiteral( "Layout Map Tests" ) ) {} + TestQgsLayoutMap() : QgsTest( QStringLiteral( "Layout Map Tests" ), QStringLiteral( "composer_map" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -152,10 +151,8 @@ void TestQgsLayoutMap::id() QgsLayoutItemMap *map3 = new QgsLayoutItemMap( &l ); QCOMPARE( map3->displayName(), QStringLiteral( "Map 1" ) ); l.addLayoutItem( map3 ); - } - void TestQgsLayoutMap::render() { QgsLayout l( QgsProject::instance() ); @@ -167,10 +164,7 @@ void TestQgsLayoutMap::render() l.addLayoutItem( map ); map->setExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) ); - QgsLayoutChecker checker( QStringLiteral( "composermap_render" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_map" ) ); - - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composermap_render" ), &l ) ); } void TestQgsLayoutMap::uniqueId() @@ -384,9 +378,7 @@ void TestQgsLayoutMap::dataDefinedLayers() QStringLiteral( "'%1|%2'" ).arg( mPolysLayer->name(), mPointsLayer->name() ) ) ); map->setExtent( QgsRectangle( -110.0, 25.0, -90, 40.0 ) ); - QgsLayoutChecker checker( QStringLiteral( "composermap_ddlayers" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_map" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composermap_ddlayers" ), &l ) ); } void TestQgsLayoutMap::dataDefinedStyles() @@ -448,9 +440,7 @@ void TestQgsLayoutMap::dataDefinedStyles() map->dataDefinedProperties().setProperty( QgsLayoutObject::MapStylePreset, QgsProperty::fromExpression( QStringLiteral( "'test preset'" ) ) ); map->setExtent( QgsRectangle( -110.0, 25.0, -90, 40.0 ) ); - QgsLayoutChecker checker( QStringLiteral( "composermap_ddstyles" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_map" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composermap_ddstyles" ), &l ) ); } void TestQgsLayoutMap::dataDefinedCrs() @@ -554,16 +544,14 @@ void TestQgsLayoutMap::rasterized() QVERIFY( map->containsAdvancedEffects() ); - QgsLayoutChecker checker( QStringLiteral( "layoutmap_rasterized" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_map" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutmap_rasterized" ), &l ) ); // try rendering again, without requiring rasterization, for comparison // (we can use the same test image, because CompositionMode_Darken doesn't actually have any noticeable // rendering differences for the black grid!) grid->setBlendMode( QPainter::CompositionMode_SourceOver ); QVERIFY( !map->containsAdvancedEffects() ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutmap_rasterized" ), &l ) ); } void TestQgsLayoutMap::layersToRender() @@ -610,9 +598,9 @@ void TestQgsLayoutMap::mapRotation() map->setMapRotation( 90 ); map->setLayers( QList() << layer ); - QgsLayoutChecker checker( QStringLiteral( "composerrotation_maprotation" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_items" ) ); - QVERIFY( checker.testLayout( mReport, 0, 200 ) ); + mControlPathPrefix = QStringLiteral( "composer_items" ); + QVERIFY( layoutCheck( QStringLiteral( "composerrotation_maprotation" ), &l, 0, 200 ) ); + mControlPathPrefix = QStringLiteral( "composer_map" ); // test that rotation correctly applies to restored items QDomDocument doc; @@ -646,9 +634,9 @@ void TestQgsLayoutMap::mapItemRotation() map->setItemRotation( 90 ); map->setLayers( QList() << layer ); - QgsLayoutChecker checker( QStringLiteral( "composerrotation_mapitemrotation" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_items" ) ); - QVERIFY( checker.testLayout( mReport, 0, 200 ) ); + mControlPathPrefix = QStringLiteral( "composer_items" ); + QVERIFY( layoutCheck( QStringLiteral( "composerrotation_mapitemrotation" ), &l, 0, 200 ) ); + mControlPathPrefix = QStringLiteral( "composer_map" ); } void TestQgsLayoutMap::expressionContext() @@ -1911,7 +1899,7 @@ void TestQgsLayoutMap::testLayeredExportLabelsByLayer() void TestQgsLayoutMap::testTemporal() { QgsLayout l( QgsProject::instance( ) ); - QgsLayoutItemMap *map = new QgsLayoutItemMap( &l ); + std::unique_ptr< QgsLayoutItemMap > map = std::make_unique< QgsLayoutItemMap >( &l ); const QDateTime begin( QDate( 2020, 01, 01 ), QTime( 10, 0, 0 ), Qt::UTC ); const QDateTime end = begin.addSecs( 3600 ); diff --git a/tests/src/core/testqgslayoutmapgrid.cpp b/tests/src/core/testqgslayoutmapgrid.cpp index 5ff13bc988f7..388123ee32db 100644 --- a/tests/src/core/testqgslayoutmapgrid.cpp +++ b/tests/src/core/testqgslayoutmapgrid.cpp @@ -17,7 +17,6 @@ #include "qgsapplication.h" #include "qgslayout.h" -#include "qgsmultirenderchecker.h" #include "qgslayoutitemmap.h" #include "qgslayoutitemmapgrid.h" #include "qgsmarkersymbollayer.h" @@ -33,7 +32,7 @@ class TestQgsLayoutMapGrid : public QgsTest public: - TestQgsLayoutMapGrid() : QgsTest( QStringLiteral( "Layout Map Grid Tests" ) ) {} + TestQgsLayoutMapGrid() : QgsTest( QStringLiteral( "Layout Map Grid Tests" ), QStringLiteral( "composer_mapgrid" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -117,10 +116,7 @@ void TestQgsLayoutMapGrid::grid() map->grid()->setAnnotationDirection( QgsLayoutItemMapGrid::Horizontal, QgsLayoutItemMapGrid::Bottom ); map->grid()->setBlendMode( QPainter::CompositionMode_Overlay ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_grid" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_grid" ), &l ); map->grid()->setEnabled( false ); map->grid()->setAnnotationEnabled( false ); QVERIFY( testResult ); @@ -158,10 +154,8 @@ void TestQgsLayoutMapGrid::reprojected() map->grid()->setFrameWidth( 10 ); map->setFrameEnabled( false ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_gridreprojected" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_gridreprojected" ), &l ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); map->grid()->setEnabled( false ); map->grid()->setCrs( crs ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -197,10 +191,7 @@ void TestQgsLayoutMapGrid::crossGrid() map->grid()->setGridLineColor( QColor( 0, 255, 0 ) ); map->grid()->setBlendMode( QPainter::CompositionMode_SourceOver ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_crossgrid" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_crossgrid" ), &l ); map->grid()->setStyle( QgsLayoutItemMapGrid::Solid ); map->grid()->setEnabled( false ); map->grid()->setAnnotationEnabled( false ); @@ -234,10 +225,7 @@ void TestQgsLayoutMapGrid::markerGrid() map->grid()->setAnnotationEnabled( false ); map->grid()->setBlendMode( QPainter::CompositionMode_SourceOver ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_markergrid" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_markergrid" ), &l ); map->grid()->setStyle( QgsLayoutItemMapGrid::Solid ); map->grid()->setEnabled( false ); map->grid()->setAnnotationEnabled( false ); @@ -274,10 +262,7 @@ void TestQgsLayoutMapGrid::frameOnly() map->grid()->setFramePenSize( 0.5 ); map->grid()->setBlendMode( QPainter::CompositionMode_SourceOver ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_gridframeonly" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_gridframeonly" ), &l ); map->grid()->setStyle( QgsLayoutItemMapGrid::Solid ); map->grid()->setEnabled( false ); map->grid()->setAnnotationEnabled( false ); @@ -319,10 +304,7 @@ void TestQgsLayoutMapGrid::zebraStyle() map->grid()->setEnabled( true ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_zebrastyle" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_zebrastyle" ), &l ); QVERIFY( testResult ); } @@ -365,23 +347,17 @@ void TestQgsLayoutMapGrid::zebraStyleSides() map->grid()->setFrameSideFlag( QgsLayoutItemMapGrid::FrameBottom, false ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_zebrastyle_left" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_zebrastyle_left" ), &l ); QVERIFY( testResult ); map->grid()->setFrameSideFlag( QgsLayoutItemMapGrid::FrameTop, true ); map->updateBoundingRect(); - QgsLayoutChecker checker2( QStringLiteral( "composermap_zebrastyle_lefttop" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult2 = checker2.testLayout( mReport, 0, 0 ); + const bool testResult2 = layoutCheck( QStringLiteral( "composermap_zebrastyle_lefttop" ), &l ); QVERIFY( testResult2 ); map->grid()->setFrameSideFlag( QgsLayoutItemMapGrid::FrameRight, true ); map->updateBoundingRect(); - QgsLayoutChecker checker3( QStringLiteral( "composermap_zebrastyle_lefttopright" ), &l ); - checker3.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult3 = checker3.testLayout( mReport, 0, 0 ); + const bool testResult3 = layoutCheck( QStringLiteral( "composermap_zebrastyle_lefttopright" ), &l ); QVERIFY( testResult3 ); map->grid()->setFrameSideFlag( QgsLayoutItemMapGrid::FrameBottom, true ); @@ -424,10 +400,7 @@ void TestQgsLayoutMapGrid::zebraStyleMargin() map->grid()->setEnabled( true ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_marginzebrastyle" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_marginzebrastyle" ), &l ); QVERIFY( testResult ); } @@ -466,10 +439,7 @@ void TestQgsLayoutMapGrid::zebraStyleNautical() map->grid()->setEnabled( true ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_zebranauticalstyle" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_zebranauticalstyle" ), &l ); QVERIFY( testResult ); } @@ -514,9 +484,7 @@ void TestQgsLayoutMapGrid::frameDivisions() map->grid()->setFrameSideFlag( QgsLayoutItemMapGrid::FrameBottom, true ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_rotatedframe" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - bool testResult = checker.testLayout( mReport, 0, 0 ); + bool testResult = layoutCheck( QStringLiteral( "composermap_rotatedframe" ), &l ); QVERIFY( testResult ); map->grid()->setFrameDivisions( QgsLayoutItemMapGrid::LatitudeOnly, QgsLayoutItemMapGrid::Left ); @@ -525,9 +493,7 @@ void TestQgsLayoutMapGrid::frameDivisions() map->grid()->setFrameDivisions( QgsLayoutItemMapGrid::LongitudeOnly, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker2( QStringLiteral( "composermap_framedivisions" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - testResult = checker2.testLayout( mReport, 0, 0 ); + testResult = layoutCheck( QStringLiteral( "composermap_framedivisions" ), &l ); QVERIFY( testResult ); map->grid()->setFrameDivisions( QgsLayoutItemMapGrid::ShowAll, QgsLayoutItemMapGrid::Left ); @@ -575,9 +541,7 @@ void TestQgsLayoutMapGrid::annotationFilter() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_rotatedannotations" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - bool testResult = checker.testLayout( mReport, 0, 0 ); + bool testResult = layoutCheck( QStringLiteral( "composermap_rotatedannotations" ), &l ); QVERIFY( testResult ); map->grid()->setAnnotationDisplay( QgsLayoutItemMapGrid::HideAll, QgsLayoutItemMapGrid::Left ); @@ -586,9 +550,7 @@ void TestQgsLayoutMapGrid::annotationFilter() map->grid()->setAnnotationDisplay( QgsLayoutItemMapGrid::LongitudeOnly, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker2( QStringLiteral( "composermap_filteredannotations" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - testResult = checker2.testLayout( mReport, 0, 0 ); + testResult = layoutCheck( QStringLiteral( "composermap_filteredannotations" ), &l ); QVERIFY( testResult ); map->grid()->setAnnotationEnabled( false ); @@ -629,9 +591,7 @@ void TestQgsLayoutMapGrid::interiorTicks() map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_interiorticks" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_interiorticks" ), &l ); QVERIFY( testResult ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -668,9 +628,7 @@ void TestQgsLayoutMapGrid::interiorTicksMargin() map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_margininteriorticks" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_margininteriorticks" ), &l ); QVERIFY( testResult ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -711,9 +669,7 @@ void TestQgsLayoutMapGrid::interiorTicksAnnotated() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_interiorticks_annotated" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_interiorticks_annotated" ), &l ); QVERIFY( testResult ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Left ); @@ -722,9 +678,7 @@ void TestQgsLayoutMapGrid::interiorTicksAnnotated() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker2( QStringLiteral( "composermap_interiorticks_annotated2" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult2 = checker2.testLayout( mReport, 0, 0 ); + const bool testResult2 = layoutCheck( QStringLiteral( "composermap_interiorticks_annotated2" ), &l ); QVERIFY( testResult2 ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -761,9 +715,7 @@ void TestQgsLayoutMapGrid::exteriorTicks() map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_exteriorticks" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_exteriorticks" ), &l ); QVERIFY( testResult ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -800,9 +752,7 @@ void TestQgsLayoutMapGrid::exteriorTicksMargin() map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_marginexteriorticks" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_marginexteriorticks" ), &l ); QVERIFY( testResult ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -843,9 +793,7 @@ void TestQgsLayoutMapGrid::exteriorTicksAnnotated() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_exteriorticks_annotated" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_exteriorticks_annotated" ), &l ); QVERIFY( testResult ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Left ); @@ -854,9 +802,7 @@ void TestQgsLayoutMapGrid::exteriorTicksAnnotated() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker2( QStringLiteral( "composermap_exteriorticks_annotated2" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult2 = checker2.testLayout( mReport, 0, 0 ); + const bool testResult2 = layoutCheck( QStringLiteral( "composermap_exteriorticks_annotated2" ), &l ); QVERIFY( testResult2 ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -893,9 +839,7 @@ void TestQgsLayoutMapGrid::interiorExteriorTicks() map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_interiorexteriorticks" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_interiorexteriorticks" ), &l ); QVERIFY( testResult ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -932,9 +876,7 @@ void TestQgsLayoutMapGrid::interiorExteriorTicksMargin() map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_margininteriorexteriorticks" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_margininteriorexteriorticks" ), &l ); QVERIFY( testResult ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -975,9 +917,7 @@ void TestQgsLayoutMapGrid::interiorExteriorTicksAnnotated() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_interiorexteriorticks_annotated" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_interiorexteriorticks_annotated" ), &l ); QVERIFY( testResult ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Left ); @@ -986,9 +926,7 @@ void TestQgsLayoutMapGrid::interiorExteriorTicksAnnotated() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker2( QStringLiteral( "composermap_interiorexteriorticks_annotated2" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult2 = checker2.testLayout( mReport, 0, 0 ); + const bool testResult2 = layoutCheck( QStringLiteral( "composermap_interiorexteriorticks_annotated2" ), &l ); QVERIFY( testResult2 ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -1025,9 +963,7 @@ void TestQgsLayoutMapGrid::lineBorder() map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_lineborder" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_lineborder" ), &l ); QVERIFY( testResult ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -1064,9 +1000,7 @@ void TestQgsLayoutMapGrid::lineBorderMargin() map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_marginlineborder" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_marginlineborder" ), &l ); QVERIFY( testResult ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -1103,9 +1037,7 @@ void TestQgsLayoutMapGrid::lineBorderNautical() map->grid()->setStyle( QgsLayoutItemMapGrid::FrameAnnotationsOnly ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_linebordernautical" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_linebordernautical" ), &l ); QVERIFY( testResult ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -1146,9 +1078,7 @@ void TestQgsLayoutMapGrid::lineBorderAnnotated() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::InsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_lineborder_annotated" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_lineborder_annotated" ), &l ); QVERIFY( testResult ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Left ); @@ -1157,9 +1087,7 @@ void TestQgsLayoutMapGrid::lineBorderAnnotated() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker2( QStringLiteral( "composermap_lineborder_annotated2" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult2 = checker2.testLayout( mReport, 0, 0 ); + const bool testResult2 = layoutCheck( QStringLiteral( "composermap_lineborder_annotated2" ), &l ); QVERIFY( testResult2 ); map->grid()->setFrameStyle( QgsLayoutItemMapGrid::NoFrame ); @@ -1266,9 +1194,7 @@ void TestQgsLayoutMapGrid::descendingAnnotations() map->grid()->setAnnotationDirection( QgsLayoutItemMapGrid::VerticalDescending, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker( QStringLiteral( "composermap_verticaldescending_inside" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_verticaldescending_inside" ), &l ); QVERIFY( testResult ); map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Left ); @@ -1277,9 +1203,7 @@ void TestQgsLayoutMapGrid::descendingAnnotations() map->grid()->setAnnotationPosition( QgsLayoutItemMapGrid::OutsideMapFrame, QgsLayoutItemMapGrid::Bottom ); map->updateBoundingRect(); - QgsLayoutChecker checker2( QStringLiteral( "composermap_verticaldescending_outside" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) ); - const bool testResult2 = checker2.testLayout( mReport, 0, 0 ); + const bool testResult2 = layoutCheck( QStringLiteral( "composermap_verticaldescending_outside" ), &l ); QVERIFY( testResult2 ); map->grid()->setAnnotationEnabled( false ); diff --git a/tests/src/core/testqgslayoutmapoverview.cpp b/tests/src/core/testqgslayoutmapoverview.cpp index 34e9e9791b15..7f516c3b2043 100644 --- a/tests/src/core/testqgslayoutmapoverview.cpp +++ b/tests/src/core/testqgslayoutmapoverview.cpp @@ -17,14 +17,12 @@ #include "qgsapplication.h" #include "qgslayout.h" -#include "qgsmultirenderchecker.h" #include "qgslayoutitemmap.h" #include "qgslayoutitemmapoverview.h" #include "qgsproject.h" #include "qgsmultibandcolorrenderer.h" #include "qgsrasterlayer.h" #include "qgsrasterdataprovider.h" -#include "qgsfontutils.h" #include #include "qgstest.h" @@ -33,7 +31,7 @@ class TestQgsLayoutMapOverview : public QgsTest Q_OBJECT public: - TestQgsLayoutMapOverview() : QgsTest( QStringLiteral( "Layout Map Overview Tests" ) ) {} + TestQgsLayoutMapOverview() : QgsTest( QStringLiteral( "Layout Map Overview Tests" ), QStringLiteral( "composer_mapoverview" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -110,10 +108,7 @@ void TestQgsLayoutMapOverview::overviewMap() //render overviewMap->overview()->setLinkedMap( map ); - QgsLayoutChecker checker( QStringLiteral( "composermap_overview" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_overview" ), &l ); QVERIFY( testResult ); } @@ -136,10 +131,7 @@ void TestQgsLayoutMapOverview::overviewMapRotated() map->setMapRotation( 30 ); overviewMap->setExtent( QgsRectangle( 0, -256, 256, 0 ) ); overviewMap->overview()->setLinkedMap( map ); - QgsLayoutChecker checker( QStringLiteral( "composermap_overview_rotated" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 600 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_overview_rotated" ), &l, 0, 600 ); QVERIFY( testResult ); } @@ -162,10 +154,7 @@ void TestQgsLayoutMapOverview::overviewMapRotated2() overviewMap->setMapRotation( 30 ); overviewMap->setExtent( QgsRectangle( 0, -256, 256, 0 ) ); overviewMap->overview()->setLinkedMap( map ); - QgsLayoutChecker checker( QStringLiteral( "composermap_overview_rotated2" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 600 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_overview_rotated2" ), &l, 0, 600 ); QVERIFY( testResult ); } @@ -189,10 +178,7 @@ void TestQgsLayoutMapOverview::overviewMapBlending() overviewMapBlend->overview()->setLinkedMap( map ); overviewMapBlend->overview()->setBlendMode( QPainter::CompositionMode_Multiply ); - QgsLayoutChecker checker( QStringLiteral( "composermap_overview_blending" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_overview_blending" ), &l ); QVERIFY( testResult ); } @@ -216,10 +202,7 @@ void TestQgsLayoutMapOverview::overviewMapInvert() overviewMapInvert->overview()->setLinkedMap( map ); overviewMapInvert->overview()->setInverted( true ); - QgsLayoutChecker checker( QStringLiteral( "composermap_overview_invert" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_overview_invert" ), &l ); QVERIFY( testResult ); } @@ -243,10 +226,7 @@ void TestQgsLayoutMapOverview::overviewMapCenter() overviewMapCenter->overview()->setLinkedMap( map ); overviewMapCenter->overview()->setCentered( true ); - QgsLayoutChecker checker( QStringLiteral( "composermap_overview_center" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_overview_center" ), &l ); QVERIFY( testResult ); } @@ -273,10 +253,7 @@ void TestQgsLayoutMapOverview::overviewReprojected() overviewMap->setExtent( QgsRectangle( 4712502, -7620278, 10872777, -2531356 ) ); overviewMap->overview()->setLinkedMap( map ); - QgsLayoutChecker checker( QStringLiteral( "composermap_overview_reprojected" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) ); - - const bool testResult = checker.testLayout( mReport, 0, 0 ); + const bool testResult = layoutCheck( QStringLiteral( "composermap_overview_reprojected" ), &l ); QVERIFY( testResult ); } diff --git a/tests/src/core/testqgslayoutmodel.cpp b/tests/src/core/testqgslayoutmodel.cpp index 23104cf92ea3..c0fd30572e1f 100644 --- a/tests/src/core/testqgslayoutmodel.cpp +++ b/tests/src/core/testqgslayoutmodel.cpp @@ -19,22 +19,22 @@ #include "qgslayoutmodel.h" #include "qgslayoutitemmap.h" #include "qgsapplication.h" -#include "qgsmapsettings.h" #include "qgsproject.h" #include "qgslayoutitemlabel.h" #include "qgslayoutitemgroup.h" #include "qgslayoutitemshape.h" #include +#include #include "qgstest.h" #include #include -class TestQgsLayoutModel : public QObject +class TestQgsLayoutModel : public QgsTest { Q_OBJECT public: - TestQgsLayoutModel() = default; + TestQgsLayoutModel(): QgsTest( QStringLiteral( "Layout model test" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -595,22 +595,22 @@ void TestQgsLayoutModel::moveItem() QCOMPARE( layout.itemsModel()->data( layout.itemsModel()->index( 3, 2, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "i1" ) ); QgsLayoutModel *model = layout.itemsModel(); - QMimeData *mimedata = model->mimeData( QModelIndexList() << model->index( 2, 2 ) ); // get i2 - model->dropMimeData( mimedata, Qt::MoveAction, 1, 2, QModelIndex() ); // move i2 at the top + std::unique_ptr< QMimeData > mimedata( model->mimeData( QModelIndexList() << model->index( 2, 2 ) ) ); // get i2 + model->dropMimeData( mimedata.get(), Qt::MoveAction, 1, 2, QModelIndex() ); // move i2 at the top QCOMPARE( layout.itemsModel()->data( layout.itemsModel()->index( 1, 2, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "i2" ) ); QCOMPARE( layout.itemsModel()->data( layout.itemsModel()->index( 2, 2, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "i3" ) ); QCOMPARE( layout.itemsModel()->data( layout.itemsModel()->index( 3, 2, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "i1" ) ); - mimedata = model->mimeData( QModelIndexList() << model->index( 1, 2 ) ); // get i2 - model->dropMimeData( mimedata, Qt::MoveAction, -1, -1, QModelIndex() ); // move i2 at the bottom + mimedata.reset( model->mimeData( QModelIndexList() << model->index( 1, 2 ) ) ); // get i2 + model->dropMimeData( mimedata.get(), Qt::MoveAction, -1, -1, QModelIndex() ); // move i2 at the bottom QCOMPARE( layout.itemsModel()->data( layout.itemsModel()->index( 1, 2, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "i3" ) ); QCOMPARE( layout.itemsModel()->data( layout.itemsModel()->index( 2, 2, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "i1" ) ); QCOMPARE( layout.itemsModel()->data( layout.itemsModel()->index( 3, 2, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "i2" ) ); - mimedata = model->mimeData( QModelIndexList() << model->index( 3, 2 ) ); // get i2 - model->dropMimeData( mimedata, Qt::MoveAction, 2, 2, QModelIndex() ); // move i2 between i3 and i1 + mimedata.reset( model->mimeData( QModelIndexList() << model->index( 3, 2 ) ) ); // get i2 + model->dropMimeData( mimedata.get(), Qt::MoveAction, 2, 2, QModelIndex() ); // move i2 between i3 and i1 QCOMPARE( layout.itemsModel()->data( layout.itemsModel()->index( 1, 2, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "i3" ) ); QCOMPARE( layout.itemsModel()->data( layout.itemsModel()->index( 2, 2, QModelIndex() ), Qt::DisplayRole ).toString(), QStringLiteral( "i2" ) ); diff --git a/tests/src/core/testqgslayoutobject.cpp b/tests/src/core/testqgslayoutobject.cpp index 6aadc6818b75..7a5169c5b760 100644 --- a/tests/src/core/testqgslayoutobject.cpp +++ b/tests/src/core/testqgslayoutobject.cpp @@ -29,6 +29,7 @@ class TestQgsLayoutObject: public QgsTest TestQgsLayoutObject() : QgsTest( QStringLiteral( "Layout Object Tests" ) ) {} private slots: + void cleanupTestCase(); void creation(); //test creation of QgsLayoutObject void layout(); //test fetching layout from QgsLayoutObject @@ -41,6 +42,11 @@ class TestQgsLayoutObject: public QgsTest }; +void TestQgsLayoutObject::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + void TestQgsLayoutObject::creation() { QgsProject p; diff --git a/tests/src/core/testqgslayoutpage.cpp b/tests/src/core/testqgslayoutpage.cpp index ab100683c826..7fd73bc6b5c4 100644 --- a/tests/src/core/testqgslayoutpage.cpp +++ b/tests/src/core/testqgslayoutpage.cpp @@ -23,7 +23,6 @@ #include "qgsfillsymbollayer.h" #include "qgslinesymbollayer.h" #include "qgsmarkersymbollayer.h" -#include "qgsmultirenderchecker.h" #include "qgslayoutpagecollection.h" #include #include "qgstest.h" @@ -35,9 +34,10 @@ class TestQgsLayoutPage : public QgsTest Q_OBJECT public: - TestQgsLayoutPage() : QgsTest( QStringLiteral( "Layout Page Tests" ) ) {} + TestQgsLayoutPage() : QgsTest( QStringLiteral( "Layout Page Tests" ), QStringLiteral( "composer_paper" ) ) {} private slots: + void cleanupTestCase(); void itemType(); void pageSize(); @@ -54,6 +54,11 @@ class TestQgsLayoutPage : public QgsTest }; +void TestQgsLayoutPage::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + void TestQgsLayoutPage::itemType() { QgsProject p; @@ -152,9 +157,7 @@ void TestQgsLayoutPage::defaultPaper() page->setPageSize( QgsLayoutSize( 297, 210, Qgis::LayoutUnit::Millimeters ) ); l.pageCollection()->addPage( page.release() ); - QgsLayoutChecker checker( QStringLiteral( "composerpaper_default" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpaper_default" ), &l ) ); } void TestQgsLayoutPage::transparentPaper() @@ -172,9 +175,7 @@ void TestQgsLayoutPage::transparentPaper() simpleFill->setStrokeColor( Qt::transparent ); l.pageCollection()->setPageStyleSymbol( fillSymbol.get() ); - QgsLayoutChecker checker( QStringLiteral( "composerpaper_transparent" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpaper_transparent" ), &l ) ); } void TestQgsLayoutPage::borderedPaper() @@ -193,9 +194,7 @@ void TestQgsLayoutPage::borderedPaper() simpleFill->setStrokeWidth( 6 ); l.pageCollection()->setPageStyleSymbol( fillSymbol.get() ); - QgsLayoutChecker checker( QStringLiteral( "composerpaper_bordered" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpaper_bordered" ), &l ) ); } void TestQgsLayoutPage::markerLinePaper() @@ -212,9 +211,7 @@ void TestQgsLayoutPage::markerLinePaper() markerLineSymbol->changeSymbolLayer( 0, markerLine ); l.pageCollection()->setPageStyleSymbol( markerLineSymbol.get() ); - QgsLayoutChecker checker( QStringLiteral( "composerpaper_markerborder" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpaper_markerborder" ), &l ) ); } void TestQgsLayoutPage::hiddenPages() @@ -234,11 +231,7 @@ void TestQgsLayoutPage::hiddenPages() l.renderContext().setPagesVisible( false ); - QgsLayoutChecker checker( QStringLiteral( "composerpaper_hidden" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); - + QVERIFY( layoutCheck( QStringLiteral( "composerpaper_hidden" ), &l ) ); } void TestQgsLayoutPage::pageLayout() diff --git a/tests/src/core/testqgslayoutpicture.cpp b/tests/src/core/testqgslayoutpicture.cpp index c92703f4ef52..77fcdbf865fe 100644 --- a/tests/src/core/testqgslayoutpicture.cpp +++ b/tests/src/core/testqgslayoutpicture.cpp @@ -16,7 +16,6 @@ ***************************************************************************/ #include "qgsapplication.h" -#include "qgsmultirenderchecker.h" #include "qgslayoutitempicture.h" #include "qgsproject.h" #include "qgsproperty.h" @@ -34,7 +33,7 @@ class TestQgsLayoutPicture : public QgsTest public: - TestQgsLayoutPicture() : QgsTest( QStringLiteral( "Layout Picture Tests" ) ) {} + TestQgsLayoutPicture() : QgsTest( QStringLiteral( "Layout Picture Tests" ), QStringLiteral( "composer_picture" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -127,9 +126,7 @@ void TestQgsLayoutPicture::pictureRender() //test picture rotation mLayout->addLayoutItem( mPicture ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_render" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_render" ), mLayout ) ); mLayout->removeItem( mPicture ); } @@ -145,9 +142,7 @@ void TestQgsLayoutPicture::pictureRaster() l.addLayoutItem( p ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_render" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_render" ), &l ) ); } void TestQgsLayoutPicture::pictureSvg() @@ -162,9 +157,7 @@ void TestQgsLayoutPicture::pictureSvg() l.addLayoutItem( p ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_svg_zoom" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_svg_zoom" ), &l ) ); } void TestQgsLayoutPicture::pictureRotation() @@ -173,9 +166,7 @@ void TestQgsLayoutPicture::pictureRotation() mLayout->addLayoutItem( mPicture ); mPicture->setPictureRotation( 45 ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_rotation" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_rotation" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setPictureRotation( 0 ); @@ -187,9 +178,7 @@ void TestQgsLayoutPicture::pictureItemRotation() mLayout->addLayoutItem( mPicture ); mPicture->setItemRotation( 45, true ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_itemrotation" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_itemrotation" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setItemRotation( 0, true ); @@ -201,9 +190,7 @@ void TestQgsLayoutPicture::pictureResizeZoom() mLayout->addLayoutItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_resize_zoom" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_resize_zoom" ), mLayout ) ); mLayout->removeItem( mPicture ); } @@ -214,9 +201,7 @@ void TestQgsLayoutPicture::pictureResizeStretch() mLayout->addLayoutItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Stretch ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_resize_stretch" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_resize_stretch" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); @@ -229,9 +214,7 @@ void TestQgsLayoutPicture::pictureResizeClip() mPicture->setResizeMode( QgsLayoutItemPicture::Clip ); mPicture->attemptSetSceneRect( QRectF( 70, 70, 30, 50 ) ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_resize_clip" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_resize_clip" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); @@ -245,9 +228,7 @@ void TestQgsLayoutPicture::pictureResizeZoomAndResize() mPicture->setResizeMode( QgsLayoutItemPicture::ZoomResizeFrame ); mPicture->attemptSetSceneRect( QRectF( 70, 70, 50, 300 ) ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_resize_zoomresize" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_resize_zoomresize" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); @@ -261,9 +242,7 @@ void TestQgsLayoutPicture::pictureResizeFrameToImage() mPicture->setResizeMode( QgsLayoutItemPicture::FrameToImageSize ); mPicture->attemptSetSceneRect( QRectF( 70, 70, 50, 300 ) ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_resize_frametoimage" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_resize_frametoimage" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); @@ -278,9 +257,7 @@ void TestQgsLayoutPicture::pictureClipAnchor() mPicture->attemptSetSceneRect( QRectF( 70, 70, 30, 50 ) ); mPicture->setPictureAnchor( QgsLayoutItem::LowerRight ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_clip_anchor" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_clip_anchor" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); @@ -296,9 +273,7 @@ void TestQgsLayoutPicture::pictureClipAnchorOversize() mPicture->attemptSetSceneRect( QRectF( 70, 70, 150, 120 ) ); mPicture->setPictureAnchor( QgsLayoutItem::LowerMiddle ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_clip_anchoroversize" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_clip_anchoroversize" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); @@ -314,9 +289,7 @@ void TestQgsLayoutPicture::pictureZoomAnchor() mPicture->attemptSetSceneRect( QRectF( 70, 10, 30, 100 ) ); mPicture->setPictureAnchor( QgsLayoutItem::LowerMiddle ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_zoom_anchor" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_zoom_anchor" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setPictureAnchor( QgsLayoutItem::UpperLeft ); @@ -330,9 +303,7 @@ void TestQgsLayoutPicture::pictureSvgZoom() mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); mPicture->setPicturePath( mSvgImage ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_svg_zoom" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_svg_zoom" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setPicturePath( mPngImage ); @@ -346,9 +317,7 @@ void TestQgsLayoutPicture::pictureSvgStretch() mPicture->setPicturePath( mSvgImage ); mPicture->attemptSetSceneRect( QRectF( 70, 70, 20, 100 ) ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_svg_stretch" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_svg_stretch" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); @@ -364,9 +333,7 @@ void TestQgsLayoutPicture::pictureSvgZoomAndResize() mPicture->setPicturePath( mSvgImage ); mPicture->attemptSetSceneRect( QRectF( 70, 70, 50, 300 ) ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_svg_zoomresize" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_svg_zoomresize" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); @@ -381,9 +348,7 @@ void TestQgsLayoutPicture::pictureSvgFrameToImage() mPicture->setResizeMode( QgsLayoutItemPicture::FrameToImageSize ); mPicture->setPicturePath( mSvgImage ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_svg_frametoimage" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_svg_frametoimage" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); @@ -401,9 +366,7 @@ void TestQgsLayoutPicture::svgParameters() mPicture->setSvgStrokeColor( QColor( 255, 45, 20, 200 ) ); mPicture->setSvgStrokeWidth( 2.2 ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_svg_params" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_svg_params" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->attemptSetSceneRect( QRectF( 70, 70, 100, 100 ) ); @@ -424,9 +387,7 @@ void TestQgsLayoutPicture::dynamicSvgParameters() mPicture->setSvgDynamicParameters( parametersProperties ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_svg_dynamic_params" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_svg_dynamic_params" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->attemptSetSceneRect( QRectF( 70, 70, 100, 100 ) ); @@ -440,9 +401,7 @@ void TestQgsLayoutPicture::issue_14644() mPicture->setResizeMode( QgsLayoutItemPicture::Zoom ); mPicture->setPicturePath( QStringLiteral( TEST_DATA_DIR ) + "/svg/issue_14644.svg" ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_issue_14644" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_issue_14644" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->attemptSetSceneRect( QRectF( 70, 70, 100, 100 ) ); @@ -459,9 +418,7 @@ void TestQgsLayoutPicture::pictureExpression() mPicture->refreshPicture(); QVERIFY( !mPicture->isMissingImage() ); - QgsLayoutChecker checker( QStringLiteral( "composerpicture_expression" ), mLayout ); - checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerpicture_expression" ), mLayout ) ); mLayout->removeItem( mPicture ); mPicture->dataDefinedProperties().setProperty( QgsLayoutObject::PictureSource, QgsProperty() ); diff --git a/tests/src/core/testqgslayoutpolyline.cpp b/tests/src/core/testqgslayoutpolyline.cpp index e124be1d1e81..905ecb46234c 100644 --- a/tests/src/core/testqgslayoutpolyline.cpp +++ b/tests/src/core/testqgslayoutpolyline.cpp @@ -18,7 +18,6 @@ #include "qgsapplication.h" #include "qgslayoutitempolyline.h" -#include "qgsrenderchecker.h" #include #include @@ -29,16 +28,13 @@ class TestQgsLayoutPolyline : public QgsTest Q_OBJECT public: - TestQgsLayoutPolyline() : QgsTest( QStringLiteral( "Layout Polyline Tests" ) ) {} + TestQgsLayoutPolyline() : QgsTest( QStringLiteral( "Layout Polyline Tests" ), QStringLiteral( "composer_utils" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. void cleanupTestCase();// will be called after the last testfunction was executed. void drawArrowHead(); - private: - bool renderCheck( const QString &testName, QImage &image, int mismatchCount = 0 ); - }; void TestQgsLayoutPolyline::initTestCase() @@ -64,22 +60,7 @@ void TestQgsLayoutPolyline::drawArrowHead() testPainter.begin( &testImage ); QgsLayoutItemPolyline::drawArrowHead( &testPainter, 100, 100, 45, 30 ); testPainter.end(); - QVERIFY( renderCheck( "composerutils_drawarrowhead", testImage, 40 ) ); -} - - -bool TestQgsLayoutPolyline::renderCheck( const QString &testName, QImage &image, int mismatchCount ) -{ - const QString myTmpDir = QDir::tempPath() + '/'; - const QString myFileName = myTmpDir + testName + ".png"; - image.save( myFileName, "PNG" ); - QgsRenderChecker myChecker; - myChecker.setControlPathPrefix( QStringLiteral( "composer_utils" ) ); - myChecker.setControlName( "expected_" + testName ); - myChecker.setRenderedImage( myFileName ); - const bool myResultFlag = myChecker.compareImages( testName, mismatchCount ); - mReport += myChecker.report(); - return myResultFlag; + QVERIFY( imageCheck( "composerutils_drawarrowhead", "composerutils_drawarrowhead", testImage, QString(), 40 ) ); } QGSTEST_MAIN( TestQgsLayoutPolyline ) diff --git a/tests/src/core/testqgslayoutscalebar.cpp b/tests/src/core/testqgslayoutscalebar.cpp index 17f8f88fa616..f728182d3b6d 100644 --- a/tests/src/core/testqgslayoutscalebar.cpp +++ b/tests/src/core/testqgslayoutscalebar.cpp @@ -17,7 +17,6 @@ ***************************************************************************/ #include "qgsapplication.h" -#include "qgsmultirenderchecker.h" #include "qgslayoutitemmap.h" #include "qgslayoutitemscalebar.h" #include "qgsfontutils.h" @@ -41,7 +40,7 @@ class TestQgsLayoutScaleBar : public QgsTest Q_OBJECT public: - TestQgsLayoutScaleBar() : QgsTest( QStringLiteral( "Layout Scalebar Tests" ) ) {} + TestQgsLayoutScaleBar() : QgsTest( QStringLiteral( "Layout Scalebar Tests" ), QStringLiteral( "layout_scalebar" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -117,9 +116,7 @@ void TestQgsLayoutScaleBar::singleBox() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "Single Box" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_singlebox" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_singlebox" ), &l ) ); } void TestQgsLayoutScaleBar::singleBoxLineSymbol() @@ -161,9 +158,7 @@ void TestQgsLayoutScaleBar::singleBoxLineSymbol() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "Single Box" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_singlebox_linesymbol" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_singlebox_linesymbol" ), &l ) ); } void TestQgsLayoutScaleBar::singleBoxFillSymbol() @@ -204,9 +199,7 @@ void TestQgsLayoutScaleBar::singleBoxFillSymbol() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "Single Box" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_singlebox_fillsymbol" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_singlebox_fillsymbol" ), &l ) ); } void TestQgsLayoutScaleBar::singleBoxLabelBelowSegment() @@ -236,9 +229,7 @@ void TestQgsLayoutScaleBar::singleBoxLabelBelowSegment() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "Single Box" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_singlebox_labelbelowsegment" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_singlebox_labelbelowsegment" ), &l ) ); } void TestQgsLayoutScaleBar::singleBoxAlpha() @@ -277,9 +268,7 @@ void TestQgsLayoutScaleBar::singleBoxAlpha() Q_NOWARN_DEPRECATED_POP qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_singlebox_alpha" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_singlebox_alpha" ), &l ) ); } void TestQgsLayoutScaleBar::doubleBox() @@ -315,9 +304,7 @@ void TestQgsLayoutScaleBar::doubleBox() scalebar->setStyle( QStringLiteral( "Double Box" ) ); qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_doublebox" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_doublebox" ), &l ) ); } void TestQgsLayoutScaleBar::doubleBoxLineSymbol() @@ -359,9 +346,7 @@ void TestQgsLayoutScaleBar::doubleBoxLineSymbol() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "Double Box" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_doublebox_linesymbol" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_doublebox_linesymbol" ), &l ) ); } void TestQgsLayoutScaleBar::doubleBoxFillSymbol() @@ -402,9 +387,7 @@ void TestQgsLayoutScaleBar::doubleBoxFillSymbol() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "Double Box" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_doublebox_fillsymbol" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_doublebox_fillsymbol" ), &l ) ); } void TestQgsLayoutScaleBar::doubleBoxLabelCenteredSegment() @@ -443,9 +426,7 @@ void TestQgsLayoutScaleBar::doubleBoxLabelCenteredSegment() scalebar->setUnitLabel( QStringLiteral( "units" ) ); qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_doublebox_labelcenteredsegment" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_doublebox_labelcenteredsegment" ), &l ) ); } void TestQgsLayoutScaleBar::numeric() @@ -481,10 +462,7 @@ void TestQgsLayoutScaleBar::numeric() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setNumberDecimalPlaces( 0 ); scalebar->setStyle( QStringLiteral( "Numeric" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_numeric" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - const bool result = checker.testLayout( mReport, 0, 0 ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_numeric" ), &l ) ); } void TestQgsLayoutScaleBar::tick() @@ -516,9 +494,7 @@ void TestQgsLayoutScaleBar::tick() Q_NOWARN_DEPRECATED_PUSH scalebar->setLineWidth( 1.0 ); Q_NOWARN_DEPRECATED_POP - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_tick" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_tick" ), &l ) ); } void TestQgsLayoutScaleBar::tickLineSymbol() @@ -564,9 +540,7 @@ void TestQgsLayoutScaleBar::tickLineSymbol() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "Line Ticks Up" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_tick_linesymbol" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_tick_linesymbol" ), &l ) ); } void TestQgsLayoutScaleBar::dataDefined() @@ -638,9 +612,7 @@ void TestQgsLayoutScaleBar::dataDefined() QCOMPARE( scalebar->subdivisionsHeight(), 30.0 ); QCOMPARE( scalebar->numberOfSubdivisions(), 40 ); - QgsLayoutChecker checker2( QStringLiteral( "layoutscalebar_datadefined" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker2.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_datadefined" ), &l ) ); } void TestQgsLayoutScaleBar::oldDataDefinedProject() @@ -697,9 +669,7 @@ void TestQgsLayoutScaleBar::textFormat() format.dataDefinedProperties().setProperty( QgsPalLayerSettings::Color, QgsProperty::fromExpression( QStringLiteral( "case when @scale_value = 2000 then '#ff00ff' else '#ffff00' end" ) ) ); scalebar->setTextFormat( format ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_textformat" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_textformat" ), &l ) ); } void TestQgsLayoutScaleBar::numericFormat() @@ -733,9 +703,7 @@ void TestQgsLayoutScaleBar::numericFormat() newFont.setPointSizeF( 12 ); scalebar->setTextFormat( QgsTextFormat::fromQFont( newFont ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_numericformat" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_numericformat" ), &l ) ); } void TestQgsLayoutScaleBar::steppedLine() @@ -778,9 +746,7 @@ void TestQgsLayoutScaleBar::steppedLine() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "stepped" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_stepped" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_stepped" ), &l ) ); } void TestQgsLayoutScaleBar::hollow() @@ -837,16 +803,14 @@ void TestQgsLayoutScaleBar::hollow() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "hollow" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_hollow" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_hollow" ), &l ) ); } void TestQgsLayoutScaleBar::hollowDefaults() { QgsLayout l( QgsProject::instance() ); - QgsLayoutItemScaleBar *scalebar = new QgsLayoutItemScaleBar( &l ); + std::unique_ptr< QgsLayoutItemScaleBar > scalebar = std::make_unique< QgsLayoutItemScaleBar >( &l ); // apply random symbols std::unique_ptr< QgsLineSymbol > lineSymbol = std::make_unique< QgsLineSymbol >(); @@ -939,9 +903,7 @@ void TestQgsLayoutScaleBar::tickSubdivisions() qgis::down_cast< QgsBasicNumericFormat *>( const_cast< QgsNumericFormat * >( scalebar->numericFormat() ) )->setShowThousandsSeparator( false ); scalebar->setStyle( QStringLiteral( "Line Ticks Middle" ) ); - QgsLayoutChecker checker( QStringLiteral( "layoutscalebar_tick_subdivisions" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "layout_scalebar" ) ); - QVERIFY( checker.testLayout( mReport, 0, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "layoutscalebar_tick_subdivisions" ), &l ) ); } diff --git a/tests/src/core/testqgslayoutshapes.cpp b/tests/src/core/testqgslayoutshapes.cpp index 36377f44d2a7..52854eea043a 100644 --- a/tests/src/core/testqgslayoutshapes.cpp +++ b/tests/src/core/testqgslayoutshapes.cpp @@ -16,7 +16,6 @@ ***************************************************************************/ #include "qgsapplication.h" -#include "qgsmultirenderchecker.h" #include "qgslayoutitemshape.h" #include "qgsproject.h" #include "qgssymbol.h" @@ -35,7 +34,7 @@ class TestQgsLayoutShapes : public QgsTest Q_OBJECT public: - TestQgsLayoutShapes() : QgsTest( QStringLiteral( "Layout Shape Tests" ) ) {} + TestQgsLayoutShapes() : QgsTest( QStringLiteral( "Layout Shape Tests" ), QStringLiteral( "composer_shapes" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -71,7 +70,6 @@ void TestQgsLayoutShapes::rectangle() shape->attemptMove( QgsLayoutPoint( 20, 20 ) ); shape->attemptResize( QgsLayoutSize( 150, 100 ) ); - QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer(); std::unique_ptr< QgsFillSymbol > fillSymbol( new QgsFillSymbol() ); fillSymbol->changeSymbolLayer( 0, simpleFill ); @@ -83,9 +81,7 @@ void TestQgsLayoutShapes::rectangle() l.addLayoutItem( shape ); - QgsLayoutChecker checker( QStringLiteral( "composershapes_rectangle" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composershapes_rectangle" ), &l ) ); } void TestQgsLayoutShapes::triangle() @@ -99,7 +95,6 @@ void TestQgsLayoutShapes::triangle() shape->attemptMove( QgsLayoutPoint( 20, 20 ) ); shape->attemptResize( QgsLayoutSize( 150, 100 ) ); - QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer(); std::unique_ptr< QgsFillSymbol > fillSymbol( new QgsFillSymbol() ); fillSymbol->changeSymbolLayer( 0, simpleFill ); @@ -111,9 +106,7 @@ void TestQgsLayoutShapes::triangle() l.addLayoutItem( shape ); - QgsLayoutChecker checker( QStringLiteral( "composershapes_triangle" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composershapes_triangle" ), &l ) ); } void TestQgsLayoutShapes::ellipse() @@ -138,9 +131,7 @@ void TestQgsLayoutShapes::ellipse() l.addLayoutItem( shape ); - QgsLayoutChecker checker( QStringLiteral( "composershapes_ellipse" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composershapes_ellipse" ), &l ) ); } void TestQgsLayoutShapes::roundedRectangle() @@ -166,9 +157,7 @@ void TestQgsLayoutShapes::roundedRectangle() shape->setCornerRadius( QgsLayoutMeasurement( 30 ) ); - QgsLayoutChecker checker( QStringLiteral( "composershapes_roundedrect" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composershapes_roundedrect" ), &l ) ); } void TestQgsLayoutShapes::symbol() @@ -192,9 +181,7 @@ void TestQgsLayoutShapes::symbol() delete fillSymbol; l.addLayoutItem( shape ); - QgsLayoutChecker checker( QStringLiteral( "composershapes_symbol" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) ); - QVERIFY( checker.testLayout( mReport ) ); + QVERIFY( layoutCheck( QStringLiteral( "composershapes_symbol" ), &l ) ); } void TestQgsLayoutShapes::readWriteXml() @@ -284,9 +271,9 @@ void TestQgsLayoutShapes::shapeRotation() delete fillSymbol; l.addLayoutItem( shape ); - QgsLayoutChecker checker( QStringLiteral( "composerrotation_shape" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_items" ) ); - QVERIFY( checker.testLayout( mReport ) ); + mControlPathPrefix = QStringLiteral( "composer_items" ); + QVERIFY( layoutCheck( QStringLiteral( "composerrotation_shape" ), &l ) ); + mControlPathPrefix = QStringLiteral( "composer_shape" ); } QGSTEST_MAIN( TestQgsLayoutShapes ) diff --git a/tests/src/core/testqgslayouttable.cpp b/tests/src/core/testqgslayouttable.cpp index 22700143fddc..f5032b2f98de 100644 --- a/tests/src/core/testqgslayouttable.cpp +++ b/tests/src/core/testqgslayouttable.cpp @@ -21,11 +21,9 @@ #include "qgslayoutitemattributetable.h" #include "qgslayouttablecolumn.h" #include "qgslayoutframe.h" -#include "qgsmapsettings.h" #include "qgsvectorlayer.h" #include "qgsvectordataprovider.h" #include "qgsfeature.h" -#include "qgsmultirenderchecker.h" #include "qgsfontutils.h" #include "qgsproject.h" #include "qgsrelationmanager.h" @@ -48,7 +46,7 @@ class TestQgsLayoutTable : public QgsTest Q_OBJECT public: - TestQgsLayoutTable() : QgsTest( QStringLiteral( "Layout Table Tests" ) ) {} + TestQgsLayoutTable() : QgsTest( QStringLiteral( "Layout Table Tests" ), QStringLiteral( "composer_table" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. @@ -513,10 +511,7 @@ void TestQgsLayoutTable::attributeTableRender() table->setBackgroundColor( Qt::yellow ); table->setMaximumNumberOfFeatures( 20 ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_render" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_render" ), &l ) ); } void TestQgsLayoutTable::manualColumnWidth() @@ -541,10 +536,7 @@ void TestQgsLayoutTable::manualColumnWidth() table->setMaximumNumberOfFeatures( 20 ); table->columns()[0].setWidth( 5 ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_columnwidth" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - const bool result = checker.testLayout( mReport, 0 ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_columnwidth" ), &l ) ); } void TestQgsLayoutTable::attributeTableEmpty() @@ -573,20 +565,14 @@ void TestQgsLayoutTable::attributeTableEmpty() table->setFilterFeatures( true ); table->setEmptyTableBehavior( QgsLayoutTable::HeadersOnly ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_headersonly" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - QVERIFY( checker.testLayout( mReport, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_headersonly" ), &l ) ); table->setEmptyTableBehavior( QgsLayoutTable::HideTable ); - QgsLayoutChecker checker2( QStringLiteral( "composerattributetable_hidetable" ), &l ); - checker2.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - QVERIFY( checker2.testLayout( mReport, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_hidetable" ), &l ) ); table->setEmptyTableBehavior( QgsLayoutTable::ShowMessage ); table->setEmptyTableMessage( QStringLiteral( "no rows" ) ); - QgsLayoutChecker checker3( QStringLiteral( "composerattributetable_showmessage" ), &l ); - checker3.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - QVERIFY( checker3.testLayout( mReport, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_showmessage" ), &l ) ); } void TestQgsLayoutTable::showEmptyRows() @@ -611,9 +597,7 @@ void TestQgsLayoutTable::showEmptyRows() table->setMaximumNumberOfFeatures( 3 ); table->setShowEmptyRows( true ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_drawempty" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - QVERIFY( checker.testLayout( mReport, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_drawempty" ), &l ) ); } void TestQgsLayoutTable::attributeTableExtend() @@ -997,10 +981,7 @@ void TestQgsLayoutTable::multiLineText() table->setMaximumNumberOfFeatures( 20 ); table->setVectorLayer( multiLineLayer ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_multiline" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_multiline" ), &l ) ); delete multiLineLayer; } @@ -1054,10 +1035,7 @@ void TestQgsLayoutTable::horizontalGrid() table->setHorizontalGrid( true ); table->setVerticalGrid( false ); table->setVectorLayer( multiLineLayer ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_horizontalgrid" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_horizontalgrid" ), &l ) ); delete multiLineLayer; } @@ -1111,10 +1089,7 @@ void TestQgsLayoutTable::verticalGrid() table->setHorizontalGrid( false ); table->setVerticalGrid( true ); table->setVectorLayer( multiLineLayer ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_verticalgrid" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_verticalgrid" ), &l ) ); delete multiLineLayer; } @@ -1139,10 +1114,7 @@ void TestQgsLayoutTable::testDataDefinedTextFormatForCell() textFormat.dataDefinedProperties().setProperty( QgsPalLayerSettings::Size, QgsProperty::fromExpression( QStringLiteral( "if(@column_number = 1,35,15)" ) ) ); table->setContentTextFormat( textFormat ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_datadefinedtextformat" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_datadefinedtextformat" ), &l ) ); } void TestQgsLayoutTable::testIntegerNullCell() @@ -1172,10 +1144,7 @@ void TestQgsLayoutTable::testIntegerNullCell() table->setContentTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); table->setHeaderTextFormat( QgsTextFormat::fromQFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) ) ) ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_integernullcell" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_integernullcell" ), &l ) ); } @@ -1230,10 +1199,7 @@ void TestQgsLayoutTable::align() table->columns()[1].setVAlignment( Qt::AlignVCenter ); table->columns()[2].setHAlignment( Qt::AlignRight ); table->columns()[2].setVAlignment( Qt::AlignBottom ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_align" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - const bool result = checker.testLayout( mReport ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_align" ), &l ) ); delete multiLineLayer; } @@ -1319,10 +1285,7 @@ void TestQgsLayoutTable::autoWrap() table->columns()[0].setWidth( 25 ); table->columns()[1].setWidth( 25 ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_autowrap" ), &l ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - const bool result = checker.testLayout( mReport, 0 ); - QVERIFY( result ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_autowrap" ), &l ) ); } void TestQgsLayoutTable::cellStyles() @@ -1569,10 +1532,7 @@ void TestQgsLayoutTable::cellStylesRender() style.cellBackgroundColor = QColor( 50, 200, 200, 200 ); table->setCellStyle( QgsLayoutTable::LastRow, style ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_cellstyle" ), &l ); - checker.setColorTolerance( 10 ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - QVERIFY( checker.testLayout( mReport, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_cellstyle" ), &l, 0, 0, QSize(), 10 ) ); } void TestQgsLayoutTable::conditionalFormatting() @@ -1631,10 +1591,7 @@ void TestQgsLayoutTable::conditionalFormatting() style.cellBackgroundColor = QColor( 50, 200, 200, 200 ); table->setCellStyle( QgsLayoutTable::LastRow, style ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_conditionalstyles" ), &l ); - checker.setColorTolerance( 10 ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - QVERIFY( checker.testLayout( mReport, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_conditionalstyles" ), &l, 0, 0, QSize(), 10 ) ); } void TestQgsLayoutTable::conditionalFormattingWithTextFormatting() @@ -1701,10 +1658,7 @@ void TestQgsLayoutTable::conditionalFormattingWithTextFormatting() style.cellBackgroundColor = QColor( 50, 200, 200, 200 ); table->setCellStyle( QgsLayoutTable::LastRow, style ); - QgsLayoutChecker checker( QStringLiteral( "composerattributetable_conditionalstyles_text" ), &l ); - checker.setColorTolerance( 10 ); - checker.setControlPathPrefix( QStringLiteral( "composer_table" ) ); - QVERIFY( checker.testLayout( mReport, 0 ) ); + QVERIFY( layoutCheck( QStringLiteral( "composerattributetable_conditionalstyles_text" ), &l, 0, 0, QSize(), 10 ) ); } void TestQgsLayoutTable::dataDefinedSource() diff --git a/tests/src/core/testqgslayoutunits.cpp b/tests/src/core/testqgslayoutunits.cpp index 95cc89886d04..3c62f4b9fc8d 100644 --- a/tests/src/core/testqgslayoutunits.cpp +++ b/tests/src/core/testqgslayoutunits.cpp @@ -24,9 +24,11 @@ #include "qgslayoutmeasurementconverter.h" #include "qgis.h" -class TestQgsLayoutUnits : public QObject +class TestQgsLayoutUnits : public QgsTest { Q_OBJECT + public: + TestQgsLayoutUnits() : QgsTest( QStringLiteral( "Layout Units Tests" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. diff --git a/tests/src/core/testqgslayoututils.cpp b/tests/src/core/testqgslayoututils.cpp index 062f8a6b8370..3973eb6c5209 100644 --- a/tests/src/core/testqgslayoututils.cpp +++ b/tests/src/core/testqgslayoututils.cpp @@ -20,7 +20,6 @@ #include "qgsproject.h" #include "qgslayoutitemmap.h" #include "qgsfontutils.h" -#include "qgsrenderchecker.h" #include "qgsvectorlayer.h" #include "qgslayout.h" #include "qgslayoutrendercontext.h" @@ -32,10 +31,11 @@ class TestQgsLayoutUtils: public QgsTest Q_OBJECT public: - TestQgsLayoutUtils() : QgsTest( QStringLiteral( "Layout Utils Tests" ) ) {} + TestQgsLayoutUtils() : QgsTest( QStringLiteral( "Layout Utils Tests" ), QStringLiteral( "composer_utils" ) ) {} private slots: void initTestCase();// will be called before the first testfunction is executed. + void cleanupTestCase(); void rotate(); void normalizedAngle(); //test normalised angle function void snappedAngle(); @@ -60,8 +60,6 @@ class TestQgsLayoutUtils: public QgsTest private: - bool renderCheck( const QString &testName, QImage &image, int mismatchCount = 0 ); - QFont mTestFont; }; @@ -72,6 +70,11 @@ void TestQgsLayoutUtils::initTestCase() mTestFont.setItalic( true ); } +void TestQgsLayoutUtils::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + void TestQgsLayoutUtils::rotate() { // pairs of lines from before -> expected after position and angle to rotate @@ -490,7 +493,7 @@ void TestQgsLayoutUtils::drawTextPos() testPainter.begin( &testImage ); QgsLayoutUtils::drawText( &testPainter, QPointF( 5, 15 ), QStringLiteral( "Abc123" ), mTestFont, Qt::white ); testPainter.end(); - QVERIFY( renderCheck( "composerutils_drawtext_pos", testImage, 100 ) ); + QVERIFY( imageCheck( "composerutils_drawtext_pos", "composerutils_drawtext_pos", testImage, QString(), 100 ) ); //test drawing with pen color set on painter and no specified color //text should be drawn using painter pen color @@ -499,7 +502,7 @@ void TestQgsLayoutUtils::drawTextPos() testPainter.setPen( QPen( Qt::green ) ); QgsLayoutUtils::drawText( &testPainter, QPointF( 5, 15 ), QStringLiteral( "Abc123" ), mTestFont ); testPainter.end(); - QVERIFY( renderCheck( "composerutils_drawtext_posnocolor", testImage, 100 ) ); + QVERIFY( imageCheck( "composerutils_drawtext_posnocolor", "composerutils_drawtext_posnocolor", testImage, QString(), 100 ) ); } void TestQgsLayoutUtils::drawTextRect() @@ -515,7 +518,7 @@ void TestQgsLayoutUtils::drawTextRect() testPainter.begin( &testImage ); QgsLayoutUtils::drawText( &testPainter, QRectF( 5, 15, 200, 50 ), QStringLiteral( "Abc123" ), mTestFont, Qt::white ); testPainter.end(); - QVERIFY( renderCheck( "composerutils_drawtext_rect", testImage, 100 ) ); + QVERIFY( imageCheck( "composerutils_drawtext_rect", "composerutils_drawtext_rect", testImage, QString(), 100 ) ); //test drawing with pen color set on painter and no specified color //text should be drawn using painter pen color @@ -524,21 +527,21 @@ void TestQgsLayoutUtils::drawTextRect() testPainter.setPen( QPen( Qt::green ) ); QgsLayoutUtils::drawText( &testPainter, QRectF( 5, 15, 200, 50 ), QStringLiteral( "Abc123" ), mTestFont ); testPainter.end(); - QVERIFY( renderCheck( "composerutils_drawtext_rectnocolor", testImage, 100 ) ); + QVERIFY( imageCheck( "composerutils_drawtext_rectnocolor", "composerutils_drawtext_rectnocolor", testImage, QString(), 100 ) ); //test alignment settings testImage.fill( qRgb( 152, 219, 249 ) ); testPainter.begin( &testImage ); QgsLayoutUtils::drawText( &testPainter, QRectF( 5, 15, 200, 50 ), QStringLiteral( "Abc123" ), mTestFont, Qt::black, Qt::AlignRight, Qt::AlignBottom ); testPainter.end(); - QVERIFY( renderCheck( "composerutils_drawtext_rectalign", testImage, 100 ) ); + QVERIFY( imageCheck( "composerutils_drawtext_rectalign", "composerutils_drawtext_rectalign", testImage, QString(), 100 ) ); //test extra flags - render without clipping testImage.fill( qRgb( 152, 219, 249 ) ); testPainter.begin( &testImage ); QgsLayoutUtils::drawText( &testPainter, QRectF( 5, 15, 20, 50 ), QStringLiteral( "Abc123" ), mTestFont, Qt::white, Qt::AlignLeft, Qt::AlignTop, Qt::TextDontClip ); testPainter.end(); - QVERIFY( renderCheck( "composerutils_drawtext_rectflag", testImage, 100 ) ); + QVERIFY( imageCheck( "composerutils_drawtext_rectflag", "composerutils_drawtext_rectflag", testImage, QString(), 100 ) ); } void TestQgsLayoutUtils::largestRotatedRect() @@ -642,21 +645,6 @@ void TestQgsLayoutUtils::mapLayerFromString() QCOMPARE( QgsLayoutUtils::mapLayerFromString( l2->id(), &p ), l2 ); QCOMPARE( QgsLayoutUtils::mapLayerFromString( l2a->id(), &p ), l2a ); QVERIFY( !QgsLayoutUtils::mapLayerFromString( "none", &p ) ); - -} - -bool TestQgsLayoutUtils::renderCheck( const QString &testName, QImage &image, int mismatchCount ) -{ - const QString myTmpDir = QDir::tempPath() + '/'; - const QString myFileName = myTmpDir + testName + ".png"; - image.save( myFileName, "PNG" ); - QgsRenderChecker myChecker; - myChecker.setControlPathPrefix( QStringLiteral( "composer_utils" ) ); - myChecker.setControlName( "expected_" + testName ); - myChecker.setRenderedImage( myFileName ); - const bool myResultFlag = myChecker.compareImages( testName, mismatchCount ); - mReport += myChecker.report(); - return myResultFlag; } QGSTEST_MAIN( TestQgsLayoutUtils ) diff --git a/tests/testdata/control_images/composer_table/expected_composerattributetable_conditionalstyles_text/expected_composerattributetable_conditionalstyles_text_mask.png b/tests/testdata/control_images/composer_table/expected_composerattributetable_conditionalstyles_text/expected_composerattributetable_conditionalstyles_text_mask.png index d734e1cc5f0d2b5276bf0ae3dee509f34b73b826..afd3b2461ee672a10ba83ee0853682e347261a0e 100644 GIT binary patch literal 25349 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 literal 25326 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 OCt_HKnJtW?Xa50H_y&pq