tsrc/qtestutils/src/testrunner.cpp
changeset 37 e9675fb210bd
equal deleted inserted replaced
34:01f0bb65bcf1 37:e9675fb210bd
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 #include "testrunner.h"
       
    19 #include <QtTest/QtTest>
       
    20 #include <QDir>
       
    21 #include <stdio.h>
       
    22 
       
    23 const char testCaseElement[] = "TestCase";
       
    24 const char testFunctionElement[] = "TestFunction";
       
    25 const char incidentElement[] = "Incident";
       
    26 const char descriptionElement[] = "Description";
       
    27 const char nameAttr[] = "name";
       
    28 const char typeAttr[] = "type";
       
    29 const char fileAttr[] = "file";
       
    30 const char lineAttr[] = "line";
       
    31 const char attrValueFail[] = "fail";
       
    32 
       
    33 
       
    34 TestRunner::TestRunner(const QString& name, const QString& combinedOutputFileName)
       
    35 : mTestCount(0),
       
    36   mParsingIncidentElement(false),
       
    37   mParsingDescriptionElement(false),
       
    38   mCurrentTestFailed(false),
       
    39   mCurrentTestFailureLine(0),
       
    40   mCombinedOutputFileName(combinedOutputFileName)
       
    41 {
       
    42     mTestRunParams.append(name);
       
    43     mTestRunParams.append("-xml");
       
    44     mTestRunParams.append("-o");
       
    45     mHomeDir = QDir::homePath();
       
    46     mTestRunParams.append(QString()); // Initial result file name
       
    47 
       
    48     if (!mHomeDir.endsWith(QString::fromAscii("/")))
       
    49         mHomeDir += QString::fromAscii("/");
       
    50 }
       
    51 
       
    52 TestRunner::~TestRunner()
       
    53 {
       
    54 }
       
    55 
       
    56 int TestRunner::runTests(QObject& testObject)
       
    57 {
       
    58     QString className(testObject.metaObject()->className());
       
    59     printf("Running tests for %s ... ", className.toUtf8().data());
       
    60     QString resultFileName = mHomeDir + className + ".xml";
       
    61     mTestRunParams.replace(mTestRunParams.count()-1,resultFileName);
       
    62     int errorsBefore = mErrors.count();
       
    63     int error = QTest::qExec(&testObject, mTestRunParams);
       
    64     parse(resultFileName);
       
    65     mResultFiles.append(resultFileName);
       
    66     printf("Failures: %d\n",mErrors.count()-errorsBefore);
       
    67     fflush(stdout);
       
    68     return error;
       
    69 }
       
    70 
       
    71 void TestRunner::printResults()
       
    72 {
       
    73     printf("\nTests executed: %d\n",mTestCount);
       
    74     if (mErrors.count() > 0) {
       
    75         printf("Failures (%d):\n", mErrors.count());
       
    76         foreach(QString error, mErrors) {
       
    77             printf("\n%s", error.toUtf8().data());
       
    78         }
       
    79         printf("\n");
       
    80     } else {
       
    81         printf("All passed.\n\n");
       
    82     }
       
    83     fflush(stdout);
       
    84     
       
    85     combineResults();
       
    86 }
       
    87 
       
    88 void TestRunner::parse(const QString& fileName)
       
    89 {
       
    90     QFile file(fileName);
       
    91     QXmlInputSource inputSource(&file);
       
    92     QXmlSimpleReader reader;
       
    93     reader.setContentHandler(this);
       
    94     reader.parse(inputSource);
       
    95 }
       
    96 
       
    97 bool TestRunner::startElement(
       
    98     const QString& /*namespaceURI*/, 
       
    99     const QString& /*localName*/, 
       
   100     const QString& qName, 
       
   101     const QXmlAttributes& atts)
       
   102 {
       
   103     if (qName == QString::fromAscii(testFunctionElement)) {
       
   104         mTestCount++;
       
   105         mCurrentTestName = atts.value(QString::fromAscii(nameAttr));
       
   106         return true;
       
   107     }
       
   108     if (qName == QString::fromAscii(incidentElement)) {
       
   109         mParsingIncidentElement = true;
       
   110         if (atts.value(QString::fromAscii(typeAttr)) == QString::fromAscii(attrValueFail)) {
       
   111             mCurrentTestFailed = true;
       
   112             mCurrentTestFile = atts.value(QString::fromAscii(fileAttr));
       
   113             mCurrentTestFailureLine = atts.value(QString::fromAscii(lineAttr)).toInt();
       
   114         }
       
   115         return true;
       
   116     }
       
   117     mParsingDescriptionElement =
       
   118         (qName == QString::fromAscii(descriptionElement));
       
   119     return true;
       
   120 }
       
   121 
       
   122 bool TestRunner::endElement(
       
   123     const QString& /*namespaceURI*/,
       
   124     const QString& /*localName*/,
       
   125     const QString& qName)
       
   126 {
       
   127     if (qName == QString::fromAscii(incidentElement)) {
       
   128         mParsingIncidentElement = false;
       
   129         mCurrentTestFailed = false;
       
   130         return true;
       
   131     }
       
   132     if (qName == QString::fromAscii(descriptionElement)) {
       
   133         mParsingDescriptionElement = false;
       
   134     }    
       
   135     return true;
       
   136 }
       
   137 
       
   138 bool TestRunner::characters(const QString& ch)
       
   139 {
       
   140     if (mParsingIncidentElement && 
       
   141         mParsingDescriptionElement &&
       
   142         mCurrentTestFailed) {
       
   143         QByteArray testResult = mCurrentTestName.toAscii() + " failed:\n";
       
   144         testResult += "File: ";
       
   145         testResult += mCurrentTestFile.toAscii();
       
   146         testResult += "\n";
       
   147         testResult += "Line: ";
       
   148         testResult += QByteArray::number(mCurrentTestFailureLine);
       
   149         testResult += "\n";
       
   150         testResult += "Reason: ";
       
   151         testResult += ch.toAscii();
       
   152         testResult += "\n";
       
   153         mErrors.append(QString::fromAscii(testResult.data()));
       
   154     }
       
   155     return true;
       
   156 }
       
   157 
       
   158 void TestRunner::combineResults()
       
   159 {
       
   160     if ( mCombinedOutputFileName.isEmpty() ){
       
   161         return;
       
   162     }
       
   163     if ( !mCombinedOutputFileName.contains(QString::fromAscii("/")) ){
       
   164         mCombinedOutputFileName.prepend( mHomeDir );
       
   165     }
       
   166     QFile file(mCombinedOutputFileName);
       
   167     if (!file.open(QIODevice::WriteOnly)){
       
   168         return;
       
   169     }
       
   170 
       
   171     QXmlStreamWriter writer(&file);
       
   172     writer.setAutoFormatting(true);
       
   173     writer.writeStartDocument();
       
   174     QString caseName;
       
   175     foreach ( QString resultFile, mResultFiles ){
       
   176         QFile readFile( resultFile );
       
   177         if ( resultFile != mCombinedOutputFileName && readFile.open(QIODevice::ReadOnly) ){
       
   178             QXmlStreamReader reader(&readFile);
       
   179             appendToXml(writer, reader, caseName);
       
   180             readFile.close();
       
   181         }
       
   182     }
       
   183     writer.writeEndDocument();
       
   184     file.close();
       
   185 }
       
   186 
       
   187 void TestRunner::appendToXml(QXmlStreamWriter& writer, QXmlStreamReader& reader, QString& caseName)
       
   188 {
       
   189     while (!reader.atEnd()) {
       
   190         QXmlStreamReader::TokenType type = reader.readNext();
       
   191         if ( type == QXmlStreamReader::StartDocument  || 
       
   192              type == QXmlStreamReader::EndDocument ){
       
   193             // Ignored
       
   194         } else if ( reader.name() == testCaseElement ){
       
   195             if ( type == QXmlStreamReader::StartElement ){
       
   196                 QString tempCaseName = reader.attributes().value(nameAttr).toString();
       
   197                 if ( caseName.isEmpty() && type == QXmlStreamReader::StartElement){
       
   198                     writer.writeStartElement(testCaseElement);
       
   199                     writer.writeAttribute(nameAttr, mTestRunParams.at(0));
       
   200                 }
       
   201                 caseName = tempCaseName;
       
   202             }  
       
   203         } else if ( type == QXmlStreamReader::StartElement ) {
       
   204             if ( reader.name() == testFunctionElement ){
       
   205                 QString tempFuncName = reader.attributes().value(nameAttr).toString();
       
   206                 if ( !tempFuncName.isEmpty() ){
       
   207                     writer.writeStartElement(testFunctionElement);
       
   208                     writer.writeAttribute(nameAttr, caseName + "::" + tempFuncName);
       
   209                 }
       
   210             } else {
       
   211                 writer.writeCurrentToken( reader );
       
   212             }
       
   213         } else {
       
   214             writer.writeCurrentToken( reader );
       
   215         }
       
   216     }
       
   217 }