halfway in the middle of the reporting change
This commit is contained in:
parent
68a2888d35
commit
e5510f13d0
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,3 +11,4 @@ moc_*.*
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
hydra-runner.log
|
hydra-runner.log
|
||||||
jhw-test
|
jhw-test
|
||||||
|
.jhw-cache/
|
||||||
|
@ -26,7 +26,8 @@ guard 'jasmine-headless-webkit', :all_on_start => false do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def compile
|
def compile
|
||||||
system %{cd ext/jasmine-webkit-specrunner && ruby test.rb && ruby extconf.rb}
|
#system %{cd ext/jasmine-webkit-specrunner && ruby test.rb && ruby extconf.rb}
|
||||||
|
system %{cd ext/jasmine-webkit-specrunner && ruby extconf.rb}
|
||||||
end
|
end
|
||||||
|
|
||||||
compile
|
compile
|
||||||
|
@ -1,10 +1,54 @@
|
|||||||
#include "ReportFileOutput.h"
|
#include "ReportFileOutput.h"
|
||||||
|
|
||||||
ReportFileOutput::ReportFileOutput() : QObject() {
|
using namespace std;
|
||||||
|
|
||||||
|
ReportFileOutput::ReportFileOutput() : QObject() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutput::reset() {
|
||||||
|
buffer = new stringstream();
|
||||||
|
|
||||||
|
outputIO = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReportFileOutput::passed(const QString &specDetail) {
|
void ReportFileOutput::passed(const QString &specDetail) {
|
||||||
*outputIO << "PASS||" << qPrintable(specDetail) << std::endl;
|
*outputIO << "PASS||" << qPrintable(specDetail) << std::endl;
|
||||||
successes.push(specDetail);
|
successes.push(specDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReportFileOutput::failed(const QString &specDetail) {
|
||||||
|
*outputIO << "FAIL||" << qPrintable(specDetail) << std::endl;
|
||||||
|
failures.push(specDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutput::errorLog(const QString &msg, int lineNumber, const QString &sourceID) {
|
||||||
|
*outputIO << "ERROR||" << qPrintable(msg) << "||" << qPrintable(sourceID) << ":" << lineNumber << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutput::consoleLog(const QString &msg) {
|
||||||
|
*outputIO << "CONSOLE||" << qPrintable(msg) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutput::internalLog(const QString &, const QString &) {}
|
||||||
|
void ReportFileOutput::logSpecFilename(const QString &) {}
|
||||||
|
void ReportFileOutput::logSpecResult(const QString &) {}
|
||||||
|
|
||||||
|
void ReportFileOutput::reportFailure(const QString &totalTests, const QString &failedTests, const QString &duration) {
|
||||||
|
reportTotals(totalTests, failedTests, duration, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutput::reportSuccess(const QString &totalTests, const QString &failedTests, const QString &duration) {
|
||||||
|
reportTotals(totalTests, failedTests, duration, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutput::reportSuccessWithJSErrors(const QString &totalTests, const QString &failedTests, const QString &duration) {
|
||||||
|
reportTotals(totalTests, failedTests, duration, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutput::reportTotals(const QString &totalTests, const QString &failedTests, const QString &duration, bool hasJavaScriptError) {
|
||||||
|
*outputIO << "TOTAL||" << qPrintable(totalTests) << "||" << qPrintable(failedTests) << "||" << qPrintable(duration) << "||";
|
||||||
|
*outputIO << (hasJavaScriptError ? "T" : "F");
|
||||||
|
*outputIO << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <QStack>
|
#include <QStack>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
class ReportFileOutput : public QObject {
|
class ReportFileOutput : public QObject {
|
||||||
public:
|
public:
|
||||||
@ -21,9 +24,14 @@ class ReportFileOutput : public QObject {
|
|||||||
void reportSuccess(const QString &totalTests, const QString &failedTests, const QString &duration);
|
void reportSuccess(const QString &totalTests, const QString &failedTests, const QString &duration);
|
||||||
void reportSuccessWithJSErrors(const QString &totalTests, const QString &failedTests, const QString &duration);
|
void reportSuccessWithJSErrors(const QString &totalTests, const QString &failedTests, const QString &duration);
|
||||||
|
|
||||||
std::ostream *outputIO;
|
void reset();
|
||||||
|
|
||||||
|
stringstream *buffer;
|
||||||
|
stringstream *outputIO;
|
||||||
QStack<QString> successes;
|
QStack<QString> successes;
|
||||||
QStack<QString> failures;
|
QStack<QString> failures;
|
||||||
|
private:
|
||||||
|
void reportTotals(const QString &totalTests, const QString &failedTests, const QString &duration, bool hasJavaScriptError);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,11 +23,66 @@ void ReportFileOutputTest::testFailed() {
|
|||||||
ReportFileOutput output;
|
ReportFileOutput output;
|
||||||
|
|
||||||
output.outputIO = &buffer;
|
output.outputIO = &buffer;
|
||||||
output.passed("test||done||file.js:23");
|
output.failed("test||done||file.js:23");
|
||||||
QVERIFY(buffer.str() == "FAIL||test||done||file.js:23\n");
|
QVERIFY(buffer.str() == "FAIL||test||done||file.js:23\n");
|
||||||
QVERIFY(output.successes.size() == 0);
|
QVERIFY(output.successes.size() == 0);
|
||||||
QVERIFY(output.failures.size() == 1);
|
QVERIFY(output.failures.size() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReportFileOutputTest::testErrorLog() {
|
||||||
|
stringstream buffer;
|
||||||
|
ReportFileOutput output;
|
||||||
|
|
||||||
|
output.outputIO = &buffer;
|
||||||
|
output.errorLog("JS Error", 23, "file.js");
|
||||||
|
QVERIFY(buffer.str() == "ERROR||JS Error||file.js:23\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutputTest::testConsoleLog() {
|
||||||
|
stringstream buffer;
|
||||||
|
ReportFileOutput output;
|
||||||
|
|
||||||
|
output.outputIO = &buffer;
|
||||||
|
output.consoleLog("Console");
|
||||||
|
QVERIFY(buffer.str() == "CONSOLE||Console\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutputTest::testStubMethods() {
|
||||||
|
stringstream buffer;
|
||||||
|
ReportFileOutput output;
|
||||||
|
|
||||||
|
output.outputIO = &buffer;
|
||||||
|
output.internalLog("Internal", "Log");
|
||||||
|
output.logSpecFilename("Filename");
|
||||||
|
output.logSpecResult("REsult");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutputTest::testReportFailure() {
|
||||||
|
stringstream buffer;
|
||||||
|
ReportFileOutput output;
|
||||||
|
|
||||||
|
output.outputIO = &buffer;
|
||||||
|
output.reportFailure("5", "2", "1.5");
|
||||||
|
QVERIFY(buffer.str() == "TOTAL||5||2||1.5||F\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutputTest::testReportSuccess() {
|
||||||
|
stringstream buffer;
|
||||||
|
ReportFileOutput output;
|
||||||
|
|
||||||
|
output.outputIO = &buffer;
|
||||||
|
output.reportSuccess("5", "0", "1.5");
|
||||||
|
QVERIFY(buffer.str() == "TOTAL||5||0||1.5||F\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportFileOutputTest::testReportSuccessWithJSErrors() {
|
||||||
|
stringstream buffer;
|
||||||
|
ReportFileOutput output;
|
||||||
|
|
||||||
|
output.outputIO = &buffer;
|
||||||
|
output.reportSuccessWithJSErrors("5", "0", "1.5");
|
||||||
|
QVERIFY(buffer.str() == "TOTAL||5||0||1.5||T\n");
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(ReportFileOutputTest);
|
QTEST_MAIN(ReportFileOutputTest);
|
||||||
|
|
||||||
|
@ -15,6 +15,12 @@ class ReportFileOutputTest : public QObject {
|
|||||||
private slots:
|
private slots:
|
||||||
void testPassed();
|
void testPassed();
|
||||||
void testFailed();
|
void testFailed();
|
||||||
|
void testErrorLog();
|
||||||
|
void testConsoleLog();
|
||||||
|
void testStubMethods();
|
||||||
|
void testReportFailure();
|
||||||
|
void testReportSuccess();
|
||||||
|
void testReportSuccessWithJSErrors();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,197 +7,195 @@
|
|||||||
|
|
||||||
#include "Runner.h"
|
#include "Runner.h"
|
||||||
|
|
||||||
Runner::Runner() : QObject()
|
using namespace std;
|
||||||
, m_runs(0)
|
|
||||||
, hasErrors(false)
|
Runner::Runner() : QObject()
|
||||||
, usedConsole(false)
|
, m_runs(0)
|
||||||
, isFinished(false)
|
, hasErrors(false)
|
||||||
, didFail(false) {
|
, usedConsole(false)
|
||||||
m_page.settings()->enablePersistentStorage();
|
, isFinished(false)
|
||||||
connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(watch(bool)));
|
, didFail(false) {
|
||||||
connect(&m_page, SIGNAL(consoleLog(QString, int, QString)), this, SLOT(errorLog(QString, int, QString)));
|
m_page.settings()->enablePersistentStorage();
|
||||||
connect(&m_page, SIGNAL(internalLog(QString, QString)), this, SLOT(internalLog(QString, QString)));
|
connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(watch(bool)));
|
||||||
connect(m_page.mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(addJHW()));
|
connect(&m_page, SIGNAL(consoleLog(QString, int, QString)), this, SLOT(errorLog(QString, int, QString)));
|
||||||
|
connect(&m_page, SIGNAL(internalLog(QString, QString)), this, SLOT(internalLog(QString, QString)));
|
||||||
|
connect(m_page.mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(addJHW()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::addFile(const QString &spec) {
|
||||||
|
runnerFiles.enqueue(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::go()
|
||||||
|
{
|
||||||
|
m_ticker.stop();
|
||||||
|
m_page.setPreferredContentsSize(QSize(1024, 600));
|
||||||
|
addJHW();
|
||||||
|
loadSpec();
|
||||||
|
}
|
||||||
|
void Runner::addJHW()
|
||||||
|
{
|
||||||
|
m_page.mainFrame()->addToJavaScriptWindowObject("JHW", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::loadSpec()
|
||||||
|
{
|
||||||
|
m_page.mainFrame()->load(runnerFiles.dequeue());
|
||||||
|
m_ticker.start(200, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Runner::watch(bool ok)
|
||||||
|
{
|
||||||
|
if (!ok) {
|
||||||
|
std::cerr << "Can't load " << qPrintable(m_page.mainFrame()->url().toString()) << ", the file may be broken." << std::endl;
|
||||||
|
std::cerr << "Out of curiosity, did your tests try to submit a form and you haven't prevented that?" << std::endl;
|
||||||
|
std::cerr << "Try running your tests in your browser with the Jasmine server and see what happens." << std::endl;
|
||||||
|
QApplication::instance()->exit(1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Runner::addFile(const QString &spec) {
|
m_ticker.start(200, this);
|
||||||
runnerFiles.enqueue(spec);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::go()
|
bool Runner::hasElement(const char *select)
|
||||||
{
|
{
|
||||||
m_ticker.stop();
|
return !m_page.mainFrame()->findFirstElement(select).isNull();
|
||||||
m_page.setPreferredContentsSize(QSize(1024, 600));
|
}
|
||||||
addJHW();
|
|
||||||
loadSpec();
|
|
||||||
}
|
|
||||||
void Runner::addJHW()
|
|
||||||
{
|
|
||||||
m_page.mainFrame()->addToJavaScriptWindowObject("JHW", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::loadSpec()
|
void Runner::setColors(bool colors) {
|
||||||
{
|
consoleOutput.showColors = colors;
|
||||||
m_page.mainFrame()->load(runnerFiles.dequeue());
|
}
|
||||||
m_ticker.start(200, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::watch(bool ok)
|
void Runner::reportFile(const QString &file) {
|
||||||
{
|
reportFileName = file;
|
||||||
if (!ok) {
|
}
|
||||||
std::cerr << "Can't load " << qPrintable(m_page.mainFrame()->url().toString()) << ", the file may be broken." << std::endl;
|
|
||||||
std::cerr << "Out of curiosity, did your tests try to submit a form and you haven't prevented that?" << std::endl;
|
|
||||||
std::cerr << "Try running your tests in your browser with the Jasmine server and see what happens." << std::endl;
|
|
||||||
QApplication::instance()->exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ticker.start(200, this);
|
bool Runner::hasError() {
|
||||||
}
|
return hasErrors;
|
||||||
|
}
|
||||||
|
|
||||||
bool Runner::hasElement(const char *select)
|
void Runner::specPassed(const QString &specDetail) {
|
||||||
{
|
consoleOutput.passed(specDetail);
|
||||||
return !m_page.mainFrame()->findFirstElement(select).isNull();
|
reportFileOutput.passed(specDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Runner::setColors(bool colors)
|
void Runner::specFailed(const QString &specDetail) {
|
||||||
{
|
consoleOutput.failed(specDetail);
|
||||||
consoleOutput.showColors = colors;
|
reportFileOutput.failed(specDetail);
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::reportFile(const QString &file)
|
didFail = true;
|
||||||
{
|
failedSpecs.push(specDetail);
|
||||||
reportFilename = file;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool Runner::hasError() {
|
void Runner::errorLog(const QString &msg, int lineNumber, const QString &sourceID)
|
||||||
return hasErrors;
|
{
|
||||||
}
|
consoleOutput.errorLog(msg, lineNumber, sourceID);
|
||||||
|
reportFileOutput.errorLog(msg, lineNumber, sourceID);
|
||||||
|
|
||||||
void Runner::specPassed()
|
hasErrors = true;
|
||||||
{
|
m_runs = 0;
|
||||||
consoleOutput.passed("");
|
m_ticker.start(200, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Runner::specFailed(const QString &specDetail)
|
void Runner::internalLog(const QString ¬e, const QString &msg) {
|
||||||
{
|
consoleOutput.internalLog(note, msg);
|
||||||
consoleOutput.failed("");
|
reportFileOutput.internalLog(note, msg);
|
||||||
didFail = true;
|
}
|
||||||
failedSpecs.push(specDetail);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::errorLog(const QString &msg, int lineNumber, const QString &sourceID)
|
void Runner::log(const QString &msg)
|
||||||
{
|
{
|
||||||
consoleOutput.errorLog(msg, lineNumber, sourceID);
|
usedConsole = true;
|
||||||
|
consoleOutput.consoleLog(msg);
|
||||||
|
reportFileOutput.consoleLog(msg);
|
||||||
|
}
|
||||||
|
|
||||||
hasErrors = true;
|
void Runner::leavePageAttempt(const QString &msg)
|
||||||
m_runs = 0;
|
{
|
||||||
m_ticker.start(200, this);
|
consoleOutput.internalLog("error", msg);
|
||||||
}
|
m_page.oneFalseConfirm();
|
||||||
|
hasErrors = true;
|
||||||
|
}
|
||||||
|
|
||||||
void Runner::internalLog(const QString ¬e, const QString &msg) {
|
void Runner::printName(const QString &name)
|
||||||
consoleOutput.internalLog(note, msg);
|
{
|
||||||
}
|
consoleOutput.logSpecFilename(name);
|
||||||
|
}
|
||||||
|
|
||||||
void Runner::log(const QString &msg)
|
void Runner::printResult(const QString &result)
|
||||||
{
|
{
|
||||||
usedConsole = true;
|
consoleOutput.logSpecResult(result);
|
||||||
consoleOutput.consoleLog(msg);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::leavePageAttempt(const QString &msg)
|
void Runner::finishSuite(const QString &duration, const QString &total, const QString& failed)
|
||||||
{
|
{
|
||||||
consoleOutput.internalLog("error", msg);
|
if (didFail) {
|
||||||
m_page.oneFalseConfirm();
|
consoleOutput.reportFailure(total, failed, duration);
|
||||||
hasErrors = true;
|
reportFileOutput.reportFailure(total, failed, duration);
|
||||||
}
|
} else {
|
||||||
|
if (hasErrors) {
|
||||||
void Runner::printName(const QString &name)
|
consoleOutput.reportSuccessWithJSErrors(total, failed, duration);
|
||||||
{
|
reportFileOutput.reportSuccessWithJSErrors(total, failed, duration);
|
||||||
consoleOutput.logSpecFilename(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::printResult(const QString &result)
|
|
||||||
{
|
|
||||||
consoleOutput.logSpecResult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Runner::finishSuite(const QString &duration, const QString &total, const QString& failed)
|
|
||||||
{
|
|
||||||
if (didFail) {
|
|
||||||
consoleOutput.reportFailure(total, failed, duration);
|
|
||||||
} else {
|
} else {
|
||||||
if (hasErrors) {
|
consoleOutput.reportSuccess(total, failed, duration);
|
||||||
consoleOutput.reportSuccessWithJSErrors(total, failed, duration);
|
reportFileOutput.reportSuccess(total, failed, duration);
|
||||||
} else {
|
|
||||||
consoleOutput.reportSuccess(total, failed, duration);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reportFilename.isEmpty()) {
|
|
||||||
QFile reportFH(reportFilename);
|
|
||||||
|
|
||||||
if (reportFH.open(QFile::WriteOnly)) {
|
|
||||||
QTextStream report(&reportFH);
|
|
||||||
report << qPrintable(total) << "/" << qPrintable(failed) << "/";
|
|
||||||
report << (usedConsole ? "T" : "F");
|
|
||||||
report << "/" << qPrintable(duration) << "\n";
|
|
||||||
|
|
||||||
QString failedSpec;
|
|
||||||
|
|
||||||
while (!failedSpecs.isEmpty()) {
|
|
||||||
failedSpec = failedSpecs.pop();
|
|
||||||
report << qPrintable(failedSpec) << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
reportFH.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isFinished = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Runner::timerEvent(QTimerEvent *event)
|
if (!reportFileName.isEmpty()) {
|
||||||
{
|
QFile outputFile(reportFileName);
|
||||||
++m_runs;
|
outputFile.open(QIODevice::WriteOnly);
|
||||||
|
|
||||||
if (event->timerId() != m_ticker.timerId())
|
QTextStream ts(&outputFile);
|
||||||
return;
|
|
||||||
|
|
||||||
if (hasErrors && m_runs > 2)
|
ts << reportFileOutput.outputIO->str().c_str();
|
||||||
QApplication::instance()->exit(1);
|
|
||||||
|
|
||||||
if (isFinished) {
|
outputFile.close();
|
||||||
int exitCode = 0;
|
}
|
||||||
if (didFail || hasErrors) {
|
|
||||||
exitCode = 1;
|
isFinished = true;
|
||||||
} else {
|
}
|
||||||
if (usedConsole) {
|
|
||||||
exitCode = 2;
|
void Runner::timerEvent(QTimerEvent *event)
|
||||||
}
|
{
|
||||||
|
++m_runs;
|
||||||
|
|
||||||
|
if (event->timerId() != m_ticker.timerId())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (hasErrors && m_runs > 2)
|
||||||
|
QApplication::instance()->exit(1);
|
||||||
|
|
||||||
|
if (isFinished) {
|
||||||
|
int exitCode = 0;
|
||||||
|
if (didFail || hasErrors) {
|
||||||
|
exitCode = 1;
|
||||||
|
} else {
|
||||||
|
if (usedConsole) {
|
||||||
|
exitCode = 2;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool runAgain = true;
|
bool runAgain = true;
|
||||||
|
|
||||||
if (runnerFiles.count() == 0) {
|
if (runnerFiles.count() == 0) {
|
||||||
|
runAgain = false;
|
||||||
|
} else {
|
||||||
|
if (exitCode == 1) {
|
||||||
runAgain = false;
|
runAgain = false;
|
||||||
} else {
|
|
||||||
if (exitCode == 1) {
|
|
||||||
runAgain = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runAgain) {
|
|
||||||
isFinished = false;
|
|
||||||
loadSpec();
|
|
||||||
} else {
|
|
||||||
QApplication::instance()->exit(exitCode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_runs > 30) {
|
if (runAgain) {
|
||||||
std::cout << "WARNING: too many runs and the test is still not finished!" << std::endl;
|
isFinished = false;
|
||||||
QApplication::instance()->exit(1);
|
loadSpec();
|
||||||
|
} else {
|
||||||
|
QApplication::instance()->exit(exitCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_runs > 30) {
|
||||||
|
std::cout << "WARNING: too many runs and the test is still not finished!" << std::endl;
|
||||||
|
QApplication::instance()->exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -6,53 +6,57 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
#include <QQueue>
|
#include <QQueue>
|
||||||
|
|
||||||
#include "Page.h"
|
#include "Page.h"
|
||||||
#include "ConsoleOutput.h"
|
#include "ConsoleOutput.h"
|
||||||
#include "ReportFileOutput.h"
|
#include "ReportFileOutput.h"
|
||||||
|
|
||||||
class Runner: public QObject {
|
using namespace std;
|
||||||
Q_OBJECT
|
|
||||||
public:
|
class Runner: public QObject {
|
||||||
Runner();
|
Q_OBJECT
|
||||||
void setColors(bool colors);
|
public:
|
||||||
void reportFile(const QString &file);
|
Runner();
|
||||||
void addFile(const QString &spec);
|
void setColors(bool colors);
|
||||||
void go();
|
void reportFile(const QString &file);
|
||||||
|
void addFile(const QString &spec);
|
||||||
|
void go();
|
||||||
public slots:
|
public slots:
|
||||||
void log(const QString &msg);
|
void log(const QString &msg);
|
||||||
bool hasError();
|
bool hasError();
|
||||||
void leavePageAttempt(const QString &msg);
|
void leavePageAttempt(const QString &msg);
|
||||||
void specPassed();
|
void specPassed(const QString &specDetail);
|
||||||
void specFailed(const QString &specDetail);
|
void specFailed(const QString &specDetail);
|
||||||
void printName(const QString &name);
|
void printName(const QString &name);
|
||||||
void printResult(const QString &result);
|
void printResult(const QString &result);
|
||||||
void finishSuite(const QString &duration, const QString &total, const QString& failed);
|
void finishSuite(const QString &duration, const QString &total, const QString& failed);
|
||||||
private slots:
|
private slots:
|
||||||
void watch(bool ok);
|
void watch(bool ok);
|
||||||
void errorLog(const QString &msg, int lineNumber, const QString &sourceID);
|
void errorLog(const QString &msg, int lineNumber, const QString &sourceID);
|
||||||
void internalLog(const QString ¬e, const QString &msg);
|
void internalLog(const QString ¬e, const QString &msg);
|
||||||
void addJHW();
|
void addJHW();
|
||||||
protected:
|
protected:
|
||||||
bool hasElement(const char *select);
|
bool hasElement(const char *select);
|
||||||
void timerEvent(QTimerEvent *event);
|
void timerEvent(QTimerEvent *event);
|
||||||
private:
|
private:
|
||||||
Page m_page;
|
Page m_page;
|
||||||
QBasicTimer m_ticker;
|
QBasicTimer m_ticker;
|
||||||
int m_runs;
|
int m_runs;
|
||||||
bool hasErrors;
|
bool hasErrors;
|
||||||
bool usedConsole;
|
bool usedConsole;
|
||||||
bool isFinished;
|
bool isFinished;
|
||||||
bool didFail;
|
bool didFail;
|
||||||
QQueue<QString> runnerFiles;
|
QQueue<QString> runnerFiles;
|
||||||
QString reportFilename;
|
QStack<QString> failedSpecs;
|
||||||
QStack<QString> failedSpecs;
|
|
||||||
|
|
||||||
ConsoleOutput consoleOutput;
|
ConsoleOutput consoleOutput;
|
||||||
ReportFileOutput reportFileOutput;
|
ReportFileOutput reportFileOutput;
|
||||||
|
|
||||||
void loadSpec();
|
QString reportFileName;
|
||||||
};
|
|
||||||
|
void loadSpec();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,11 +56,13 @@ int main(int argc, char** argv)
|
|||||||
app.setApplicationName("jasmine-headless-webkit");
|
app.setApplicationName("jasmine-headless-webkit");
|
||||||
Runner runner;
|
Runner runner;
|
||||||
runner.setColors(showColors);
|
runner.setColors(showColors);
|
||||||
|
|
||||||
runner.reportFile(reporter);
|
runner.reportFile(reporter);
|
||||||
|
|
||||||
for (index = optind; index < argc; index++) {
|
for (index = optind; index < argc; index++) {
|
||||||
runner.addFile(QString::fromLocal8Bit(argv[index]));
|
runner.addFile(QString::fromLocal8Bit(argv[index]));
|
||||||
}
|
}
|
||||||
|
|
||||||
runner.go();
|
runner.go();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
@ -8,19 +8,19 @@ class window.HeadlessReporterResult
|
|||||||
@results.push(message)
|
@results.push(message)
|
||||||
print: ->
|
print: ->
|
||||||
output = @name
|
output = @name
|
||||||
bestChoice = this._findSpecLine()
|
bestChoice = HeadlessReporterResult.findSpecLine(@splitName)
|
||||||
output += " (#{bestChoice.file}:#{bestChoice.lineNumber})" if bestChoice.file
|
output += " (#{bestChoice.file}:#{bestChoice.lineNumber})" if bestChoice.file
|
||||||
|
|
||||||
JHW.printName(output)
|
JHW.printName(output)
|
||||||
for result in @results
|
for result in @results
|
||||||
JHW.printResult(result)
|
JHW.printResult(result)
|
||||||
_findSpecLine: ->
|
@findSpecLine: (splitName) ->
|
||||||
bestChoice = { accuracy: 0, file: null, lineNumber: null }
|
bestChoice = { accuracy: 0, file: null, lineNumber: null }
|
||||||
|
|
||||||
for file, lines of HeadlessReporterResult.specLineNumbers
|
for file, lines of HeadlessReporterResult.specLineNumbers
|
||||||
index = 0
|
index = 0
|
||||||
lineNumber = 0
|
lineNumber = 0
|
||||||
while newLineNumberInfo = lines[@splitName[index]]
|
while newLineNumberInfo = lines[splitName[index]]
|
||||||
if newLineNumberInfo.length == 0
|
if newLineNumberInfo.length == 0
|
||||||
lineNumber = newLineNumberInfo[0]
|
lineNumber = newLineNumberInfo[0]
|
||||||
else
|
else
|
||||||
@ -40,14 +40,20 @@ class window.HeadlessReporterResult
|
|||||||
|
|
||||||
jasmine.Suite.prototype.getSuiteSplitName = ->
|
jasmine.Suite.prototype.getSuiteSplitName = ->
|
||||||
parts = if @parentSuite then @parentSuite.getSuiteSplitName() else []
|
parts = if @parentSuite then @parentSuite.getSuiteSplitName() else []
|
||||||
parts.push(@description)
|
parts.push(String(@description).replace(/[\n\r]/g, ' '))
|
||||||
parts
|
parts
|
||||||
|
|
||||||
jasmine.Spec.prototype.getSpecSplitName = ->
|
jasmine.Spec.prototype.getSpecSplitName = ->
|
||||||
parts = @suite.getSuiteSplitName()
|
parts = @suite.getSuiteSplitName()
|
||||||
parts.push(@description)
|
parts.push(String(@description).replace(/[\n\r]/g, ' '))
|
||||||
parts
|
parts
|
||||||
|
|
||||||
|
jasmine.Spec.prototype.getJHWSpecInformation = ->
|
||||||
|
parts = this.getSpecSplitName()
|
||||||
|
specLineInfo = HeadlessReporterResult.findSpecLine(parts)
|
||||||
|
parts.push("#{specLineInfo.file}:#{specLineInfo.lineNumber}")
|
||||||
|
parts.join("||")
|
||||||
|
|
||||||
class jasmine.HeadlessReporter
|
class jasmine.HeadlessReporter
|
||||||
constructor: (@callback = null) ->
|
constructor: (@callback = null) ->
|
||||||
@results = []
|
@results = []
|
||||||
@ -61,27 +67,31 @@ class jasmine.HeadlessReporter
|
|||||||
|
|
||||||
this.callback() if @callback
|
this.callback() if @callback
|
||||||
JHW.finishSuite((new Date() - @startTime) / 1000.0, @length, @failedCount)
|
JHW.finishSuite((new Date() - @startTime) / 1000.0, @length, @failedCount)
|
||||||
|
|
||||||
reportRunnerStarting: (runner) ->
|
reportRunnerStarting: (runner) ->
|
||||||
@startTime = new Date()
|
@startTime = new Date()
|
||||||
|
|
||||||
reportSpecResults: (spec) ->
|
reportSpecResults: (spec) ->
|
||||||
return if this.hasError()
|
return if this.hasError()
|
||||||
|
|
||||||
results = spec.results()
|
results = spec.results()
|
||||||
@length++
|
@length++
|
||||||
if results.passed()
|
if results.passed()
|
||||||
JHW.specPassed()
|
JHW.specPassed(spec.getJHWSpecInformation())
|
||||||
else
|
else
|
||||||
JHW.specFailed(spec.getSpecSplitName().join('||'))
|
JHW.specFailed(spec.getJHWSpecInformation())
|
||||||
@failedCount++
|
@failedCount++
|
||||||
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName())
|
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName())
|
||||||
for result in results.getItems()
|
for result in results.getItems()
|
||||||
if result.type == 'expect' and !result.passed_
|
if result.type == 'expect' and !result.passed_
|
||||||
failureResult.addResult(result.message)
|
failureResult.addResult(result.message)
|
||||||
@results.push(failureResult)
|
@results.push(failureResult)
|
||||||
|
|
||||||
reportSpecStarting: (spec) ->
|
reportSpecStarting: (spec) ->
|
||||||
if this.hasError()
|
if this.hasError()
|
||||||
spec.finish()
|
spec.finish()
|
||||||
spec.suite.finish()
|
spec.suite.finish()
|
||||||
|
|
||||||
reportSuiteResults: (suite) ->
|
reportSuiteResults: (suite) ->
|
||||||
hasError: ->
|
hasError: ->
|
||||||
JHW.hasError()
|
JHW.hasError()
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
HeadlessReporterResult.prototype.print = function() {
|
HeadlessReporterResult.prototype.print = function() {
|
||||||
var bestChoice, output, result, _i, _len, _ref, _results;
|
var bestChoice, output, result, _i, _len, _ref, _results;
|
||||||
output = this.name;
|
output = this.name;
|
||||||
bestChoice = this._findSpecLine();
|
bestChoice = HeadlessReporterResult.findSpecLine(this.splitName);
|
||||||
if (bestChoice.file) {
|
if (bestChoice.file) {
|
||||||
output += " (" + bestChoice.file + ":" + bestChoice.lineNumber + ")";
|
output += " (" + bestChoice.file + ":" + bestChoice.lineNumber + ")";
|
||||||
}
|
}
|
||||||
@ -27,7 +27,7 @@
|
|||||||
}
|
}
|
||||||
return _results;
|
return _results;
|
||||||
};
|
};
|
||||||
HeadlessReporterResult.prototype._findSpecLine = function() {
|
HeadlessReporterResult.findSpecLine = function(splitName) {
|
||||||
var bestChoice, file, index, lastLine, line, lineNumber, lines, newLineNumberInfo, _i, _len, _ref;
|
var bestChoice, file, index, lastLine, line, lineNumber, lines, newLineNumberInfo, _i, _len, _ref;
|
||||||
bestChoice = {
|
bestChoice = {
|
||||||
accuracy: 0,
|
accuracy: 0,
|
||||||
@ -39,7 +39,7 @@
|
|||||||
lines = _ref[file];
|
lines = _ref[file];
|
||||||
index = 0;
|
index = 0;
|
||||||
lineNumber = 0;
|
lineNumber = 0;
|
||||||
while (newLineNumberInfo = lines[this.splitName[index]]) {
|
while (newLineNumberInfo = lines[splitName[index]]) {
|
||||||
if (newLineNumberInfo.length === 0) {
|
if (newLineNumberInfo.length === 0) {
|
||||||
lineNumber = newLineNumberInfo[0];
|
lineNumber = newLineNumberInfo[0];
|
||||||
} else {
|
} else {
|
||||||
@ -70,15 +70,22 @@
|
|||||||
jasmine.Suite.prototype.getSuiteSplitName = function() {
|
jasmine.Suite.prototype.getSuiteSplitName = function() {
|
||||||
var parts;
|
var parts;
|
||||||
parts = this.parentSuite ? this.parentSuite.getSuiteSplitName() : [];
|
parts = this.parentSuite ? this.parentSuite.getSuiteSplitName() : [];
|
||||||
parts.push(this.description);
|
parts.push(String(this.description).replace(/[\n\r]/g, ' '));
|
||||||
return parts;
|
return parts;
|
||||||
};
|
};
|
||||||
jasmine.Spec.prototype.getSpecSplitName = function() {
|
jasmine.Spec.prototype.getSpecSplitName = function() {
|
||||||
var parts;
|
var parts;
|
||||||
parts = this.suite.getSuiteSplitName();
|
parts = this.suite.getSuiteSplitName();
|
||||||
parts.push(this.description);
|
parts.push(String(this.description).replace(/[\n\r]/g, ' '));
|
||||||
return parts;
|
return parts;
|
||||||
};
|
};
|
||||||
|
jasmine.Spec.prototype.getJHWSpecInformation = function() {
|
||||||
|
var parts, specLineInfo;
|
||||||
|
parts = this.getSpecSplitName();
|
||||||
|
specLineInfo = HeadlessReporterResult.findSpecLine(parts);
|
||||||
|
parts.push("" + specLineInfo.file + ":" + specLineInfo.lineNumber);
|
||||||
|
return parts.join("||");
|
||||||
|
};
|
||||||
jasmine.HeadlessReporter = (function() {
|
jasmine.HeadlessReporter = (function() {
|
||||||
function HeadlessReporter(callback) {
|
function HeadlessReporter(callback) {
|
||||||
this.callback = callback != null ? callback : null;
|
this.callback = callback != null ? callback : null;
|
||||||
@ -112,9 +119,9 @@
|
|||||||
results = spec.results();
|
results = spec.results();
|
||||||
this.length++;
|
this.length++;
|
||||||
if (results.passed()) {
|
if (results.passed()) {
|
||||||
return JHW.specPassed();
|
return JHW.specPassed(spec.getJHWSpecInformation());
|
||||||
} else {
|
} else {
|
||||||
JHW.specFailed(spec.getSpecSplitName().join('||'));
|
JHW.specFailed(spec.getJHWSpecInformation());
|
||||||
this.failedCount++;
|
this.failedCount++;
|
||||||
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName());
|
failureResult = new HeadlessReporterResult(spec.getFullName(), spec.getSpecSplitName());
|
||||||
_ref = results.getItems();
|
_ref = results.getItems();
|
||||||
|
@ -9,11 +9,8 @@ describe 'HeadlessReporterResult', ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
it 'should find the best spec lines', ->
|
it 'should find the best spec lines', ->
|
||||||
result = new HeadlessReporterResult('test', [ 'name', 'of', 'test' ])
|
expect(HeadlessReporterResult.findSpecLine([ 'name', 'of', 'test' ]).lineNumber).toEqual(3)
|
||||||
expect(result._findSpecLine().lineNumber).toEqual(3)
|
expect(HeadlessReporterResult.findSpecLine([ 'other', 'of', 'test' ]).lineNumber).toEqual(10)
|
||||||
|
|
||||||
result = new HeadlessReporterResult('test', [ 'other', 'of', 'test' ])
|
|
||||||
expect(result._findSpecLine().lineNumber).toEqual(10)
|
|
||||||
|
|
||||||
describe 'jasmine.HeadlessReporter', ->
|
describe 'jasmine.HeadlessReporter', ->
|
||||||
reporter = null
|
reporter = null
|
||||||
@ -36,3 +33,31 @@ describe 'jasmine.HeadlessReporter', ->
|
|||||||
expect(spec.finish).toHaveBeenCalled()
|
expect(spec.finish).toHaveBeenCalled()
|
||||||
expect(suite.finish).toHaveBeenCalled()
|
expect(suite.finish).toHaveBeenCalled()
|
||||||
|
|
||||||
|
describe 'jasmine.Suite.prototype.getSuiteSplitName', ->
|
||||||
|
it 'should flatten the description', ->
|
||||||
|
suite = new jasmine.Suite({});
|
||||||
|
suite.description = "hello\ngoodbye\n";
|
||||||
|
expect(suite.getSuiteSplitName()).toEqual([ "hello goodbye " ])
|
||||||
|
|
||||||
|
it 'should not fail on missing description', ->
|
||||||
|
suite = new jasmine.Suite({});
|
||||||
|
suite.description = 1;
|
||||||
|
expect(suite.getSuiteSplitName()).toEqual([ "1" ])
|
||||||
|
|
||||||
|
describe 'jasmine.Spec.prototype.getSuiteSplitName', ->
|
||||||
|
it 'should flatten the description', ->
|
||||||
|
spec = new jasmine.Spec({}, {});
|
||||||
|
spec.suite = {
|
||||||
|
getSuiteSplitName: -> []
|
||||||
|
}
|
||||||
|
spec.description = "hello\ngoodbye\n";
|
||||||
|
expect(spec.getSpecSplitName()).toEqual([ "hello goodbye " ])
|
||||||
|
|
||||||
|
it 'should not fail on missing description', ->
|
||||||
|
spec = new jasmine.Spec({}, {});
|
||||||
|
spec.suite = {
|
||||||
|
getSuiteSplitName: -> []
|
||||||
|
}
|
||||||
|
spec.description = 1
|
||||||
|
expect(spec.getSpecSplitName()).toEqual([ "1" ])
|
||||||
|
|
||||||
|
18
spec/lib/jasmine/headless/report_spec.rb
Normal file
18
spec/lib/jasmine/headless/report_spec.rb
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Jasmine::Headless::Report do
|
||||||
|
include FakeFS::SpecHelpers
|
||||||
|
|
||||||
|
describe '.load' do
|
||||||
|
context 'no file' do
|
||||||
|
it 'should raise an exception' do
|
||||||
|
expect { described_class.load(file) }.to raise_error(Errno::ENOENT)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'file' do
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user