tsrc/qtestutils/src/testrunner.cpp
changeset 37 e9675fb210bd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tsrc/qtestutils/src/testrunner.cpp	Fri Sep 17 08:28:43 2010 +0300
@@ -0,0 +1,217 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+#include "testrunner.h"
+#include <QtTest/QtTest>
+#include <QDir>
+#include <stdio.h>
+
+const char testCaseElement[] = "TestCase";
+const char testFunctionElement[] = "TestFunction";
+const char incidentElement[] = "Incident";
+const char descriptionElement[] = "Description";
+const char nameAttr[] = "name";
+const char typeAttr[] = "type";
+const char fileAttr[] = "file";
+const char lineAttr[] = "line";
+const char attrValueFail[] = "fail";
+
+
+TestRunner::TestRunner(const QString& name, const QString& combinedOutputFileName)
+: mTestCount(0),
+  mParsingIncidentElement(false),
+  mParsingDescriptionElement(false),
+  mCurrentTestFailed(false),
+  mCurrentTestFailureLine(0),
+  mCombinedOutputFileName(combinedOutputFileName)
+{
+    mTestRunParams.append(name);
+    mTestRunParams.append("-xml");
+    mTestRunParams.append("-o");
+    mHomeDir = QDir::homePath();
+    mTestRunParams.append(QString()); // Initial result file name
+
+    if (!mHomeDir.endsWith(QString::fromAscii("/")))
+        mHomeDir += QString::fromAscii("/");
+}
+
+TestRunner::~TestRunner()
+{
+}
+
+int TestRunner::runTests(QObject& testObject)
+{
+    QString className(testObject.metaObject()->className());
+    printf("Running tests for %s ... ", className.toUtf8().data());
+    QString resultFileName = mHomeDir + className + ".xml";
+    mTestRunParams.replace(mTestRunParams.count()-1,resultFileName);
+    int errorsBefore = mErrors.count();
+    int error = QTest::qExec(&testObject, mTestRunParams);
+    parse(resultFileName);
+    mResultFiles.append(resultFileName);
+    printf("Failures: %d\n",mErrors.count()-errorsBefore);
+    fflush(stdout);
+    return error;
+}
+
+void TestRunner::printResults()
+{
+    printf("\nTests executed: %d\n",mTestCount);
+    if (mErrors.count() > 0) {
+        printf("Failures (%d):\n", mErrors.count());
+        foreach(QString error, mErrors) {
+            printf("\n%s", error.toUtf8().data());
+        }
+        printf("\n");
+    } else {
+        printf("All passed.\n\n");
+    }
+    fflush(stdout);
+    
+    combineResults();
+}
+
+void TestRunner::parse(const QString& fileName)
+{
+    QFile file(fileName);
+    QXmlInputSource inputSource(&file);
+    QXmlSimpleReader reader;
+    reader.setContentHandler(this);
+    reader.parse(inputSource);
+}
+
+bool TestRunner::startElement(
+    const QString& /*namespaceURI*/, 
+    const QString& /*localName*/, 
+    const QString& qName, 
+    const QXmlAttributes& atts)
+{
+    if (qName == QString::fromAscii(testFunctionElement)) {
+        mTestCount++;
+        mCurrentTestName = atts.value(QString::fromAscii(nameAttr));
+        return true;
+    }
+    if (qName == QString::fromAscii(incidentElement)) {
+        mParsingIncidentElement = true;
+        if (atts.value(QString::fromAscii(typeAttr)) == QString::fromAscii(attrValueFail)) {
+            mCurrentTestFailed = true;
+            mCurrentTestFile = atts.value(QString::fromAscii(fileAttr));
+            mCurrentTestFailureLine = atts.value(QString::fromAscii(lineAttr)).toInt();
+        }
+        return true;
+    }
+    mParsingDescriptionElement =
+        (qName == QString::fromAscii(descriptionElement));
+    return true;
+}
+
+bool TestRunner::endElement(
+    const QString& /*namespaceURI*/,
+    const QString& /*localName*/,
+    const QString& qName)
+{
+    if (qName == QString::fromAscii(incidentElement)) {
+        mParsingIncidentElement = false;
+        mCurrentTestFailed = false;
+        return true;
+    }
+    if (qName == QString::fromAscii(descriptionElement)) {
+        mParsingDescriptionElement = false;
+    }    
+    return true;
+}
+
+bool TestRunner::characters(const QString& ch)
+{
+    if (mParsingIncidentElement && 
+        mParsingDescriptionElement &&
+        mCurrentTestFailed) {
+        QByteArray testResult = mCurrentTestName.toAscii() + " failed:\n";
+        testResult += "File: ";
+        testResult += mCurrentTestFile.toAscii();
+        testResult += "\n";
+        testResult += "Line: ";
+        testResult += QByteArray::number(mCurrentTestFailureLine);
+        testResult += "\n";
+        testResult += "Reason: ";
+        testResult += ch.toAscii();
+        testResult += "\n";
+        mErrors.append(QString::fromAscii(testResult.data()));
+    }
+    return true;
+}
+
+void TestRunner::combineResults()
+{
+    if ( mCombinedOutputFileName.isEmpty() ){
+        return;
+    }
+    if ( !mCombinedOutputFileName.contains(QString::fromAscii("/")) ){
+        mCombinedOutputFileName.prepend( mHomeDir );
+    }
+    QFile file(mCombinedOutputFileName);
+    if (!file.open(QIODevice::WriteOnly)){
+        return;
+    }
+
+    QXmlStreamWriter writer(&file);
+    writer.setAutoFormatting(true);
+    writer.writeStartDocument();
+    QString caseName;
+    foreach ( QString resultFile, mResultFiles ){
+        QFile readFile( resultFile );
+        if ( resultFile != mCombinedOutputFileName && readFile.open(QIODevice::ReadOnly) ){
+            QXmlStreamReader reader(&readFile);
+            appendToXml(writer, reader, caseName);
+            readFile.close();
+        }
+    }
+    writer.writeEndDocument();
+    file.close();
+}
+
+void TestRunner::appendToXml(QXmlStreamWriter& writer, QXmlStreamReader& reader, QString& caseName)
+{
+    while (!reader.atEnd()) {
+        QXmlStreamReader::TokenType type = reader.readNext();
+        if ( type == QXmlStreamReader::StartDocument  || 
+             type == QXmlStreamReader::EndDocument ){
+            // Ignored
+        } else if ( reader.name() == testCaseElement ){
+            if ( type == QXmlStreamReader::StartElement ){
+                QString tempCaseName = reader.attributes().value(nameAttr).toString();
+                if ( caseName.isEmpty() && type == QXmlStreamReader::StartElement){
+                    writer.writeStartElement(testCaseElement);
+                    writer.writeAttribute(nameAttr, mTestRunParams.at(0));
+                }
+                caseName = tempCaseName;
+            }  
+        } else if ( type == QXmlStreamReader::StartElement ) {
+            if ( reader.name() == testFunctionElement ){
+                QString tempFuncName = reader.attributes().value(nameAttr).toString();
+                if ( !tempFuncName.isEmpty() ){
+                    writer.writeStartElement(testFunctionElement);
+                    writer.writeAttribute(nameAttr, caseName + "::" + tempFuncName);
+                }
+            } else {
+                writer.writeCurrentToken( reader );
+            }
+        } else {
+            writer.writeCurrentToken( reader );
+        }
+    }
+}