From 795423beea4b9631ff3734eee9db12671af2754b Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sat, 7 Jul 2018 17:21:46 -0700 Subject: [PATCH 01/36] WIP. --- tools/auto-tester/CMakeLists.txt | 4 +- tools/auto-tester/src/Test.cpp | 21 +++++ tools/auto-tester/src/Test.h | 3 +- tools/auto-tester/src/TestSuiteCreator.cpp | 105 +++++++++++++++++++++ tools/auto-tester/src/TestSuiteCreator.h | 26 +++++ tools/auto-tester/src/ui/AutoTester.cpp | 4 + tools/auto-tester/src/ui/AutoTester.h | 2 +- tools/auto-tester/src/ui/AutoTester.ui | 27 ++++-- 8 files changed, 181 insertions(+), 11 deletions(-) create mode 100644 tools/auto-tester/src/TestSuiteCreator.cpp create mode 100644 tools/auto-tester/src/TestSuiteCreator.h diff --git a/tools/auto-tester/CMakeLists.txt b/tools/auto-tester/CMakeLists.txt index a2589bb760..1546a35f4c 100644 --- a/tools/auto-tester/CMakeLists.txt +++ b/tools/auto-tester/CMakeLists.txt @@ -5,7 +5,7 @@ project(${TARGET_NAME}) SET (CMAKE_AUTOUIC ON) SET (CMAKE_AUTOMOC ON) -setup_hifi_project (Core Widgets Network) +setup_hifi_project (Core Widgets Network Xml) link_hifi_libraries () # FIX: Qt was built with -reduce-relocations @@ -18,7 +18,7 @@ include_directories (${CMAKE_CURRENT_SOURCE_DIR}) include_directories (${Qt5Core_INCLUDE_DIRS}) include_directories (${Qt5Widgets_INCLUDE_DIRS}) -set (QT_LIBRARIES Qt5::Core Qt5::Widgets) +set (QT_LIBRARIES Qt5::Core Qt5::Widgets QT::Gui Qt5::Xml) if (WIN32) # Do not show Console diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 4f02544c12..8255d845f6 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -18,6 +18,7 @@ #include #include +#include "TestSuiteCreator.h" #include "ui/AutoTester.h" extern AutoTester* autoTester; @@ -821,6 +822,26 @@ void Test::createTestsOutline() { QMessageBox::information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created"); } +void Test::createTestRailTestSuite() { + QString previousSelection = testDirectory; + QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); + if (!parent.isNull() && parent.right(1) != "/") { + parent += "/"; + } + + testDirectory = + QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, QFileDialog::ShowDirsOnly); + + // If user cancelled then restore previous selection and return + if (testDirectory == "") { + testDirectory = previousSelection; + return; + } + + TestSuiteCreator testSuiteCreator; + testSuiteCreator.createTestSuite(testDirectory); +} + QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { imageDirectory = QDir(pathToImageDirectory); QStringList nameFilters; diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 5c6d3e5686..47786664fd 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -50,6 +50,7 @@ public: void createMDFile(const QString& topLevelDirectory); void createTestsOutline(); + void createTestRailTestSuite(); bool compareImageLists(bool isInteractiveMode, QProgressBar* progressBar); @@ -64,7 +65,7 @@ public: bool createTestResultsFolderPath(const QString& directory); void zipAndDeleteTestResultsFolder(); - bool isAValidDirectory(const QString& pathname); + static bool isAValidDirectory(const QString& pathname); QString extractPathFromTestsDown(const QString& fullPath); QString getExpectedImageDestinationDirectory(const QString& filename); QString getExpectedImagePartialSourceDirectory(const QString& filename); diff --git a/tools/auto-tester/src/TestSuiteCreator.cpp b/tools/auto-tester/src/TestSuiteCreator.cpp new file mode 100644 index 0000000000..0e3d9d52bd --- /dev/null +++ b/tools/auto-tester/src/TestSuiteCreator.cpp @@ -0,0 +1,105 @@ +// +// TestSuiteCreator.cpp +// +// Created by Nissim Hadar on 6 Jul 2018. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "TestSuiteCreator.h" +#include "Test.h" + +#include +#include +#include +#include + +void TestSuiteCreator::createTestSuite(const QString& testDirectory) { + QDomProcessingInstruction instruction = document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); + document.appendChild(instruction); + + // root element + QDomElement root = document.createElement("suite"); + document.appendChild(root); + + // id (empty seems to be OK) + QDomElement idElement = document.createElement("id"); + root.appendChild(idElement); + + // name - our tests are in "Rendering" + QDomElement nameElement = document.createElement("name"); + QDomText nameElementText = document.createTextNode("Rendering"); + nameElement.appendChild(nameElementText); + root.appendChild(nameElement); + + // We create a single section, within sections + QDomElement topLevelSections = document.createElement("sections"); + + QDomElement topLevelSection = document.createElement("section"); + + QDomElement suiteName = document.createElement("name"); + QDomText suiteNameElementElementText = document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString()); + suiteName.appendChild(suiteNameElementElementText); + topLevelSection.appendChild(suiteName); + + QDomElement secondLevelSections = document.createElement("sections"); + QDomElement tests = processDirectory(testDirectory, secondLevelSections); + topLevelSection.appendChild(tests); + + + topLevelSection.appendChild(secondLevelSections); + topLevelSections.appendChild(topLevelSection); + + root.appendChild(topLevelSections); + + // Write to file + const QString testRailsFilename{ "D:/t/TestRailSuite.xml" }; + QFile file(testRailsFilename); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not create XML file"); + exit(-1); + } + + QTextStream stream(&file); + stream << document.toString(); + + file.close(); + + QMessageBox::information(0, "Success", "TestRail XML file has been created"); +} + +QDomElement TestSuiteCreator::processDirectory(const QString& directory, const QDomElement& element) { + QDomElement result = element; + + // Loop over all entries in directory + QDirIterator it(directory.toStdString().c_str()); + while (it.hasNext()) { + QString directory = it.next(); + + // Only process directories + QDir dir; + if (Test::isAValidDirectory(directory)) { + // Ignore the utils directory + if (directory.right(5) == "utils") { + continue; + } + + // Create a section and process it + // The directory name appears after the last slash (we are assured there is at least 1). + QString directoryName = directory.right(directory.length() - directory.lastIndexOf("/") - 1); + + QDomElement sectionElement = document.createElement("section"); + + QDomElement sectionElementName = document.createElement("name"); + QDomText sectionElementNameText = document.createTextNode(directoryName); + sectionElementName.appendChild(sectionElementNameText); + sectionElement.appendChild(sectionElementName); + + result.appendChild(sectionElement); + } + } + + return result; +} \ No newline at end of file diff --git a/tools/auto-tester/src/TestSuiteCreator.h b/tools/auto-tester/src/TestSuiteCreator.h new file mode 100644 index 0000000000..3ecf046497 --- /dev/null +++ b/tools/auto-tester/src/TestSuiteCreator.h @@ -0,0 +1,26 @@ +// +// TestSuiteCreator.h +// +// Created by Nissim Hadar on 6 Jul 2018. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_test_suite_creator_h +#define hifi_test_suite_creator_h + +#include +#include +#include + +class TestSuiteCreator { +public: + void createTestSuite(const QString& testDirectory); + QDomElement processDirectory(const QString& directory, const QDomElement& element); +private: + QDomDocument document; +}; + +#endif // hifi_test_suite_creator_h \ No newline at end of file diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 079fa63a9d..76ae6c5385 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -68,6 +68,10 @@ void AutoTester::on_createTestsOutlineButton_clicked() { test->createTestsOutline(); } +void AutoTester::on_createTestRailTestSuiteButton_clicked() { + test->createTestRailTestSuite(); +} + // To toggle between show and hide // if (uState & ABS_AUTOHIDE) on_showTaskbarButton_clicked(); // else on_hideTaskbarButton_clicked(); diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index d47c4929c4..76b4741d9a 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -45,7 +45,7 @@ private slots: void on_createMDFileButton_clicked(); void on_createAllMDFilesButton_clicked(); void on_createTestsOutlineButton_clicked(); - + void on_createTestRailTestSuiteButton_clicked(); void on_hideTaskbarButton_clicked(); void on_showTaskbarButton_clicked(); diff --git a/tools/auto-tester/src/ui/AutoTester.ui b/tools/auto-tester/src/ui/AutoTester.ui index e12fc70e3f..ddc095ba23 100644 --- a/tools/auto-tester/src/ui/AutoTester.ui +++ b/tools/auto-tester/src/ui/AutoTester.ui @@ -7,7 +7,7 @@ 0 0 612 - 537 + 553 @@ -18,7 +18,7 @@ 380 - 430 + 450 101 40 @@ -44,7 +44,7 @@ 430 - 270 + 320 101 40 @@ -57,7 +57,7 @@ 330 - 110 + 170 220 40 @@ -70,7 +70,7 @@ 320 - 280 + 330 131 20 @@ -86,7 +86,7 @@ 320 - 330 + 380 255 23 @@ -99,7 +99,7 @@ 330 - 170 + 230 220 40 @@ -229,6 +229,19 @@ + + + + 330 + 90 + 220 + 40 + + + + Create TestRail Test Suite + + From 95a2d586c6e654667fe9c4cfdd1bb6c6d43efd8b Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sat, 7 Jul 2018 21:05:22 -0700 Subject: [PATCH 02/36] WIP. --- tools/auto-tester/src/TestSuiteCreator.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tools/auto-tester/src/TestSuiteCreator.cpp b/tools/auto-tester/src/TestSuiteCreator.cpp index 0e3d9d52bd..d1dc0ce281 100644 --- a/tools/auto-tester/src/TestSuiteCreator.cpp +++ b/tools/auto-tester/src/TestSuiteCreator.cpp @@ -25,8 +25,7 @@ void TestSuiteCreator::createTestSuite(const QString& testDirectory) { document.appendChild(root); // id (empty seems to be OK) - QDomElement idElement = document.createElement("id"); - root.appendChild(idElement); + root.appendChild(document.createElement("id")); // name - our tests are in "Rendering" QDomElement nameElement = document.createElement("name"); @@ -45,9 +44,7 @@ void TestSuiteCreator::createTestSuite(const QString& testDirectory) { topLevelSection.appendChild(suiteName); QDomElement secondLevelSections = document.createElement("sections"); - QDomElement tests = processDirectory(testDirectory, secondLevelSections); - topLevelSection.appendChild(tests); - + topLevelSection.appendChild(processDirectory(testDirectory, secondLevelSections)); topLevelSection.appendChild(secondLevelSections); topLevelSections.appendChild(topLevelSection); @@ -79,7 +76,6 @@ QDomElement TestSuiteCreator::processDirectory(const QString& directory, const Q QString directory = it.next(); // Only process directories - QDir dir; if (Test::isAValidDirectory(directory)) { // Ignore the utils directory if (directory.right(5) == "utils") { @@ -97,6 +93,9 @@ QDomElement TestSuiteCreator::processDirectory(const QString& directory, const Q sectionElementName.appendChild(sectionElementNameText); sectionElement.appendChild(sectionElementName); + QDomElement testsElement = document.createElement("sections"); + sectionElement.appendChild(processDirectory(directory, testsElement)); + result.appendChild(sectionElement); } } From a6dbeb3db7151ed43cec3ae4304ac90309a9b9c7 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 9 Jul 2018 12:06:20 -0700 Subject: [PATCH 03/36] WIP. --- tools/auto-tester/src/TestSuiteCreator.cpp | 155 +++++++++++++++++---- tools/auto-tester/src/TestSuiteCreator.h | 2 + 2 files changed, 129 insertions(+), 28 deletions(-) diff --git a/tools/auto-tester/src/TestSuiteCreator.cpp b/tools/auto-tester/src/TestSuiteCreator.cpp index d1dc0ce281..7abe214d1c 100644 --- a/tools/auto-tester/src/TestSuiteCreator.cpp +++ b/tools/auto-tester/src/TestSuiteCreator.cpp @@ -20,36 +20,21 @@ void TestSuiteCreator::createTestSuite(const QString& testDirectory) { QDomProcessingInstruction instruction = document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); document.appendChild(instruction); - // root element - QDomElement root = document.createElement("suite"); + // We create a single section, within sections + QDomElement root = document.createElement("sections"); document.appendChild(root); - // id (empty seems to be OK) - root.appendChild(document.createElement("id")); - - // name - our tests are in "Rendering" - QDomElement nameElement = document.createElement("name"); - QDomText nameElementText = document.createTextNode("Rendering"); - nameElement.appendChild(nameElementText); - root.appendChild(nameElement); - - // We create a single section, within sections - QDomElement topLevelSections = document.createElement("sections"); - QDomElement topLevelSection = document.createElement("section"); QDomElement suiteName = document.createElement("name"); - QDomText suiteNameElementElementText = document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString()); - suiteName.appendChild(suiteNameElementElementText); + suiteName.appendChild(document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString())); topLevelSection.appendChild(suiteName); QDomElement secondLevelSections = document.createElement("sections"); topLevelSection.appendChild(processDirectory(testDirectory, secondLevelSections)); topLevelSection.appendChild(secondLevelSections); - topLevelSections.appendChild(topLevelSection); - - root.appendChild(topLevelSections); + root.appendChild(topLevelSection); // Write to file const QString testRailsFilename{ "D:/t/TestRailSuite.xml" }; @@ -73,32 +58,146 @@ QDomElement TestSuiteCreator::processDirectory(const QString& directory, const Q // Loop over all entries in directory QDirIterator it(directory.toStdString().c_str()); while (it.hasNext()) { - QString directory = it.next(); + QString nextDirectory = it.next(); + + // The object name appears after the last slash (we are assured there is at least 1). + QString objectName = nextDirectory.right(nextDirectory.length() - nextDirectory.lastIndexOf("/") - 1); // Only process directories - if (Test::isAValidDirectory(directory)) { - // Ignore the utils directory - if (directory.right(5) == "utils") { + if (Test::isAValidDirectory(nextDirectory)) { + // Ignore the utils and preformance directories + if (nextDirectory.right(QString("utils").length()) == "utils" || nextDirectory.right(QString("performance").length()) == "performance") { continue; } // Create a section and process it - // The directory name appears after the last slash (we are assured there is at least 1). - QString directoryName = directory.right(directory.length() - directory.lastIndexOf("/") - 1); QDomElement sectionElement = document.createElement("section"); QDomElement sectionElementName = document.createElement("name"); - QDomText sectionElementNameText = document.createTextNode(directoryName); - sectionElementName.appendChild(sectionElementNameText); + sectionElementName.appendChild(document.createTextNode(objectName)); sectionElement.appendChild(sectionElementName); QDomElement testsElement = document.createElement("sections"); - sectionElement.appendChild(processDirectory(directory, testsElement)); + sectionElement.appendChild(processDirectory(nextDirectory, testsElement)); result.appendChild(sectionElement); + } else { + if (objectName == "test.js") { + QDomElement sectionElement = document.createElement("section"); + QDomElement sectionElementName = document.createElement("name"); + sectionElementName.appendChild(document.createTextNode("all")); + sectionElement.appendChild(sectionElementName); + sectionElement.appendChild(processTest(nextDirectory, objectName, document.createElement("cases"))); + result.appendChild(sectionElement); + } } } + return result; +} + +QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QString& test, const QDomElement& element) { + QDomElement result = element; + + QDomElement caseElement = document.createElement("case"); + + caseElement.appendChild(document.createElement("id")); + + // The name of the test is derived from the full path. + // The first term is the first word after "tests" + // The last word is the penultimate word + QStringList words = fullDirectory.split('/'); + int i = 0; + while (words[i] != "tests") { + ++i; + if (i >= words.length() - 1) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder \"tests\" not found in " + fullDirectory); + exit(-1); + } + } + + ++i; + QString title{ words[i] }; + for (++i; i < words.length() - 1; ++i) { + title += " / " + words[i]; + } + + QDomElement titleElement = document.createElement("title"); + titleElement.appendChild(document.createTextNode(title)); + caseElement.appendChild(titleElement); + + QDomElement templateElement = document.createElement("template"); + templateElement.appendChild(document.createTextNode("Test Case (Steps)")); + caseElement.appendChild(templateElement); + + QDomElement typeElement = document.createElement("type"); + typeElement.appendChild(document.createTextNode("3 - Regression")); + caseElement.appendChild(typeElement); + + QDomElement priorityElement = document.createElement("priority"); + priorityElement.appendChild(document.createTextNode("Medium")); + caseElement.appendChild(priorityElement); + + QDomElement estimateElementName = document.createElement("estimate"); + estimateElementName.appendChild(document.createTextNode("60")); + caseElement.appendChild(estimateElementName); + + caseElement.appendChild(document.createElement("references")); + + QDomElement customElement = document.createElement("custom"); + + QDomElement tester_countElement = document.createElement("tester_count"); + tester_countElement.appendChild(document.createTextNode("1")); + customElement.appendChild(tester_countElement); + + QDomElement domain_bot_loadElement = document.createElement("domain_bot_load"); + domain_bot_loadElement.appendChild(document.createElement("id")); + QDomElement domain_bot_loadElementValue = document.createElement("value"); + domain_bot_loadElementValue.appendChild(document.createTextNode(" With Bots (hifiqa-rc-bots / hifi-qa-stable-bots / hifiqa-master-bots)")); + domain_bot_loadElement.appendChild(domain_bot_loadElementValue); + customElement.appendChild(domain_bot_loadElement); + + QDomElement automation_typeElement = document.createElement("automation_type"); + automation_typeElement.appendChild(document.createElement("id")); + QDomElement automation_typeElementValue = document.createElement("value"); + automation_typeElementValue.appendChild(document.createTextNode("None")); + automation_typeElement.appendChild(automation_typeElementValue); + customElement.appendChild(automation_typeElement); + + QDomElement added_to_releaseElement = document.createElement("added_to_release"); + QDomElement added_to_releaseElementId = document.createElement("id"); + added_to_releaseElement.appendChild(document.createElement("id")); + QDomElement added_to_releaseElementValue = document.createElement("value"); + added_to_releaseElementValue.appendChild(document.createTextNode("RC68")); + added_to_releaseElement.appendChild(added_to_releaseElementValue); + customElement.appendChild(added_to_releaseElement); + + QDomElement precondsElement = document.createElement("preconds"); + precondsElement.appendChild(document.createTextNode("Tester is in an empty region of a domain in which they have edit rights\n\n*Note: Press 'n' to advance test script")); + customElement.appendChild(precondsElement); + + QDomElement steps_seperatedElement = document.createElement("steps_separated"); + QDomElement stepElement = document.createElement("step"); + QDomElement stepIndexElement = document.createElement("index"); + stepIndexElement.appendChild(document.createTextNode("1")); + stepElement.appendChild(stepIndexElement); + QDomElement stepContentElement = document.createElement("content"); + stepContentElement.appendChild(document.createTextNode("Execute instructions in [THIS TEST](https://github.com/highfidelity/hifi_tests/blob/RC70/tests/content/entity/light/point/create/test.md)")); + stepElement.appendChild(stepContentElement); + QDomElement stepExpectedElement = document.createElement("expected"); + stepExpectedElement.appendChild(document.createTextNode("Refer to the expected result in the linked description.")); + stepElement.appendChild(stepExpectedElement); + steps_seperatedElement.appendChild(stepElement); + customElement.appendChild(steps_seperatedElement); + + QDomElement notesElement = document.createElement("notes"); + notesElement.appendChild(document.createTextNode("https://github.com/highfidelity/hifi_tests/blob/RC70/tests/content/entity/light/point/create/test.md")); + customElement.appendChild(notesElement); + + caseElement.appendChild(customElement); + + result.appendChild(caseElement); + return result; } \ No newline at end of file diff --git a/tools/auto-tester/src/TestSuiteCreator.h b/tools/auto-tester/src/TestSuiteCreator.h index 3ecf046497..c7175dea89 100644 --- a/tools/auto-tester/src/TestSuiteCreator.h +++ b/tools/auto-tester/src/TestSuiteCreator.h @@ -19,6 +19,8 @@ class TestSuiteCreator { public: void createTestSuite(const QString& testDirectory); QDomElement processDirectory(const QString& directory, const QDomElement& element); + QDomElement processTest(const QString& fullDirectory, const QString& test, const QDomElement& element); + private: QDomDocument document; }; From 112ba27f2d4ff7f11f09aa1f1b567b5e680e8422 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 9 Jul 2018 14:00:08 -0700 Subject: [PATCH 04/36] Added user and branch - not tested yet! --- tools/auto-tester/src/Test.cpp | 2 +- tools/auto-tester/src/TestSuiteCreator.cpp | 32 +++++++++++----------- tools/auto-tester/src/TestSuiteCreator.h | 7 +++-- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 8255d845f6..11e1696bb1 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -839,7 +839,7 @@ void Test::createTestRailTestSuite() { } TestSuiteCreator testSuiteCreator; - testSuiteCreator.createTestSuite(testDirectory); + testSuiteCreator.createTestSuite(testDirectory, autoTester->getSelectedUser(), autoTester->getSelectedBranch()); } QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { diff --git a/tools/auto-tester/src/TestSuiteCreator.cpp b/tools/auto-tester/src/TestSuiteCreator.cpp index 7abe214d1c..0d11a84291 100644 --- a/tools/auto-tester/src/TestSuiteCreator.cpp +++ b/tools/auto-tester/src/TestSuiteCreator.cpp @@ -16,7 +16,7 @@ #include #include -void TestSuiteCreator::createTestSuite(const QString& testDirectory) { +void TestSuiteCreator::createTestSuite(const QString& testDirectory, const QString& user, const QString& branch) { QDomProcessingInstruction instruction = document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); document.appendChild(instruction); @@ -31,7 +31,7 @@ void TestSuiteCreator::createTestSuite(const QString& testDirectory) { topLevelSection.appendChild(suiteName); QDomElement secondLevelSections = document.createElement("sections"); - topLevelSection.appendChild(processDirectory(testDirectory, secondLevelSections)); + topLevelSection.appendChild(processDirectory(testDirectory, user, branch, secondLevelSections)); topLevelSection.appendChild(secondLevelSections); root.appendChild(topLevelSection); @@ -52,7 +52,7 @@ void TestSuiteCreator::createTestSuite(const QString& testDirectory) { QMessageBox::information(0, "Success", "TestRail XML file has been created"); } -QDomElement TestSuiteCreator::processDirectory(const QString& directory, const QDomElement& element) { +QDomElement TestSuiteCreator::processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element) { QDomElement result = element; // Loop over all entries in directory @@ -79,25 +79,23 @@ QDomElement TestSuiteCreator::processDirectory(const QString& directory, const Q sectionElement.appendChild(sectionElementName); QDomElement testsElement = document.createElement("sections"); - sectionElement.appendChild(processDirectory(nextDirectory, testsElement)); + sectionElement.appendChild(processDirectory(nextDirectory, user, branch, testsElement)); result.appendChild(sectionElement); - } else { - if (objectName == "test.js") { - QDomElement sectionElement = document.createElement("section"); - QDomElement sectionElementName = document.createElement("name"); - sectionElementName.appendChild(document.createTextNode("all")); - sectionElement.appendChild(sectionElementName); - sectionElement.appendChild(processTest(nextDirectory, objectName, document.createElement("cases"))); - result.appendChild(sectionElement); - } + } else if (objectName == "test.js" || objectName == "testStory.js") { + QDomElement sectionElement = document.createElement("section"); + QDomElement sectionElementName = document.createElement("name"); + sectionElementName.appendChild(document.createTextNode("all")); + sectionElement.appendChild(sectionElementName); + sectionElement.appendChild(processTest(nextDirectory, objectName, user, branch, document.createElement("cases"))); + result.appendChild(sectionElement); } } return result; } -QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QString& test, const QDomElement& element) { +QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element) { QDomElement result = element; QDomElement caseElement = document.createElement("case"); @@ -177,13 +175,15 @@ QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QS precondsElement.appendChild(document.createTextNode("Tester is in an empty region of a domain in which they have edit rights\n\n*Note: Press 'n' to advance test script")); customElement.appendChild(precondsElement); + QString testMDName = QString("https://github.com/") + user + "/hifi_tests/blob/" + branch + "/tests/content/entity/light/point/create/test.md"; + QDomElement steps_seperatedElement = document.createElement("steps_separated"); QDomElement stepElement = document.createElement("step"); QDomElement stepIndexElement = document.createElement("index"); stepIndexElement.appendChild(document.createTextNode("1")); stepElement.appendChild(stepIndexElement); QDomElement stepContentElement = document.createElement("content"); - stepContentElement.appendChild(document.createTextNode("Execute instructions in [THIS TEST](https://github.com/highfidelity/hifi_tests/blob/RC70/tests/content/entity/light/point/create/test.md)")); + stepContentElement.appendChild(document.createTextNode(QString("Execute instructions in [THIS TEST](") + testMDName + ")")); stepElement.appendChild(stepContentElement); QDomElement stepExpectedElement = document.createElement("expected"); stepExpectedElement.appendChild(document.createTextNode("Refer to the expected result in the linked description.")); @@ -192,7 +192,7 @@ QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QS customElement.appendChild(steps_seperatedElement); QDomElement notesElement = document.createElement("notes"); - notesElement.appendChild(document.createTextNode("https://github.com/highfidelity/hifi_tests/blob/RC70/tests/content/entity/light/point/create/test.md")); + notesElement.appendChild(document.createTextNode(testMDName)); customElement.appendChild(notesElement); caseElement.appendChild(customElement); diff --git a/tools/auto-tester/src/TestSuiteCreator.h b/tools/auto-tester/src/TestSuiteCreator.h index c7175dea89..a6ffa762e9 100644 --- a/tools/auto-tester/src/TestSuiteCreator.h +++ b/tools/auto-tester/src/TestSuiteCreator.h @@ -17,9 +17,10 @@ class TestSuiteCreator { public: - void createTestSuite(const QString& testDirectory); - QDomElement processDirectory(const QString& directory, const QDomElement& element); - QDomElement processTest(const QString& fullDirectory, const QString& test, const QDomElement& element); + void createTestSuite(const QString& testDirectory, const QString& user, const QString& branch); + + QDomElement processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element); + QDomElement processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element); private: QDomDocument document; From f69f0cbd808d0d20f2ea700f8ac8763a47782908 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 9 Jul 2018 19:59:59 -0700 Subject: [PATCH 05/36] Seems to create a valid test suite. --- tools/auto-tester/src/TestSuiteCreator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/auto-tester/src/TestSuiteCreator.cpp b/tools/auto-tester/src/TestSuiteCreator.cpp index 0d11a84291..98aa4391a1 100644 --- a/tools/auto-tester/src/TestSuiteCreator.cpp +++ b/tools/auto-tester/src/TestSuiteCreator.cpp @@ -167,7 +167,7 @@ QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QS QDomElement added_to_releaseElementId = document.createElement("id"); added_to_releaseElement.appendChild(document.createElement("id")); QDomElement added_to_releaseElementValue = document.createElement("value"); - added_to_releaseElementValue.appendChild(document.createTextNode("RC68")); + added_to_releaseElementValue.appendChild(document.createTextNode(branch)); added_to_releaseElement.appendChild(added_to_releaseElementValue); customElement.appendChild(added_to_releaseElement); From cb0f9639ba6e9251173c42e7183c7c7fe5860828 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 11 Jul 2018 09:08:43 -0700 Subject: [PATCH 06/36] Added IDs where needed. --- tools/auto-tester/src/TestSuiteCreator.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/auto-tester/src/TestSuiteCreator.cpp b/tools/auto-tester/src/TestSuiteCreator.cpp index 98aa4391a1..627012deec 100644 --- a/tools/auto-tester/src/TestSuiteCreator.cpp +++ b/tools/auto-tester/src/TestSuiteCreator.cpp @@ -150,14 +150,18 @@ QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QS customElement.appendChild(tester_countElement); QDomElement domain_bot_loadElement = document.createElement("domain_bot_load"); - domain_bot_loadElement.appendChild(document.createElement("id")); + QDomElement domain_bot_loadElementId = document.createElement("id"); + domain_bot_loadElementId.appendChild(document.createTextNode("1")); + domain_bot_loadElement.appendChild(domain_bot_loadElementId); QDomElement domain_bot_loadElementValue = document.createElement("value"); - domain_bot_loadElementValue.appendChild(document.createTextNode(" With Bots (hifiqa-rc-bots / hifi-qa-stable-bots / hifiqa-master-bots)")); + domain_bot_loadElementValue.appendChild(document.createTextNode(" Without Bots (hifiqa-rc / hifi-qa-stable / hifiqa-master)")); domain_bot_loadElement.appendChild(domain_bot_loadElementValue); customElement.appendChild(domain_bot_loadElement); QDomElement automation_typeElement = document.createElement("automation_type"); - automation_typeElement.appendChild(document.createElement("id")); + QDomElement automation_typeElementId = document.createElement("id"); + automation_typeElementId.appendChild(document.createTextNode("0")); + automation_typeElement.appendChild(automation_typeElementId); QDomElement automation_typeElementValue = document.createElement("value"); automation_typeElementValue.appendChild(document.createTextNode("None")); automation_typeElement.appendChild(automation_typeElementValue); @@ -165,7 +169,8 @@ QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QS QDomElement added_to_releaseElement = document.createElement("added_to_release"); QDomElement added_to_releaseElementId = document.createElement("id"); - added_to_releaseElement.appendChild(document.createElement("id")); + added_to_releaseElementId.appendChild(document.createTextNode("4")); + added_to_releaseElement.appendChild(added_to_releaseElementId); QDomElement added_to_releaseElementValue = document.createElement("value"); added_to_releaseElementValue.appendChild(document.createTextNode(branch)); added_to_releaseElement.appendChild(added_to_releaseElementValue); From 816b3a4ef6f3e64ea7675edc4df6b901b8cda34f Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 25 Jul 2018 15:49:41 -0700 Subject: [PATCH 07/36] WIP. --- tools/auto-tester/src/Test.cpp | 211 +++++++++--------- tools/auto-tester/src/Test.h | 28 +-- ...SuiteCreator.cpp => TestRailInterface.cpp} | 15 +- ...TestSuiteCreator.h => TestRailInterface.h} | 15 +- tools/auto-tester/src/ui/AutoTester.cpp | 74 +++--- tools/auto-tester/src/ui/AutoTester.h | 10 +- tools/auto-tester/src/ui/MismatchWindow.cpp | 6 +- tools/auto-tester/src/ui/MismatchWindow.h | 2 +- 8 files changed, 188 insertions(+), 173 deletions(-) rename tools/auto-tester/src/{TestSuiteCreator.cpp => TestRailInterface.cpp} (92%) rename tools/auto-tester/src/{TestSuiteCreator.h => TestRailInterface.h} (65%) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 11e1696bb1..22ec78e284 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -18,14 +18,14 @@ #include #include -#include "TestSuiteCreator.h" +#include "TestRailInterface.h" #include "ui/AutoTester.h" extern AutoTester* autoTester; #include Test::Test() { - mismatchWindow.setModal(true); + _mismatchWindow.setModal(true); if (autoTester) { autoTester->setUserText("highfidelity"); @@ -35,35 +35,35 @@ Test::Test() { bool Test::createTestResultsFolderPath(const QString& directory) { QDateTime now = QDateTime::currentDateTime(); - testResultsFolderPath = directory + "/" + TEST_RESULTS_FOLDER + "--" + now.toString(DATETIME_FORMAT); - QDir testResultsFolder(testResultsFolderPath); + _testResultsFolderPath = directory + "/" + TEST_RESULTS_FOLDER + "--" + now.toString(DATETIME_FORMAT); + QDir testResultsFolder(_testResultsFolderPath); // Create a new test results folder - return QDir().mkdir(testResultsFolderPath); + return QDir().mkdir(_testResultsFolderPath); } void Test::zipAndDeleteTestResultsFolder() { - QString zippedResultsFileName { testResultsFolderPath + ".zip" }; + QString zippedResultsFileName { _testResultsFolderPath + ".zip" }; QFileInfo fileInfo(zippedResultsFileName); if (!fileInfo.exists()) { QFile::remove(zippedResultsFileName); } - QDir testResultsFolder(testResultsFolderPath); + QDir testResultsFolder(_testResultsFolderPath); if (!testResultsFolder.isEmpty()) { - JlCompress::compressDir(testResultsFolderPath + ".zip", testResultsFolderPath); + JlCompress::compressDir(_testResultsFolderPath + ".zip", _testResultsFolderPath); } testResultsFolder.removeRecursively(); //In all cases, for the next evaluation - testResultsFolderPath = ""; - index = 1; + _testResultsFolderPath = ""; + _index = 1; } bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) { progressBar->setMinimum(0); - progressBar->setMaximum(expectedImagesFullFilenames.length() - 1); + progressBar->setMaximum(_expectedImagesFullFilenames.length() - 1); progressBar->setValue(0); progressBar->setVisible(true); @@ -71,10 +71,10 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) // Quit loop if user has aborted due to a failed test. bool success{ true }; bool keepOn{ true }; - for (int i = 0; keepOn && i < expectedImagesFullFilenames.length(); ++i) { + for (int i = 0; keepOn && i < _expectedImagesFullFilenames.length(); ++i) { // First check that images are the same size - QImage resultImage(resultImagesFullFilenames[i]); - QImage expectedImage(expectedImagesFullFilenames[i]); + QImage resultImage(_resultImagesFullFilenames[i]); + QImage expectedImage(_expectedImagesFullFilenames[i]); double similarityIndex; // in [-1.0 .. 1.0], where 1.0 means images are identical @@ -83,30 +83,30 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size"); similarityIndex = -100.0; } else { - similarityIndex = imageComparer.compareImages(resultImage, expectedImage); + similarityIndex = _imageComparer.compareImages(resultImage, expectedImage); } if (similarityIndex < THRESHOLD) { TestFailure testFailure = TestFailure{ (float)similarityIndex, - expectedImagesFullFilenames[i].left(expectedImagesFullFilenames[i].lastIndexOf("/") + 1), // path to the test (including trailing /) - QFileInfo(expectedImagesFullFilenames[i].toStdString().c_str()).fileName(), // filename of expected image - QFileInfo(resultImagesFullFilenames[i].toStdString().c_str()).fileName() // filename of result image + _expectedImagesFullFilenames[i].left(_expectedImagesFullFilenames[i].lastIndexOf("/") + 1), // path to the test (including trailing /) + QFileInfo(_expectedImagesFullFilenames[i].toStdString().c_str()).fileName(), // filename of expected image + QFileInfo(_resultImagesFullFilenames[i].toStdString().c_str()).fileName() // filename of result image }; - mismatchWindow.setTestFailure(testFailure); + _mismatchWindow.setTestFailure(testFailure); if (!isInteractiveMode) { - appendTestResultsToFile(testResultsFolderPath, testFailure, mismatchWindow.getComparisonImage()); + appendTestResultsToFile(_testResultsFolderPath, testFailure, _mismatchWindow.getComparisonImage()); success = false; } else { - mismatchWindow.exec(); + _mismatchWindow.exec(); - switch (mismatchWindow.getUserResponse()) { + switch (_mismatchWindow.getUserResponse()) { case USER_RESPONSE_PASS: break; case USE_RESPONSE_FAIL: - appendTestResultsToFile(testResultsFolderPath, testFailure, mismatchWindow.getComparisonImage()); + appendTestResultsToFile(_testResultsFolderPath, testFailure, _mismatchWindow.getComparisonImage()); success = false; break; case USER_RESPONSE_ABORT: @@ -127,20 +127,20 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) return success; } -void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage) { - if (!QDir().exists(testResultsFolderPath)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + testResultsFolderPath + " not found"); +void Test::appendTestResultsToFile(const QString& _testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage) { + if (!QDir().exists(_testResultsFolderPath)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder " + _testResultsFolderPath + " not found"); exit(-1); } QString err = QString::number(testFailure._error).left(6); - QString failureFolderPath { testResultsFolderPath + "/" + err + "-Failure_" + QString::number(index) + "--" + testFailure._actualImageFilename.left(testFailure._actualImageFilename.length() - 4) }; + QString failureFolderPath { _testResultsFolderPath + "/" + err + "-Failure_" + QString::number(_index) + "--" + testFailure._actualImageFilename.left(testFailure._actualImageFilename.length() - 4) }; if (!QDir().mkdir(failureFolderPath)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create folder " + failureFolderPath); exit(-1); } - ++index; + ++_index; QFile descriptionFile(failureFolderPath + "/" + TEST_RESULTS_FILENAME); if (!descriptionFile.open(QIODevice::ReadWrite)) { @@ -153,7 +153,7 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai stream << "Test failed in folder " << testFailure._pathname.left(testFailure._pathname.length() - 1) << endl; // remove trailing '/' stream << "Expected image was " << testFailure._expectedImageFilename << endl; stream << "Actual image was " << testFailure._actualImageFilename << endl; - stream << "Similarity index was " << testFailure._error << endl; + stream << "Similarity _index was " << testFailure._error << endl; descriptionFile.close(); @@ -181,26 +181,26 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai void Test::startTestsEvaluation(const QString& testFolder, const QString& branchFromCommandLine, const QString& userFromCommandLine) { if (testFolder.isNull()) { // Get list of JPEG images in folder, sorted by name - QString previousSelection = snapshotDirectory; + QString previousSelection = _snapshotDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", parent, + _snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (snapshotDirectory == "") { - snapshotDirectory = previousSelection; + if (_snapshotDirectory == "") { + _snapshotDirectory = previousSelection; return; } } else { - snapshotDirectory = testFolder; - exitWhenComplete = true; + _snapshotDirectory = testFolder; + _exitWhenComplete = true; } // Quit if test results folder could not be created - if (!createTestResultsFolderPath(snapshotDirectory)) { + if (!createTestResultsFolderPath(_snapshotDirectory)) { return; } @@ -208,20 +208,20 @@ void Test::startTestsEvaluation(const QString& testFolder, const QString& branch // The expected images are represented as a URL to enable download from GitHub // Images that are in the wrong format are ignored. - QStringList sortedTestResultsFilenames = createListOfAll_imagesInDirectory("png", snapshotDirectory); + QStringList sortedTestResultsFilenames = createListOfAll_imagesInDirectory("png", _snapshotDirectory); QStringList expectedImagesURLs; - resultImagesFullFilenames.clear(); - expectedImagesFilenames.clear(); - expectedImagesFullFilenames.clear(); + _resultImagesFullFilenames.clear(); + _expectedImagesFilenames.clear(); + _expectedImagesFullFilenames.clear(); QString branch = (branchFromCommandLine.isNull()) ? autoTester->getSelectedBranch() : branchFromCommandLine; QString user = (userFromCommandLine.isNull()) ? autoTester->getSelectedUser() : userFromCommandLine; foreach(QString currentFilename, sortedTestResultsFilenames) { - QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename; + QString fullCurrentFilename = _snapshotDirectory + "/" + currentFilename; if (isInSnapshotFilenameFormat("png", currentFilename)) { - resultImagesFullFilenames << fullCurrentFilename; + _resultImagesFullFilenames << fullCurrentFilename; QString expectedImagePartialSourceDirectory = getExpectedImagePartialSourceDirectory(currentFilename); @@ -238,12 +238,12 @@ void Test::startTestsEvaluation(const QString& testFolder, const QString& branch // The image retrieved from GitHub needs a unique name QString expectedImageFilename = currentFilename.replace("/", "_").replace(".png", "_EI.png"); - expectedImagesFilenames << expectedImageFilename; - expectedImagesFullFilenames << snapshotDirectory + "/" + expectedImageFilename; + _expectedImagesFilenames << expectedImageFilename; + _expectedImagesFullFilenames << _snapshotDirectory + "/" + expectedImageFilename; } } - autoTester->downloadImages(expectedImagesURLs, snapshotDirectory, expectedImagesFilenames); + autoTester->downloadImages(expectedImagesURLs, _snapshotDirectory, _expectedImagesFilenames); } void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar) { @@ -259,7 +259,7 @@ void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactive zipAndDeleteTestResultsFolder(); - if (exitWhenComplete) { + if (_exitWhenComplete) { exit(0); } } @@ -311,46 +311,46 @@ void Test::includeTest(QTextStream& textStream, const QString& testPathname) { // This script will run all text.js scripts in every applicable sub-folder void Test::createRecursiveScript() { // Select folder to start recursing from - QString previousSelection = testDirectory; + QString previousSelection = _testDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testDirectory = + _testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder that will contain the top level test script", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testDirectory == "") { - testDirectory = previousSelection; + if (_testDirectory == "") { + _testDirectory = previousSelection; return; } - createRecursiveScript(testDirectory, true); + createRecursiveScript(_testDirectory, true); } // This method creates a `testRecursive.js` script in every sub-folder. void Test::createAllRecursiveScripts() { // Select folder to start recursing from - QString previousSelection = testsRootDirectory; + QString previousSelection = _testsRootDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the recursive scripts", + _testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the recursive scripts", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testsRootDirectory == "") { - testsRootDirectory = previousSelection; + if (_testsRootDirectory == "") { + _testsRootDirectory = previousSelection; return; } - createRecursiveScript(testsRootDirectory, false); + createRecursiveScript(_testsRootDirectory, false); - QDirIterator it(testsRootDirectory.toStdString().c_str(), QDirIterator::Subdirectories); + QDirIterator it(_testsRootDirectory.toStdString().c_str(), QDirIterator::Subdirectories); while (it.hasNext()) { QString directory = it.next(); @@ -478,42 +478,42 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact void Test::createTests() { // Rename files sequentially, as ExpectedResult_00000.jpeg, ExpectedResult_00001.jpg and so on // Any existing expected result images will be deleted - QString previousSelection = snapshotDirectory; + QString previousSelection = _snapshotDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", parent, + _snapshotDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test images", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (snapshotDirectory == "") { - snapshotDirectory = previousSelection; + if (_snapshotDirectory == "") { + _snapshotDirectory = previousSelection; return; } - previousSelection = testsRootDirectory; + previousSelection = _testsRootDirectory; parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select test root folder", parent, + _testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select test root folder", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testsRootDirectory == "") { - testsRootDirectory = previousSelection; + if (_testsRootDirectory == "") { + _testsRootDirectory = previousSelection; return; } - QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("png", snapshotDirectory); + QStringList sortedImageFilenames = createListOfAll_imagesInDirectory("png", _snapshotDirectory); int i = 1; const int maxImages = pow(10, NUM_DIGITS); foreach (QString currentFilename, sortedImageFilenames) { - QString fullCurrentFilename = snapshotDirectory + "/" + currentFilename; + QString fullCurrentFilename = _snapshotDirectory + "/" + currentFilename; if (isInSnapshotFilenameFormat("png", currentFilename)) { if (i >= maxImages) { QMessageBox::critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported"); @@ -523,17 +523,17 @@ void Test::createTests() { // Path to test is extracted from the file name // Example: // filename is tests.engine.interaction.pointer.laser.distanceScaleEnd.00000.jpg - // path is /engine/interaction/pointer/laser/distanceScaleEnd + // path is <_testDirectory>/engine/interaction/pointer/laser/distanceScaleEnd // // Note: we don't use the first part and the last 2 parts of the filename at this stage // QStringList pathParts = currentFilename.split("."); - QString fullNewFileName = testsRootDirectory; + QString fullNewFileName = _testsRootDirectory; for (int j = 1; j < pathParts.size() - 2; ++j) { fullNewFileName += "/" + pathParts[j]; } - // The image index is the penultimate component of the path parts (the last being the file extension) + // The image _index is the penultimate component of the path parts (the last being the file extension) QString newFilename = "ExpectedImage_" + pathParts[pathParts.size() - 2].rightJustified(5, '0') + ".png"; fullNewFileName += "/" + newFilename; @@ -622,51 +622,51 @@ ExtractedText Test::getTestScriptLines(QString testFileName) { // The folder selected must contain a script named "test.js", the file produced is named "test.md" void Test::createMDFile() { // Folder selection - QString previousSelection = testDirectory; + QString previousSelection = _testDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test", parent, + _testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder containing the test", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testDirectory == "") { - testDirectory = previousSelection; + if (_testDirectory == "") { + _testDirectory = previousSelection; return; } - createMDFile(testDirectory); + createMDFile(_testDirectory); QMessageBox::information(0, "Success", "MD file has been created"); } void Test::createAllMDFiles() { // Select folder to start recursing from - QString previousSelection = testsRootDirectory; + QString previousSelection = _testsRootDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the MD files", parent, + _testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the MD files", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testsRootDirectory == "") { - testsRootDirectory = previousSelection; + if (_testsRootDirectory == "") { + _testsRootDirectory = previousSelection; return; } // First test if top-level folder has a test.js file - const QString testPathname{ testsRootDirectory + "/" + TEST_FILENAME }; + const QString testPathname{ _testsRootDirectory + "/" + TEST_FILENAME }; QFileInfo fileInfo(testPathname); if (fileInfo.exists()) { - createMDFile(testsRootDirectory); + createMDFile(_testsRootDirectory); } - QDirIterator it(testsRootDirectory.toStdString().c_str(), QDirIterator::Subdirectories); + QDirIterator it(_testsRootDirectory.toStdString().c_str(), QDirIterator::Subdirectories); while (it.hasNext()) { QString directory = it.next(); @@ -686,9 +686,9 @@ void Test::createAllMDFiles() { QMessageBox::information(0, "Success", "MD files have been created"); } -void Test::createMDFile(const QString& testDirectory) { +void Test::createMDFile(const QString& _testDirectory) { // Verify folder contains test.js file - QString testFileName(testDirectory + "/" + TEST_FILENAME); + QString testFileName(_testDirectory + "/" + TEST_FILENAME); QFileInfo testFileInfo(testFileName); if (!testFileInfo.exists()) { QMessageBox::critical(0, "Error", "Could not find file: " + TEST_FILENAME); @@ -697,7 +697,7 @@ void Test::createMDFile(const QString& testDirectory) { ExtractedText testScriptLines = getTestScriptLines(testFileName); - QString mdFilename(testDirectory + "/" + "test.md"); + QString mdFilename(_testDirectory + "/" + "test.md"); QFile mdFile(mdFilename); if (!mdFile.open(QIODevice::WriteOnly)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); @@ -711,7 +711,7 @@ void Test::createMDFile(const QString& testDirectory) { stream << "# " << testName << "\n"; // Find the relevant part of the path to the test (i.e. from "tests" down - QString partialPath = extractPathFromTestsDown(testDirectory); + QString partialPath = extractPathFromTestsDown(_testDirectory); stream << "## Run this script URL: [Manual](./test.js?raw=true) [Auto](./testAuto.js?raw=true)(from menu/Edit/Open and Run scripts from URL...)." << "\n\n"; @@ -735,23 +735,23 @@ void Test::createMDFile(const QString& testDirectory) { } void Test::createTestsOutline() { - QString previousSelection = testDirectory; + QString previousSelection = _testDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testDirectory = + _testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testDirectory == "") { - testDirectory = previousSelection; + if (_testDirectory == "") { + _testDirectory = previousSelection; return; } const QString testsOutlineFilename { "testsOutline.md" }; - QString mdFilename(testDirectory + "/" + testsOutlineFilename); + QString mdFilename(_testDirectory + "/" + testsOutlineFilename); QFile mdFile(mdFilename); if (!mdFile.open(QIODevice::WriteOnly)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create file " + mdFilename); @@ -765,10 +765,10 @@ void Test::createTestsOutline() { stream << "Directories with an appended (*) have an automatic test\n\n"; // We need to know our current depth, as this isn't given by QDirIterator - int rootDepth { testDirectory.count('/') }; + int rootDepth { _testDirectory.count('/') }; // Each test is shown as the folder name linking to the matching GitHub URL, and the path to the associated test.md file - QDirIterator it(testDirectory.toStdString().c_str(), QDirIterator::Subdirectories); + QDirIterator it(_testDirectory.toStdString().c_str(), QDirIterator::Subdirectories); while (it.hasNext()) { QString directory = it.next(); @@ -823,31 +823,40 @@ void Test::createTestsOutline() { } void Test::createTestRailTestSuite() { - QString previousSelection = testDirectory; + QString previousSelection = _testDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testDirectory = + _testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testDirectory == "") { - testDirectory = previousSelection; + if (_testDirectory == "") { + _testDirectory = previousSelection; return; } - TestSuiteCreator testSuiteCreator; - testSuiteCreator.createTestSuite(testDirectory, autoTester->getSelectedUser(), autoTester->getSelectedBranch()); + QString outputDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store generated files in", + parent, QFileDialog::ShowDirsOnly); + + // If user cancelled then restore previous selection and return + if (outputDirectory == "") { + return; + } + + TestRailInterface testRailInterface; + testRailInterface.createTestSuite(_testDirectory, outputDirectory, autoTester->getSelectedUser(), + autoTester->getSelectedBranch()); } QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { - imageDirectory = QDir(pathToImageDirectory); + _imageDirectory = QDir(pathToImageDirectory); QStringList nameFilters; nameFilters << "*." + imageFormat; - return imageDirectory.entryList(nameFilters, QDir::Files, QDir::Name); + return _imageDirectory.entryList(nameFilters, QDir::Files, QDir::Name); } // Snapshots are files in the following format: diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 47786664fd..3648906086 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -70,6 +70,8 @@ public: QString getExpectedImageDestinationDirectory(const QString& filename); QString getExpectedImagePartialSourceDirectory(const QString& filename); + ExtractedText getTestScriptLines(QString testFileName); + private: const QString TEST_FILENAME { "test.js" }; const QString TEST_RESULTS_FOLDER { "TestResults" }; @@ -77,14 +79,14 @@ private: const double THRESHOLD{ 0.96 }; - QDir imageDirectory; + QDir _imageDirectory; - MismatchWindow mismatchWindow; + MismatchWindow _mismatchWindow; - ImageComparer imageComparer; + ImageComparer _imageComparer; - QString testResultsFolderPath; - int index { 1 }; + QString _testResultsFolderPath; + int _index { 1 }; // Expected images are in the format ExpectedImage_dddd.jpg (d == decimal digit) const int NUM_DIGITS { 5 }; @@ -94,28 +96,26 @@ private: // The first is the directory containing the test we are working with // The second is the root directory of all tests // The third contains the snapshots taken for test runs that need to be evaluated - QString testDirectory; - QString testsRootDirectory; - QString snapshotDirectory; + QString _testDirectory; + QString _testsRootDirectory; + QString _snapshotDirectory; - QStringList expectedImagesFilenames; - QStringList expectedImagesFullFilenames; - QStringList resultImagesFullFilenames; + QStringList _expectedImagesFilenames; + QStringList _expectedImagesFullFilenames; + QStringList _resultImagesFullFilenames; // Used for accessing GitHub const QString GIT_HUB_REPOSITORY{ "hifi_tests" }; const QString DATETIME_FORMAT{ "yyyy-MM-dd_hh-mm-ss" }; - ExtractedText getTestScriptLines(QString testFileName); - // NOTE: these need to match the appropriate var's in autoTester.js // var advanceKey = "n"; // var pathSeparator = "."; const QString ADVANCE_KEY{ "n" }; const QString PATH_SEPARATOR{ "." }; - bool exitWhenComplete{ false }; + bool _exitWhenComplete{ false }; }; #endif // hifi_test_h \ No newline at end of file diff --git a/tools/auto-tester/src/TestSuiteCreator.cpp b/tools/auto-tester/src/TestRailInterface.cpp similarity index 92% rename from tools/auto-tester/src/TestSuiteCreator.cpp rename to tools/auto-tester/src/TestRailInterface.cpp index 627012deec..189dc9a551 100644 --- a/tools/auto-tester/src/TestSuiteCreator.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -1,5 +1,5 @@ // -// TestSuiteCreator.cpp +// TestRailInterface.cpp // // Created by Nissim Hadar on 6 Jul 2018. // Copyright 2013 High Fidelity, Inc. @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "TestSuiteCreator.h" +#include "TestRailInterface.h" #include "Test.h" #include @@ -16,7 +16,10 @@ #include #include -void TestSuiteCreator::createTestSuite(const QString& testDirectory, const QString& user, const QString& branch) { +void TestRailInterface::createTestSuite(const QString& testDirectory, + const QString& outputDirectory, + const QString& user, + const QString& branch) { QDomProcessingInstruction instruction = document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); document.appendChild(instruction); @@ -37,7 +40,7 @@ void TestSuiteCreator::createTestSuite(const QString& testDirectory, const QStri root.appendChild(topLevelSection); // Write to file - const QString testRailsFilename{ "D:/t/TestRailSuite.xml" }; + const QString testRailsFilename{ outputDirectory + "/TestRailSuite.xml" }; QFile file(testRailsFilename); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not create XML file"); @@ -52,7 +55,7 @@ void TestSuiteCreator::createTestSuite(const QString& testDirectory, const QStri QMessageBox::information(0, "Success", "TestRail XML file has been created"); } -QDomElement TestSuiteCreator::processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element) { +QDomElement TestRailInterface::processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element) { QDomElement result = element; // Loop over all entries in directory @@ -95,7 +98,7 @@ QDomElement TestSuiteCreator::processDirectory(const QString& directory, const Q return result; } -QDomElement TestSuiteCreator::processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element) { +QDomElement TestRailInterface::processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element) { QDomElement result = element; QDomElement caseElement = document.createElement("case"); diff --git a/tools/auto-tester/src/TestSuiteCreator.h b/tools/auto-tester/src/TestRailInterface.h similarity index 65% rename from tools/auto-tester/src/TestSuiteCreator.h rename to tools/auto-tester/src/TestRailInterface.h index a6ffa762e9..12e2f058c5 100644 --- a/tools/auto-tester/src/TestSuiteCreator.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -1,5 +1,5 @@ // -// TestSuiteCreator.h +// TestRailInterface.h // // Created by Nissim Hadar on 6 Jul 2018. // Copyright 2013 High Fidelity, Inc. @@ -8,16 +8,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_test_suite_creator_h -#define hifi_test_suite_creator_h +#ifndef hifi_test_testrail_interface_h +#define hifi_test_testrail_interface_h #include #include #include -class TestSuiteCreator { +class TestRailInterface { public: - void createTestSuite(const QString& testDirectory, const QString& user, const QString& branch); + void createTestSuite(const QString& testDirectory, + const QString& outputDirectory, + const QString& user, + const QString& branch); QDomElement processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element); QDomElement processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element); @@ -26,4 +29,4 @@ private: QDomDocument document; }; -#endif // hifi_test_suite_creator_h \ No newline at end of file +#endif \ No newline at end of file diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 76ae6c5385..b4dbb5a7da 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -16,60 +16,60 @@ #endif AutoTester::AutoTester(QWidget *parent) : QMainWindow(parent) { - ui.setupUi(this); - ui.checkBoxInteractiveMode->setChecked(true); - ui.progressBar->setVisible(false); + _ui.setupUi(this); + _ui.checkBoxInteractiveMode->setChecked(true); + _ui.progressBar->setVisible(false); - signalMapper = new QSignalMapper(); + _signalMapper = new QSignalMapper(); - connect(ui.actionClose, &QAction::triggered, this, &AutoTester::on_closeButton_clicked); - connect(ui.actionAbout, &QAction::triggered, this, &AutoTester::about); + connect(_ui.actionClose, &QAction::triggered, this, &AutoTester::on_closeButton_clicked); + connect(_ui.actionAbout, &QAction::triggered, this, &AutoTester::about); #ifndef Q_OS_WIN - ui.hideTaskbarButton->setVisible(false); - ui.showTaskbarButton->setVisible(false); + _ui.hideTaskbarButton->setVisible(false); + _ui.showTaskbarButton->setVisible(false); #endif } void AutoTester::setup() { - test = new Test(); + _test = new Test(); } void AutoTester::runFromCommandLine(const QString& testFolder, const QString& branch, const QString& user) { - isRunningFromCommandline = true; - test->startTestsEvaluation(testFolder, branch, user); + _isRunningFromCommandline = true; + _test->startTestsEvaluation(testFolder, branch, user); } void AutoTester::on_evaluateTestsButton_clicked() { - test->startTestsEvaluation(); + _test->startTestsEvaluation(); } void AutoTester::on_createRecursiveScriptButton_clicked() { - test->createRecursiveScript(); + _test->createRecursiveScript(); } void AutoTester::on_createAllRecursiveScriptsButton_clicked() { - test->createAllRecursiveScripts(); + _test->createAllRecursiveScripts(); } void AutoTester::on_createTestsButton_clicked() { - test->createTests(); + _test->createTests(); } void AutoTester::on_createMDFileButton_clicked() { - test->createMDFile(); + _test->createMDFile(); } void AutoTester::on_createAllMDFilesButton_clicked() { - test->createAllMDFiles(); + _test->createAllMDFiles(); } void AutoTester::on_createTestsOutlineButton_clicked() { - test->createTestsOutline(); + _test->createTestsOutline(); } void AutoTester::on_createTestRailTestSuiteButton_clicked() { - test->createTestRailTestSuite(); + _test->createTestRailTestSuite(); } // To toggle between show and hide @@ -101,10 +101,10 @@ void AutoTester::on_closeButton_clicked() { } void AutoTester::downloadImage(const QUrl& url) { - downloaders.emplace_back(new Downloader(url, this)); - connect(downloaders[_index], SIGNAL (downloaded()), signalMapper, SLOT (map())); + _downloaders.emplace_back(new Downloader(url, this)); + connect(_downloaders[_index], SIGNAL (downloaded()), _signalMapper, SLOT (map())); - signalMapper->setMapping(downloaders[_index], _index); + _signalMapper->setMapping(_downloaders[_index], _index); ++_index; } @@ -117,39 +117,39 @@ void AutoTester::downloadImages(const QStringList& URLs, const QString& director _numberOfImagesDownloaded = 0; _index = 0; - ui.progressBar->setMinimum(0); - ui.progressBar->setMaximum(_numberOfImagesToDownload - 1); - ui.progressBar->setValue(0); - ui.progressBar->setVisible(true); + _ui.progressBar->setMinimum(0); + _ui.progressBar->setMaximum(_numberOfImagesToDownload - 1); + _ui.progressBar->setValue(0); + _ui.progressBar->setVisible(true); - downloaders.clear(); + _downloaders.clear(); for (int i = 0; i < _numberOfImagesToDownload; ++i) { QUrl imageURL(URLs[i]); downloadImage(imageURL); } - connect(signalMapper, SIGNAL (mapped(int)), this, SLOT (saveImage(int))); + connect(_signalMapper, SIGNAL (mapped(int)), this, SLOT (saveImage(int))); } void AutoTester::saveImage(int index) { try { QFile file(_directoryName + "/" + _filenames[index]); file.open(QIODevice::WriteOnly); - file.write(downloaders[index]->downloadedData()); + file.write(_downloaders[index]->downloadedData()); file.close(); } catch (...) { QMessageBox::information(0, "Test Aborted", "Failed to save image: " + _filenames[index]); - ui.progressBar->setVisible(false); + _ui.progressBar->setVisible(false); return; } ++_numberOfImagesDownloaded; if (_numberOfImagesDownloaded == _numberOfImagesToDownload) { - disconnect(signalMapper, SIGNAL (mapped(int)), this, SLOT (saveImage(int))); - test->finishTestsEvaluation(isRunningFromCommandline, ui.checkBoxInteractiveMode->isChecked(), ui.progressBar); + disconnect(_signalMapper, SIGNAL (mapped(int)), this, SLOT (saveImage(int))); + _test->finishTestsEvaluation(_isRunningFromCommandline, _ui.checkBoxInteractiveMode->isChecked(), _ui.progressBar); } else { - ui.progressBar->setValue(_numberOfImagesDownloaded); + _ui.progressBar->setValue(_numberOfImagesDownloaded); } } @@ -158,18 +158,18 @@ void AutoTester::about() { } void AutoTester::setUserText(const QString& user) { - ui.userTextEdit->setText(user); + _ui.userTextEdit->setText(user); } QString AutoTester::getSelectedUser() { - return ui.userTextEdit->toPlainText(); + return _ui.userTextEdit->toPlainText(); } void AutoTester::setBranchText(const QString& branch) { - ui.branchTextEdit->setText(branch); + _ui.branchTextEdit->setText(branch); } QString AutoTester::getSelectedBranch() { - return ui.branchTextEdit->toPlainText(); + return _ui.branchTextEdit->toPlainText(); } diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index 76b4741d9a..cb99b0a79c 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -56,23 +56,23 @@ private slots: void about(); private: - Ui::AutoTesterClass ui; - Test* test; + Ui::AutoTesterClass _ui; + Test* _test; - std::vector downloaders; + std::vector _downloaders; // local storage for parameters - folder to store downloaded files in, and a list of their names QString _directoryName; QStringList _filenames; // Used to enable passing a parameter to slots - QSignalMapper* signalMapper; + QSignalMapper* _signalMapper; int _numberOfImagesToDownload { 0 }; int _numberOfImagesDownloaded { 0 }; int _index { 0 }; - bool isRunningFromCommandline { false }; + bool _isRunningFromCommandline { false }; }; #endif // hifi_AutoTester_h \ No newline at end of file diff --git a/tools/auto-tester/src/ui/MismatchWindow.cpp b/tools/auto-tester/src/ui/MismatchWindow.cpp index d880a1abdc..79d2ce9f61 100644 --- a/tools/auto-tester/src/ui/MismatchWindow.cpp +++ b/tools/auto-tester/src/ui/MismatchWindow.cpp @@ -66,14 +66,14 @@ void MismatchWindow::setTestFailure(TestFailure testFailure) { QPixmap expectedPixmap = QPixmap(testFailure._pathname + testFailure._expectedImageFilename); QPixmap actualPixmap = QPixmap(testFailure._pathname + testFailure._actualImageFilename); - diffPixmap = computeDiffPixmap( + _diffPixmap = computeDiffPixmap( QImage(testFailure._pathname + testFailure._expectedImageFilename), QImage(testFailure._pathname + testFailure._actualImageFilename) ); expectedImage->setPixmap(expectedPixmap); resultImage->setPixmap(actualPixmap); - diffImage->setPixmap(diffPixmap); + diffImage->setPixmap(_diffPixmap); } void MismatchWindow::on_passTestButton_clicked() { @@ -92,5 +92,5 @@ void MismatchWindow::on_abortTestsButton_clicked() { } QPixmap MismatchWindow::getComparisonImage() { - return diffPixmap; + return _diffPixmap; } diff --git a/tools/auto-tester/src/ui/MismatchWindow.h b/tools/auto-tester/src/ui/MismatchWindow.h index cdbdcb4098..30fca94469 100644 --- a/tools/auto-tester/src/ui/MismatchWindow.h +++ b/tools/auto-tester/src/ui/MismatchWindow.h @@ -36,7 +36,7 @@ private slots: private: UserResponse _userResponse{ USER_RESPONSE_INVALID }; - QPixmap diffPixmap; + QPixmap _diffPixmap; }; From 6db83660b62acaf0316c57f24b60750d4ab2dc09 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 25 Jul 2018 17:07:18 -0700 Subject: [PATCH 08/36] Working on Python integration. --- tools/auto-tester/src/Test.cpp | 18 ++++++--- tools/auto-tester/src/Test.h | 13 +++++++ tools/auto-tester/src/TestRailInterface.cpp | 8 ++-- tools/auto-tester/src/TestRailInterface.h | 8 ++-- tools/auto-tester/src/ui/AutoTester.cpp | 8 ++++ tools/auto-tester/src/ui/AutoTester.h | 4 ++ tools/auto-tester/src/ui/AutoTester.ui | 41 ++++++++++++++++++--- 7 files changed, 80 insertions(+), 20 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 22ec78e284..c8ae75eee0 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -18,7 +18,6 @@ #include #include -#include "TestRailInterface.h" #include "ui/AutoTester.h" extern AutoTester* autoTester; @@ -839,16 +838,19 @@ void Test::createTestRailTestSuite() { } QString outputDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store generated files in", - parent, QFileDialog::ShowDirsOnly); + parent, QFileDialog::ShowDirsOnly); - // If user cancelled then restore previous selection and return + // If user cancelled then return if (outputDirectory == "") { return; } - TestRailInterface testRailInterface; - testRailInterface.createTestSuite(_testDirectory, outputDirectory, autoTester->getSelectedUser(), - autoTester->getSelectedBranch()); + if (_testRailCreateMode == PYTHON) { + ////createTestRailPythonTestSuite(); + } else { + _testRailInterface.createTestSuiteXML(_testDirectory, outputDirectory, autoTester->getSelectedUser(), + autoTester->getSelectedBranch()); + } } QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { @@ -919,3 +921,7 @@ QString Test::getExpectedImagePartialSourceDirectory(const QString& filename) { return result; } + +void Test::setTestRailCreateMode(TestRailCreateMode testRailCreateMode) { + _testRailCreateMode = testRailCreateMode; +} diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 3648906086..36b4cdd897 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -18,6 +18,7 @@ #include "ImageComparer.h" #include "ui/MismatchWindow.h" +#include "TestRailInterface.h" class Step { public: @@ -33,6 +34,11 @@ public: StepList stepList; }; +enum TestRailCreateMode { + PYTHON, + XML +}; + class Test { public: Test(); @@ -50,6 +56,7 @@ public: void createMDFile(const QString& topLevelDirectory); void createTestsOutline(); + void createTestRailTestSuite(); bool compareImageLists(bool isInteractiveMode, QProgressBar* progressBar); @@ -72,6 +79,8 @@ public: ExtractedText getTestScriptLines(QString testFileName); + void setTestRailCreateMode(TestRailCreateMode testRailCreateMode); + private: const QString TEST_FILENAME { "test.js" }; const QString TEST_RESULTS_FOLDER { "TestResults" }; @@ -116,6 +125,10 @@ private: const QString PATH_SEPARATOR{ "." }; bool _exitWhenComplete{ false }; + + TestRailInterface _testRailInterface; + + TestRailCreateMode _testRailCreateMode { PYTHON }; }; #endif // hifi_test_h \ No newline at end of file diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 189dc9a551..ee1969db44 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -16,10 +16,10 @@ #include #include -void TestRailInterface::createTestSuite(const QString& testDirectory, - const QString& outputDirectory, - const QString& user, - const QString& branch) { +void TestRailInterface::createTestSuiteXML(const QString& testDirectory, + const QString& outputDirectory, + const QString& user, + const QString& branch) { QDomProcessingInstruction instruction = document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); document.appendChild(instruction); diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 12e2f058c5..c0a61687e4 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -17,10 +17,10 @@ class TestRailInterface { public: - void createTestSuite(const QString& testDirectory, - const QString& outputDirectory, - const QString& user, - const QString& branch); + void createTestSuiteXML(const QString& testDirectory, + const QString& outputDirectory, + const QString& user, + const QString& branch); QDomElement processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element); QDomElement processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element); diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index b4dbb5a7da..02c3c49a53 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -100,6 +100,14 @@ void AutoTester::on_closeButton_clicked() { exit(0); } +void AutoTester::on_createPythonScriptRadioButton_clicked() { + _test->setTestRailCreateMode(PYTHON); +} + +void AutoTester::on_createXMLScriptRadioButton_clicked() { + _test->setTestRailCreateMode(XML); +} + void AutoTester::downloadImage(const QUrl& url) { _downloaders.emplace_back(new Downloader(url, this)); connect(_downloaders[_index], SIGNAL (downloaded()), _signalMapper, SLOT (map())); diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index cb99b0a79c..7f04bd1c49 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -46,9 +46,13 @@ private slots: void on_createAllMDFilesButton_clicked(); void on_createTestsOutlineButton_clicked(); void on_createTestRailTestSuiteButton_clicked(); + void on_hideTaskbarButton_clicked(); void on_showTaskbarButton_clicked(); + void on_createPythonScriptRadioButton_clicked(); + void on_createXMLScriptRadioButton_clicked(); + void on_closeButton_clicked(); void saveImage(int index); diff --git a/tools/auto-tester/src/ui/AutoTester.ui b/tools/auto-tester/src/ui/AutoTester.ui index ddc095ba23..9030016f34 100644 --- a/tools/auto-tester/src/ui/AutoTester.ui +++ b/tools/auto-tester/src/ui/AutoTester.ui @@ -6,8 +6,8 @@ 0 0 - 612 - 553 + 645 + 570 @@ -232,9 +232,9 @@ - 330 - 90 - 220 + 409 + 100 + 141 40 @@ -242,13 +242,42 @@ Create TestRail Test Suite + + + + 310 + 100 + 95 + 20 + + + + Python + + + true + + + + + + 310 + 120 + 95 + 20 + + + + XML + + 0 0 - 612 + 645 21 From aa57d359beba6c328e4d5cb204500481baa71fe6 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 25 Jul 2018 17:26:23 -0700 Subject: [PATCH 09/36] Adding interface to select TestRail user. --- tools/auto-tester/src/Test.cpp | 3 +- tools/auto-tester/src/TestRailInterface.cpp | 8 +- tools/auto-tester/src/TestRailInterface.h | 10 +- tools/auto-tester/src/ui/TestRailSelector.ui | 147 +++++++++++++++++++ 4 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 tools/auto-tester/src/ui/TestRailSelector.ui diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index c8ae75eee0..f708137305 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -846,7 +846,8 @@ void Test::createTestRailTestSuite() { } if (_testRailCreateMode == PYTHON) { - ////createTestRailPythonTestSuite(); + _testRailInterface.createTestSuitePython(_testDirectory, outputDirectory, autoTester->getSelectedUser(), + autoTester->getSelectedBranch()); } else { _testRailInterface.createTestSuiteXML(_testDirectory, outputDirectory, autoTester->getSelectedUser(), autoTester->getSelectedBranch()); diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index ee1969db44..4c7c1a4f27 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -16,7 +16,13 @@ #include #include -void TestRailInterface::createTestSuiteXML(const QString& testDirectory, +void TestRailInterface::createTestSuitePython(const QString& testDirectory, + const QString& outputDirectory, + const QString& user, + const QString& branch) { + } + + void TestRailInterface::createTestSuiteXML(const QString& testDirectory, const QString& outputDirectory, const QString& user, const QString& branch) { diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index c0a61687e4..a8edd1f8b7 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -22,7 +22,15 @@ public: const QString& user, const QString& branch); - QDomElement processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element); + void createTestSuitePython(const QString& testDirectory, + const QString& outputDirectory, + const QString& user, + const QString& branch); + + QDomElement processDirectory(const QString& directory, + const QString& user, + const QString& branch, + const QDomElement& element); QDomElement processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element); private: diff --git a/tools/auto-tester/src/ui/TestRailSelector.ui b/tools/auto-tester/src/ui/TestRailSelector.ui new file mode 100644 index 0000000000..695b374a50 --- /dev/null +++ b/tools/auto-tester/src/ui/TestRailSelector.ui @@ -0,0 +1,147 @@ + + + AutoTesterClass + + + + 0 + 0 + 314 + 259 + + + + AutoTester + + + + + + 20 + 130 + 101 + 40 + + + + OK + + + + + + 20 + 65 + 81 + 16 + + + + + 10 + + + + TestRail Branch + + + + + + 20 + 25 + 81 + 16 + + + + + 10 + + + + TestRail User + + + + + + 110 + 22 + 140 + 24 + + + + + + + 110 + 60 + 140 + 24 + + + + + + + 170 + 130 + 101 + 40 + + + + Cancel + + + + + + + 0 + 0 + 314 + 21 + + + + + File + + + + + + Help + + + + + + + + + TopToolBarArea + + + false + + + + + + Close + + + + + About + + + + + + + From db0969d1a718f42b6f54c03a2e9a6cc0faad9474 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 26 Jul 2018 09:16:14 -0700 Subject: [PATCH 10/36] Creates 'testrail.py' script in the output folder. --- tools/auto-tester/src/TestRailInterface.cpp | 119 +++++++++++++++++++- 1 file changed, 113 insertions(+), 6 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 4c7c1a4f27..2a8086b8c2 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -17,15 +17,122 @@ #include void TestRailInterface::createTestSuitePython(const QString& testDirectory, - const QString& outputDirectory, - const QString& user, - const QString& branch) { + const QString& outputDirectory, + const QString& user, + const QString& branch) { + + // Create the testrail.py script + // This is the file linked to from http://docs.gurock.com/testrail-api2/bindings-python + QFile file(outputDirectory + "/testrail.py"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not create \'testrail.py\'"); + exit(-1); + } + + QTextStream stream(&file); + + stream << "#\n"; + stream << "# TestRail API binding for Python 3.x (API v2, available since \n"; + stream << "# TestRail 3.0)\n"; + stream << "#\n"; + stream << "# Learn more:\n"; + stream << "#\n"; + stream << "# http://docs.gurock.com/testrail-api2/start\n"; + stream << "# http://docs.gurock.com/testrail-api2/accessing\n"; + stream << "#\n"; + stream << "# Copyright Gurock Software GmbH. See license.md for details.\n"; + stream << "#\n"; + stream << "\n"; + stream << "import urllib.request, urllib.error\n"; + stream << "import json, base64\n"; + stream << "\n"; + stream << "class APIClient:\n"; + stream << "\tdef __init__(self, base_url):\n"; + stream << "\t\tself.user = ''\n"; + stream << "\t\tself.password = ''\n"; + stream << "\t\tif not base_url.endswith('/'):\n"; + stream << "\t\t\tbase_url += '/'\n"; + stream << "\t\tself.__url = base_url + 'index.php?/api/v2/'\n"; + stream << "\n"; + stream << "\t#\n"; + stream << "\t# Send Get\n"; + stream << "\t#\n"; + stream << "\t# Issues a GET request (read) against the API and returns the result\n"; + stream << "\t# (as Python dict).\n"; + stream << "\t#\n"; + stream << "\t# Arguments:\n"; + stream << "\t#\n"; + stream << "\t# uri The API method to call including parameters\n"; + stream << "\t# (e.g. get_case/1)\n"; + stream << "\t#\n"; + stream << "\tdef send_get(self, uri):\n"; + stream << "\t\treturn self.__send_request('GET', uri, None)\n"; + stream << "\n"; + stream << "\t#\n"; + stream << "\t# Send POST\n"; + stream << "\t#\n"; + stream << "\t# Issues a POST request (write) against the API and returns the result\n"; + stream << "\t# (as Python dict).\n"; + stream << "\t#\n"; + stream << "\t# Arguments:\n"; + stream << "\t#\n"; + stream << "\t# uri The API method to call including parameters\n"; + stream << "\t# (e.g. add_case/1)\n"; + stream << "\t# data The data to submit as part of the request (as\n"; + stream << "\t# Python dict, strings must be UTF-8 encoded)\n"; + stream << "\t#\n"; + stream << "\tdef send_post(self, uri, data):\n"; + stream << "\t\treturn self.__send_request('POST', uri, data)\n"; + stream << "\n"; + stream << "\tdef __send_request(self, method, uri, data):\n"; + stream << "\t\turl = self.__url + uri\n"; + stream << "\t\trequest = urllib.request.Request(url)\n"; + stream << "\t\tif (method == 'POST'):\n"; + stream << "\t\t\trequest.data = bytes(json.dumps(data), 'utf-8')\n"; + stream << "\t\tauth = str(\n"; + stream << "\t\t\tbase64.b64encode(\n"; + stream << "\t\t\t\tbytes('%s:%s' % (self.user, self.password), 'utf-8')\n"; + stream << "\t\t\t),\n"; + stream << "\t\t\t'ascii'\n"; + stream << "\t\t).strip()\n"; + stream << "\t\trequest.add_header('Authorization', 'Basic %s' % auth)\n"; + stream << "\t\trequest.add_header('Content-Type', 'application/json')\n"; + stream << "\n"; + stream << "\t\te = None\n"; + stream << "\t\ttry:\n"; + stream << "\t\t\tresponse = urllib.request.urlopen(request).read()\n"; + stream << "\t\texcept urllib.error.HTTPError as ex:\n"; + stream << "\t\t\tresponse = ex.read()\n"; + stream << "\t\t\te = ex\n"; + stream << "\n"; + stream << "\t\tif response:\n"; + stream << "\t\t\tresult = json.loads(response.decode())\n"; + stream << "\t\telse:\n"; + stream << "\t\t\tresult = {}\n"; + stream << "\n"; + stream << "\t\tif e != None:\n"; + stream << "\t\t\tif result and 'error' in result:\n"; + stream << "\t\t\t\terror = \'\"\' + result[\'error\'] + \'\"\'\n"; + stream << "\t\t\telse:\n"; + stream << "\t\t\t\terror = \'No additional error message received\'\n"; + stream << "\t\t\traise APIError(\'TestRail API returned HTTP %s (%s)\' % \n"; + stream << "\t\t\t\t(e.code, error))\n"; + stream << "\n"; + stream << "\t\treturn result\n"; + stream << "\n"; + stream << "class APIError(Exception):\n"; + stream << "\tpass\n"; + + file.close(); + } void TestRailInterface::createTestSuiteXML(const QString& testDirectory, - const QString& outputDirectory, - const QString& user, - const QString& branch) { + const QString& outputDirectory, + const QString& user, + const QString& branch) { + QDomProcessingInstruction instruction = document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); document.appendChild(instruction); From 72d4e7dba204631e1b98ad9b921f70b923334379 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 26 Jul 2018 10:46:43 -0700 Subject: [PATCH 11/36] Refactoring. --- tools/auto-tester/src/TestRailInterface.cpp | 17 ++++++++++++----- tools/auto-tester/src/TestRailInterface.h | 4 ++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 2a8086b8c2..5f597734f6 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -16,11 +16,7 @@ #include #include -void TestRailInterface::createTestSuitePython(const QString& testDirectory, - const QString& outputDirectory, - const QString& user, - const QString& branch) { - +void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory) { // Create the testrail.py script // This is the file linked to from http://docs.gurock.com/testrail-api2/bindings-python QFile file(outputDirectory + "/testrail.py"); @@ -125,7 +121,18 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, stream << "\tpass\n"; file.close(); +} +void TestRailInterface::requestDataFromUser() { +} + +void TestRailInterface::createTestSuitePython(const QString& testDirectory, + const QString& outputDirectory, + const QString& user, + const QString& branch) { + + createTestRailDotPyScript(outputDirectory); + requestDataFromUser(); } void TestRailInterface::createTestSuiteXML(const QString& testDirectory, diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index a8edd1f8b7..eb562fa7c9 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -31,8 +31,12 @@ public: const QString& user, const QString& branch, const QDomElement& element); + QDomElement processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element); + void createTestRailDotPyScript(const QString& outputDirectory); + void requestDataFromUser(); + private: QDomDocument document; }; From 2dca95a146b12b01b0a2d4f6652ff45360f159df Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 26 Jul 2018 14:12:44 -0700 Subject: [PATCH 12/36] Working on TestRail, adding sections --- tools/auto-tester/src/TestRailInterface.cpp | 158 +++++++++++------- tools/auto-tester/src/TestRailInterface.h | 12 +- tools/auto-tester/src/ui/TestRailSelector.ui | 147 ---------------- .../src/ui/TestRailSelectorWindow.cpp | 52 ++++++ .../src/ui/TestRailSelectorWindow.h | 38 +++++ .../src/ui/TestRailSelectorWindow.ui | 151 +++++++++++++++++ 6 files changed, 350 insertions(+), 208 deletions(-) delete mode 100644 tools/auto-tester/src/ui/TestRailSelector.ui create mode 100644 tools/auto-tester/src/ui/TestRailSelectorWindow.cpp create mode 100644 tools/auto-tester/src/ui/TestRailSelectorWindow.h create mode 100644 tools/auto-tester/src/ui/TestRailSelectorWindow.ui diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 5f597734f6..7077b02aac 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -11,11 +11,20 @@ #include "TestRailInterface.h" #include "Test.h" +#include "ui/TestRailSelectorWindow.h" + #include #include #include #include +TestRailInterface::TestRailInterface() { + _testRailSelectorWindow.setModal(true); + + _testRailSelectorWindow.setURL("https://highfidelity.testrail.net/"); + _testRailSelectorWindow.setUser("@highfidelity.io"); +} + void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory) { // Create the testrail.py script // This is the file linked to from http://docs.gurock.com/testrail-api2/bindings-python @@ -124,6 +133,34 @@ void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory } void TestRailInterface::requestDataFromUser() { + _testRailSelectorWindow.exec(); + + if (_testRailSelectorWindow.getUserCancelled()) { + return; + } + + _url = _testRailSelectorWindow.getURL(); + _user = _testRailSelectorWindow.getUser(); + _password = _testRailSelectorWindow.getPassword(); +} + +void TestRailInterface::createAddSectionsPythonScript(const QString& outputDirectory) { + QFile file(outputDirectory + "/addSections.py"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not create \'addSections.py\'"); + exit(-1); + } + + QTextStream stream(&file); + + // Code to access TestRail + stream << "from testrail import *\n"; + stream << "client = APIClient(\'" << _url.toStdString().c_str() << "\')\n"; + stream << "client.user = \'" << _user << "\'\n"; + stream << "client.password = \'" << _password << "\'\n\n"; + + file.close(); } void TestRailInterface::createTestSuitePython(const QString& testDirectory, @@ -133,6 +170,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, createTestRailDotPyScript(outputDirectory); requestDataFromUser(); + createAddSectionsPythonScript(outputDirectory); } void TestRailInterface::createTestSuiteXML(const QString& testDirectory, @@ -140,20 +178,20 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, const QString& user, const QString& branch) { - QDomProcessingInstruction instruction = document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); - document.appendChild(instruction); + QDomProcessingInstruction instruction = _document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); + _document.appendChild(instruction); // We create a single section, within sections - QDomElement root = document.createElement("sections"); - document.appendChild(root); + QDomElement root = _document.createElement("sections"); + _document.appendChild(root); - QDomElement topLevelSection = document.createElement("section"); + QDomElement topLevelSection = _document.createElement("section"); - QDomElement suiteName = document.createElement("name"); - suiteName.appendChild(document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString())); + QDomElement suiteName = _document.createElement("name"); + suiteName.appendChild(_document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString())); topLevelSection.appendChild(suiteName); - QDomElement secondLevelSections = document.createElement("sections"); + QDomElement secondLevelSections = _document.createElement("sections"); topLevelSection.appendChild(processDirectory(testDirectory, user, branch, secondLevelSections)); topLevelSection.appendChild(secondLevelSections); @@ -168,7 +206,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, } QTextStream stream(&file); - stream << document.toString(); + stream << _document.toString(); file.close(); @@ -195,22 +233,22 @@ QDomElement TestRailInterface::processDirectory(const QString& directory, const // Create a section and process it - QDomElement sectionElement = document.createElement("section"); + QDomElement sectionElement = _document.createElement("section"); - QDomElement sectionElementName = document.createElement("name"); - sectionElementName.appendChild(document.createTextNode(objectName)); + QDomElement sectionElementName = _document.createElement("name"); + sectionElementName.appendChild(_document.createTextNode(objectName)); sectionElement.appendChild(sectionElementName); - QDomElement testsElement = document.createElement("sections"); + QDomElement testsElement = _document.createElement("sections"); sectionElement.appendChild(processDirectory(nextDirectory, user, branch, testsElement)); result.appendChild(sectionElement); } else if (objectName == "test.js" || objectName == "testStory.js") { - QDomElement sectionElement = document.createElement("section"); - QDomElement sectionElementName = document.createElement("name"); - sectionElementName.appendChild(document.createTextNode("all")); + QDomElement sectionElement = _document.createElement("section"); + QDomElement sectionElementName = _document.createElement("name"); + sectionElementName.appendChild(_document.createTextNode("all")); sectionElement.appendChild(sectionElementName); - sectionElement.appendChild(processTest(nextDirectory, objectName, user, branch, document.createElement("cases"))); + sectionElement.appendChild(processTest(nextDirectory, objectName, user, branch, _document.createElement("cases"))); result.appendChild(sectionElement); } } @@ -221,9 +259,9 @@ QDomElement TestRailInterface::processDirectory(const QString& directory, const QDomElement TestRailInterface::processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element) { QDomElement result = element; - QDomElement caseElement = document.createElement("case"); + QDomElement caseElement = _document.createElement("case"); - caseElement.appendChild(document.createElement("id")); + caseElement.appendChild(_document.createElement("id")); // The name of the test is derived from the full path. // The first term is the first word after "tests" @@ -244,83 +282,83 @@ QDomElement TestRailInterface::processTest(const QString& fullDirectory, const Q title += " / " + words[i]; } - QDomElement titleElement = document.createElement("title"); - titleElement.appendChild(document.createTextNode(title)); + QDomElement titleElement = _document.createElement("title"); + titleElement.appendChild(_document.createTextNode(title)); caseElement.appendChild(titleElement); - QDomElement templateElement = document.createElement("template"); - templateElement.appendChild(document.createTextNode("Test Case (Steps)")); + QDomElement templateElement = _document.createElement("template"); + templateElement.appendChild(_document.createTextNode("Test Case (Steps)")); caseElement.appendChild(templateElement); - QDomElement typeElement = document.createElement("type"); - typeElement.appendChild(document.createTextNode("3 - Regression")); + QDomElement typeElement = _document.createElement("type"); + typeElement.appendChild(_document.createTextNode("3 - Regression")); caseElement.appendChild(typeElement); - QDomElement priorityElement = document.createElement("priority"); - priorityElement.appendChild(document.createTextNode("Medium")); + QDomElement priorityElement = _document.createElement("priority"); + priorityElement.appendChild(_document.createTextNode("Medium")); caseElement.appendChild(priorityElement); - QDomElement estimateElementName = document.createElement("estimate"); - estimateElementName.appendChild(document.createTextNode("60")); + QDomElement estimateElementName = _document.createElement("estimate"); + estimateElementName.appendChild(_document.createTextNode("60")); caseElement.appendChild(estimateElementName); - caseElement.appendChild(document.createElement("references")); + caseElement.appendChild(_document.createElement("references")); - QDomElement customElement = document.createElement("custom"); + QDomElement customElement = _document.createElement("custom"); - QDomElement tester_countElement = document.createElement("tester_count"); - tester_countElement.appendChild(document.createTextNode("1")); + QDomElement tester_countElement = _document.createElement("tester_count"); + tester_countElement.appendChild(_document.createTextNode("1")); customElement.appendChild(tester_countElement); - QDomElement domain_bot_loadElement = document.createElement("domain_bot_load"); - QDomElement domain_bot_loadElementId = document.createElement("id"); - domain_bot_loadElementId.appendChild(document.createTextNode("1")); + QDomElement domain_bot_loadElement = _document.createElement("domain_bot_load"); + QDomElement domain_bot_loadElementId = _document.createElement("id"); + domain_bot_loadElementId.appendChild(_document.createTextNode("1")); domain_bot_loadElement.appendChild(domain_bot_loadElementId); - QDomElement domain_bot_loadElementValue = document.createElement("value"); - domain_bot_loadElementValue.appendChild(document.createTextNode(" Without Bots (hifiqa-rc / hifi-qa-stable / hifiqa-master)")); + QDomElement domain_bot_loadElementValue = _document.createElement("value"); + domain_bot_loadElementValue.appendChild(_document.createTextNode(" Without Bots (hifiqa-rc / hifi-qa-stable / hifiqa-master)")); domain_bot_loadElement.appendChild(domain_bot_loadElementValue); customElement.appendChild(domain_bot_loadElement); - QDomElement automation_typeElement = document.createElement("automation_type"); - QDomElement automation_typeElementId = document.createElement("id"); - automation_typeElementId.appendChild(document.createTextNode("0")); + QDomElement automation_typeElement = _document.createElement("automation_type"); + QDomElement automation_typeElementId = _document.createElement("id"); + automation_typeElementId.appendChild(_document.createTextNode("0")); automation_typeElement.appendChild(automation_typeElementId); - QDomElement automation_typeElementValue = document.createElement("value"); - automation_typeElementValue.appendChild(document.createTextNode("None")); + QDomElement automation_typeElementValue = _document.createElement("value"); + automation_typeElementValue.appendChild(_document.createTextNode("None")); automation_typeElement.appendChild(automation_typeElementValue); customElement.appendChild(automation_typeElement); - QDomElement added_to_releaseElement = document.createElement("added_to_release"); - QDomElement added_to_releaseElementId = document.createElement("id"); - added_to_releaseElementId.appendChild(document.createTextNode("4")); + QDomElement added_to_releaseElement = _document.createElement("added_to_release"); + QDomElement added_to_releaseElementId = _document.createElement("id"); + added_to_releaseElementId.appendChild(_document.createTextNode("4")); added_to_releaseElement.appendChild(added_to_releaseElementId); - QDomElement added_to_releaseElementValue = document.createElement("value"); - added_to_releaseElementValue.appendChild(document.createTextNode(branch)); + QDomElement added_to_releaseElementValue = _document.createElement("value"); + added_to_releaseElementValue.appendChild(_document.createTextNode(branch)); added_to_releaseElement.appendChild(added_to_releaseElementValue); customElement.appendChild(added_to_releaseElement); - QDomElement precondsElement = document.createElement("preconds"); - precondsElement.appendChild(document.createTextNode("Tester is in an empty region of a domain in which they have edit rights\n\n*Note: Press 'n' to advance test script")); + QDomElement precondsElement = _document.createElement("preconds"); + precondsElement.appendChild(_document.createTextNode("Tester is in an empty region of a domain in which they have edit rights\n\n*Note: Press 'n' to advance test script")); customElement.appendChild(precondsElement); QString testMDName = QString("https://github.com/") + user + "/hifi_tests/blob/" + branch + "/tests/content/entity/light/point/create/test.md"; - QDomElement steps_seperatedElement = document.createElement("steps_separated"); - QDomElement stepElement = document.createElement("step"); - QDomElement stepIndexElement = document.createElement("index"); - stepIndexElement.appendChild(document.createTextNode("1")); + QDomElement steps_seperatedElement = _document.createElement("steps_separated"); + QDomElement stepElement = _document.createElement("step"); + QDomElement stepIndexElement = _document.createElement("index"); + stepIndexElement.appendChild(_document.createTextNode("1")); stepElement.appendChild(stepIndexElement); - QDomElement stepContentElement = document.createElement("content"); - stepContentElement.appendChild(document.createTextNode(QString("Execute instructions in [THIS TEST](") + testMDName + ")")); + QDomElement stepContentElement = _document.createElement("content"); + stepContentElement.appendChild(_document.createTextNode(QString("Execute instructions in [THIS TEST](") + testMDName + ")")); stepElement.appendChild(stepContentElement); - QDomElement stepExpectedElement = document.createElement("expected"); - stepExpectedElement.appendChild(document.createTextNode("Refer to the expected result in the linked description.")); + QDomElement stepExpectedElement = _document.createElement("expected"); + stepExpectedElement.appendChild(_document.createTextNode("Refer to the expected result in the linked description.")); stepElement.appendChild(stepExpectedElement); steps_seperatedElement.appendChild(stepElement); customElement.appendChild(steps_seperatedElement); - QDomElement notesElement = document.createElement("notes"); - notesElement.appendChild(document.createTextNode(testMDName)); + QDomElement notesElement = _document.createElement("notes"); + notesElement.appendChild(_document.createTextNode(testMDName)); customElement.appendChild(notesElement); caseElement.appendChild(customElement); diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index eb562fa7c9..6c98ddf430 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -11,12 +11,15 @@ #ifndef hifi_test_testrail_interface_h #define hifi_test_testrail_interface_h +#include "ui/TestRailSelectorWindow.h" #include #include #include class TestRailInterface { public: + TestRailInterface(); + void createTestSuiteXML(const QString& testDirectory, const QString& outputDirectory, const QString& user, @@ -36,9 +39,16 @@ public: void createTestRailDotPyScript(const QString& outputDirectory); void requestDataFromUser(); + void createAddSectionsPythonScript(const QString& outputDirectory); private: - QDomDocument document; + QDomDocument _document; + + TestRailSelectorWindow _testRailSelectorWindow; + + QString _url; + QString _user; + QString _password; }; #endif \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailSelector.ui b/tools/auto-tester/src/ui/TestRailSelector.ui deleted file mode 100644 index 695b374a50..0000000000 --- a/tools/auto-tester/src/ui/TestRailSelector.ui +++ /dev/null @@ -1,147 +0,0 @@ - - - AutoTesterClass - - - - 0 - 0 - 314 - 259 - - - - AutoTester - - - - - - 20 - 130 - 101 - 40 - - - - OK - - - - - - 20 - 65 - 81 - 16 - - - - - 10 - - - - TestRail Branch - - - - - - 20 - 25 - 81 - 16 - - - - - 10 - - - - TestRail User - - - - - - 110 - 22 - 140 - 24 - - - - - - - 110 - 60 - 140 - 24 - - - - - - - 170 - 130 - 101 - 40 - - - - Cancel - - - - - - - 0 - 0 - 314 - 21 - - - - - File - - - - - - Help - - - - - - - - - TopToolBarArea - - - false - - - - - - Close - - - - - About - - - - - - - diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp new file mode 100644 index 0000000000..ff3cf05ed4 --- /dev/null +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp @@ -0,0 +1,52 @@ +// +// TestRailSelectorWindow.cpp +// +// Created by Nissim Hadar on 26 Jul 2017. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "TestRailSelectorWindow.h" + +#include + +#include + +TestRailSelectorWindow::TestRailSelectorWindow(QWidget *parent) { + setupUi(this); +} + +void TestRailSelectorWindow::on_OKButton_clicked() { + userCancelled = false; + close(); +} + +void TestRailSelectorWindow::on_cancelButton_clicked() { + userCancelled = true; + close(); +} + +bool TestRailSelectorWindow::getUserCancelled() { + return userCancelled; +} + +void TestRailSelectorWindow::setURL(const QString& user) { + URLTextEdit->setText(user); +} + +QString TestRailSelectorWindow::getURL() { + return URLTextEdit->toPlainText(); +} + +void TestRailSelectorWindow::setUser(const QString& user) { + UserTextEdit->setText(user); +} + +QString TestRailSelectorWindow::getUser() { + return UserTextEdit->toPlainText(); +} + +QString TestRailSelectorWindow::getPassword() { + return passwordLineEdit->text(); +} \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.h b/tools/auto-tester/src/ui/TestRailSelectorWindow.h new file mode 100644 index 0000000000..587e3401b8 --- /dev/null +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.h @@ -0,0 +1,38 @@ +// +// TestRailSelectorWindow.h +// +// Created by Nissim Hadar on 26 Jul 2017. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_TestRailSelectorWindow_h +#define hifi_TestRailSelectorWindow_h + +#include "ui_TestRailSelectorWindow.h" + +class TestRailSelectorWindow : public QDialog, public Ui::TestRailSelectorWindow { + Q_OBJECT + +public: + TestRailSelectorWindow(QWidget* parent = Q_NULLPTR); + + bool getUserCancelled(); + + void setURL(const QString& user); + QString getURL(); + + void setUser(const QString& user); + QString getUser(); + + QString getPassword(); + + bool userCancelled{ false }; + +private slots: + void on_OKButton_clicked(); + void on_cancelButton_clicked(); +}; + +#endif \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui new file mode 100644 index 0000000000..e05e2b6370 --- /dev/null +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui @@ -0,0 +1,151 @@ + + + TestRailSelectorWindow + + + + 0 + 0 + 489 + 312 + + + + MismatchWindow + + + + + 30 + 850 + 500 + 28 + + + + + 12 + + + + similarity + + + + + + 70 + 115 + 121 + 20 + + + + + 10 + + + + TestRail Password + + + + + + 70 + 25 + 121 + 20 + + + + + 10 + + + + TestRail URL + + + + + + 200 + 25 + 231 + 24 + + + + + + + 120 + 200 + 93 + 28 + + + + OK + + + + + + 280 + 200 + 93 + 28 + + + + Cancel + + + + + + 200 + 115 + 231 + 24 + + + + QLineEdit::Password + + + + + + 200 + 70 + 231 + 24 + + + + + + + 70 + 70 + 121 + 20 + + + + + 10 + + + + TestRail User + + + + + + + From 99ba550af5eb7b37e66c487df88c28242137e347 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 26 Jul 2018 15:00:02 -0700 Subject: [PATCH 13/36] WIP --- tools/auto-tester/src/TestRailInterface.cpp | 6 ++- .../src/ui/TestRailSelectorWindow.cpp | 16 ++++++-- .../src/ui/TestRailSelectorWindow.h | 3 ++ .../src/ui/TestRailSelectorWindow.ui | 37 +++++++++++++++++-- 4 files changed, 55 insertions(+), 7 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 7077b02aac..948da59947 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -160,6 +160,10 @@ void TestRailInterface::createAddSectionsPythonScript(const QString& outputDirec stream << "client.user = \'" << _user << "\'\n"; stream << "client.password = \'" << _password << "\'\n\n"; + // top-level section + stream << "data = { \'name\': \'" + << "Test Suite - " << QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm") << "\'}\n"; + file.close(); } @@ -188,7 +192,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, QDomElement topLevelSection = _document.createElement("section"); QDomElement suiteName = _document.createElement("name"); - suiteName.appendChild(_document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString())); + suiteName.appendChild(_document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm"))); topLevelSection.appendChild(suiteName); QDomElement secondLevelSections = _document.createElement("sections"); diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp index ff3cf05ed4..b7232837c8 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp @@ -15,6 +15,8 @@ TestRailSelectorWindow::TestRailSelectorWindow(QWidget *parent) { setupUi(this); + + projectLineEdit->setValidator(new QIntValidator(1, 999, this)); } void TestRailSelectorWindow::on_OKButton_clicked() { @@ -40,13 +42,21 @@ QString TestRailSelectorWindow::getURL() { } void TestRailSelectorWindow::setUser(const QString& user) { - UserTextEdit->setText(user); + userTextEdit->setText(user); } QString TestRailSelectorWindow::getUser() { - return UserTextEdit->toPlainText(); + return userTextEdit->toPlainText(); } QString TestRailSelectorWindow::getPassword() { return passwordLineEdit->text(); -} \ No newline at end of file +} + +void TestRailSelectorWindow::setProject(const int project) { + projectLineEdit->setText(QString::number(project)); +} + +int TestRailSelectorWindow::getProject() { + return projectLineEdit->getText().toInt(); +} diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.h b/tools/auto-tester/src/ui/TestRailSelectorWindow.h index 587e3401b8..821102b6bc 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.h +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.h @@ -28,6 +28,9 @@ public: QString getPassword(); + void setProject(const int project); + int getProject(); + bool userCancelled{ false }; private slots: diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui index e05e2b6370..dfc477deb0 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui @@ -81,7 +81,7 @@ 120 - 200 + 240 93 28 @@ -94,7 +94,7 @@ 280 - 200 + 240 93 28 @@ -116,7 +116,7 @@ QLineEdit::Password - + 200 @@ -144,6 +144,37 @@ TestRail User + + + + 200 + 160 + 231 + 24 + + + + QLineEdit::Normal + + + + + + 70 + 160 + 121 + 20 + + + + + 10 + + + + TestRail Project + + From 91c04bb6391b713652ae387e7808ff3fae9a0205 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 26 Jul 2018 17:21:43 -0700 Subject: [PATCH 14/36] Working on creating sections in TestRail. --- tools/auto-tester/src/TestRailInterface.cpp | 3 +++ tools/auto-tester/src/ui/TestRailSelectorWindow.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 948da59947..d81077c0dc 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -23,6 +23,9 @@ TestRailInterface::TestRailInterface() { _testRailSelectorWindow.setURL("https://highfidelity.testrail.net/"); _testRailSelectorWindow.setUser("@highfidelity.io"); + + // 24 is the HighFidelity Interface project id in TestRail + _testRailSelectorWindow.setProject(24); } void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory) { diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp index b7232837c8..b2555ae4ad 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp @@ -58,5 +58,5 @@ void TestRailSelectorWindow::setProject(const int project) { } int TestRailSelectorWindow::getProject() { - return projectLineEdit->getText().toInt(); + return projectLineEdit->text().toInt(); } From be79fa9e31c509b31233c85825b94724c10a7d96 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 27 Jul 2018 09:04:37 -0700 Subject: [PATCH 15/36] Added creation of a python stack class --- tools/auto-tester/src/TestRailInterface.cpp | 49 ++++++++++++++++++++- tools/auto-tester/src/TestRailInterface.h | 2 + 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index d81077c0dc..66d42e9ab7 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -28,9 +28,9 @@ TestRailInterface::TestRailInterface() { _testRailSelectorWindow.setProject(24); } +// Creates the testrail.py script +// This is the file linked to from http://docs.gurock.com/testrail-api2/bindings-python void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory) { - // Create the testrail.py script - // This is the file linked to from http://docs.gurock.com/testrail-api2/bindings-python QFile file(outputDirectory + "/testrail.py"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), @@ -135,6 +135,46 @@ void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory file.close(); } +// Creates a Stack class +void TestRailInterface::createStackDotPyScript(const QString& outputDirectory) { + QFile file(outputDirectory + "/stack.py"); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not create \'stack.py\'"); + exit(-1); + } + + QTextStream stream(&file); + + stream << "class Stack:\n"; + + stream << "\tdef __init__(self):\n"; + stream << "\t\tself.items = []\n"; + stream << "\n"; + + stream << "\tdef isEmpty(self):\n"; + stream << "\t\treturn self.items == []\n"; + stream << "\n"; + + stream << "\tdef push(self, item):\n"; + stream << "\t\tself.items.append(item)\n"; + stream << "\n"; + + stream << "\tdef pop(self):\n"; + stream << "\t\treturn self.items.pop()\n"; + stream << "\n"; + + stream << "\tdef peek(self):\n"; + stream << "\t\treturn self.items[len(self.items)-1]\n"; + stream << "\n"; + + stream << "\tdef size(self):\n"; + stream << "\t\treturn len(self.items)\n"; + stream << "\n"; + + file.close(); +} + void TestRailInterface::requestDataFromUser() { _testRailSelectorWindow.exec(); @@ -145,6 +185,7 @@ void TestRailInterface::requestDataFromUser() { _url = _testRailSelectorWindow.getURL(); _user = _testRailSelectorWindow.getUser(); _password = _testRailSelectorWindow.getPassword(); + _project = _testRailSelectorWindow.getProject(); } void TestRailInterface::createAddSectionsPythonScript(const QString& outputDirectory) { @@ -163,10 +204,13 @@ void TestRailInterface::createAddSectionsPythonScript(const QString& outputDirec stream << "client.user = \'" << _user << "\'\n"; stream << "client.password = \'" << _password << "\'\n\n"; + // top-level section stream << "data = { \'name\': \'" << "Test Suite - " << QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm") << "\'}\n"; + stream << "section = client.send_post(\'add_section/\' + str(" << QString::number(_project) << "), data)"; + file.close(); } @@ -176,6 +220,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, const QString& branch) { createTestRailDotPyScript(outputDirectory); + createStackDotPyScript(outputDirectory); requestDataFromUser(); createAddSectionsPythonScript(outputDirectory); } diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 6c98ddf430..171a716a32 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -38,6 +38,7 @@ public: QDomElement processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element); void createTestRailDotPyScript(const QString& outputDirectory); + void createStackDotPyScript(const QString& outputDirectory); void requestDataFromUser(); void createAddSectionsPythonScript(const QString& outputDirectory); @@ -49,6 +50,7 @@ private: QString _url; QString _user; QString _password; + int _project; }; #endif \ No newline at end of file From 7bb6d8dc823ed1516741bc25b61eb4c7bedee72c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 27 Jul 2018 12:41:11 -0700 Subject: [PATCH 16/36] Can now create first level of sub-sections. --- tools/auto-tester/src/TestRailInterface.cpp | 85 ++++++++++++++++----- tools/auto-tester/src/TestRailInterface.h | 17 +++-- 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 66d42e9ab7..04977f473e 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -21,11 +21,14 @@ TestRailInterface::TestRailInterface() { _testRailSelectorWindow.setModal(true); - _testRailSelectorWindow.setURL("https://highfidelity.testrail.net/"); - _testRailSelectorWindow.setUser("@highfidelity.io"); + ////_testRailSelectorWindow.setURL("https://highfidelity.testrail.net"); + _testRailSelectorWindow.setURL("https://nissimhadar.testrail.io"); + ////_testRailSelectorWindow.setUser("@highfidelity.io"); + _testRailSelectorWindow.setUser("nissim.hadar@gmail.com"); // 24 is the HighFidelity Interface project id in TestRail - _testRailSelectorWindow.setProject(24); + ////_testRailSelectorWindow.setProject(24); + _testRailSelectorWindow.setProject(1); } // Creates the testrail.py script @@ -152,7 +155,7 @@ void TestRailInterface::createStackDotPyScript(const QString& outputDirectory) { stream << "\t\tself.items = []\n"; stream << "\n"; - stream << "\tdef isEmpty(self):\n"; + stream << "\tdef is_empty(self):\n"; stream << "\t\treturn self.items == []\n"; stream << "\n"; @@ -182,13 +185,54 @@ void TestRailInterface::requestDataFromUser() { return; } - _url = _testRailSelectorWindow.getURL(); + _url = _testRailSelectorWindow.getURL() + "/"; _user = _testRailSelectorWindow.getUser(); - _password = _testRailSelectorWindow.getPassword(); - _project = _testRailSelectorWindow.getProject(); + ////_password = _testRailSelectorWindow.getPassword(); + _password = "tutKA76"; + _project = QString::number(_testRailSelectorWindow.getProject()); } -void TestRailInterface::createAddSectionsPythonScript(const QString& outputDirectory) { +bool TestRailInterface::isAValidTestDirectory(const QString& directory) { + if (Test::isAValidDirectory(directory)) { + // Ignore the utils and preformance directories + if (directory.right(QString("utils").length()) == "utils" || + directory.right(QString("performance").length()) == "performance") { + return false; + } + return true; + } + + return false; +} + +void TestRailInterface::processDirecoryPython(const QString& directory, QTextStream& stream) { + // Loop over all entries in directory + QDirIterator it(directory.toStdString().c_str()); + while (it.hasNext()) { + QString nextDirectory = it.next(); + + // Only process directories + if (!isAValidTestDirectory(nextDirectory)) { + continue; + } + + // The name of the section is the directory at the end of the path + stream << "parent_id = parent_ids.peek()\n"; + QString name = nextDirectory.right(nextDirectory.length() - nextDirectory.lastIndexOf("/") - 1); + stream << "data = { \'name\': \'" << name << "\', \'parent_id\': parent_id }\n"; + + stream << "section = client.send_post(\'add_section/\' + str(" << _project << "), data)\n"; + } +} + + // A suite of TestRail test cases contains trees. +// The nodes of the trees are sections +// The leaves are the test cases +// +// Each node and leaf have an ID and a parent ID. +// Therefore, the tree is built top-down, using a stack to store the IDs of each node +// +void TestRailInterface::createAddSectionsPythonScript(const QString& testDirectory, const QString& outputDirectory) { QFile file(outputDirectory + "/addSections.py"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), @@ -204,12 +248,18 @@ void TestRailInterface::createAddSectionsPythonScript(const QString& outputDirec stream << "client.user = \'" << _user << "\'\n"; stream << "client.password = \'" << _password << "\'\n\n"; + stream << "from stack import *\n"; + stream << "parent_ids = Stack()\n\n"; // top-level section stream << "data = { \'name\': \'" << "Test Suite - " << QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm") << "\'}\n"; - stream << "section = client.send_post(\'add_section/\' + str(" << QString::number(_project) << "), data)"; + stream << "section = client.send_post(\'add_section/\' + str(" << _project << "), data)\n"; + stream << "parent_ids.push(section[\'id\'])\n\n"; + + // Now recursively process each directory + processDirecoryPython(testDirectory, stream); file.close(); } @@ -222,7 +272,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, createTestRailDotPyScript(outputDirectory); createStackDotPyScript(outputDirectory); requestDataFromUser(); - createAddSectionsPythonScript(outputDirectory); + createAddSectionsPythonScript(testDirectory, outputDirectory); } void TestRailInterface::createTestSuiteXML(const QString& testDirectory, @@ -243,8 +293,9 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, suiteName.appendChild(_document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm"))); topLevelSection.appendChild(suiteName); + // This is the first call to 'process'. This is then called recursively to build the full XML tree QDomElement secondLevelSections = _document.createElement("sections"); - topLevelSection.appendChild(processDirectory(testDirectory, user, branch, secondLevelSections)); + topLevelSection.appendChild(processDirectoryXML(testDirectory, user, branch, secondLevelSections)); topLevelSection.appendChild(secondLevelSections); root.appendChild(topLevelSection); @@ -265,7 +316,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, QMessageBox::information(0, "Success", "TestRail XML file has been created"); } -QDomElement TestRailInterface::processDirectory(const QString& directory, const QString& user, const QString& branch, const QDomElement& element) { +QDomElement TestRailInterface::processDirectoryXML(const QString& directory, const QString& user, const QString& branch, const QDomElement& element) { QDomElement result = element; // Loop over all entries in directory @@ -277,14 +328,8 @@ QDomElement TestRailInterface::processDirectory(const QString& directory, const QString objectName = nextDirectory.right(nextDirectory.length() - nextDirectory.lastIndexOf("/") - 1); // Only process directories - if (Test::isAValidDirectory(nextDirectory)) { - // Ignore the utils and preformance directories - if (nextDirectory.right(QString("utils").length()) == "utils" || nextDirectory.right(QString("performance").length()) == "performance") { - continue; - } - + if (isAValidTestDirectory(nextDirectory)) { // Create a section and process it - QDomElement sectionElement = _document.createElement("section"); QDomElement sectionElementName = _document.createElement("name"); @@ -292,7 +337,7 @@ QDomElement TestRailInterface::processDirectory(const QString& directory, const sectionElement.appendChild(sectionElementName); QDomElement testsElement = _document.createElement("sections"); - sectionElement.appendChild(processDirectory(nextDirectory, user, branch, testsElement)); + sectionElement.appendChild(processDirectoryXML(nextDirectory, user, branch, testsElement)); result.appendChild(sectionElement); } else if (objectName == "test.js" || objectName == "testStory.js") { diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 171a716a32..3285281577 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -30,17 +30,22 @@ public: const QString& user, const QString& branch); - QDomElement processDirectory(const QString& directory, - const QString& user, - const QString& branch, - const QDomElement& element); + QDomElement processDirectoryXML(const QString& directory, + const QString& user, + const QString& branch, + const QDomElement& element); QDomElement processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element); void createTestRailDotPyScript(const QString& outputDirectory); void createStackDotPyScript(const QString& outputDirectory); void requestDataFromUser(); - void createAddSectionsPythonScript(const QString& outputDirectory); + void createAddSectionsPythonScript(const QString& testDirectory, const QString& outputDirectory); + + void processDirecoryPython(const QString& directory, QTextStream& stream); + + bool isAValidTestDirectory(const QString& directory); + private: QDomDocument _document; @@ -50,7 +55,7 @@ private: QString _url; QString _user; QString _password; - int _project; + QString _project; }; #endif \ No newline at end of file From 066b1acd9431a60fbf71a072d5fe144d76c94b0a Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 27 Jul 2018 13:35:31 -0700 Subject: [PATCH 17/36] Can write all the sections (sans tests themselves). --- tools/auto-tester/src/TestRailInterface.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 04977f473e..5a63576733 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -222,7 +222,14 @@ void TestRailInterface::processDirecoryPython(const QString& directory, QTextStr stream << "data = { \'name\': \'" << name << "\', \'parent_id\': parent_id }\n"; stream << "section = client.send_post(\'add_section/\' + str(" << _project << "), data)\n"; + + // Now we push the parent_id, and recursively process each directory + stream << "parent_ids.push(section[\'id\'])\n\n"; + processDirecoryPython(nextDirectory, stream); } + + // pop the parent directory before leaving + stream << "parent_ids.pop()\n\n"; } // A suite of TestRail test cases contains trees. @@ -256,9 +263,9 @@ void TestRailInterface::createAddSectionsPythonScript(const QString& testDirecto << "Test Suite - " << QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm") << "\'}\n"; stream << "section = client.send_post(\'add_section/\' + str(" << _project << "), data)\n"; - stream << "parent_ids.push(section[\'id\'])\n\n"; - // Now recursively process each directory + // Now we push the parent_id, and recursively process each directory + stream << "parent_ids.push(section[\'id\'])\n\n"; processDirecoryPython(testDirectory, stream); file.close(); From 35464c4ca4d8a2151dd869d05b0f0609deaf0e54 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 27 Jul 2018 15:10:06 -0700 Subject: [PATCH 18/36] Can add tests (include only the preconditions) --- tools/auto-tester/src/TestRailInterface.cpp | 101 +++++++++++++------- tools/auto-tester/src/TestRailInterface.h | 12 ++- 2 files changed, 78 insertions(+), 35 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 5a63576733..987ce5a739 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -31,13 +31,17 @@ TestRailInterface::TestRailInterface() { _testRailSelectorWindow.setProject(1); } +QString TestRailInterface::getObject(const QString& path) { + return path.right(path.length() - path.lastIndexOf("/") - 1); +} + // Creates the testrail.py script // This is the file linked to from http://docs.gurock.com/testrail-api2/bindings-python void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory) { QFile file(outputDirectory + "/testrail.py"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Could not create \'testrail.py\'"); + "Could not create 'testrail.py'"); exit(-1); } @@ -124,10 +128,10 @@ void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory stream << "\n"; stream << "\t\tif e != None:\n"; stream << "\t\t\tif result and 'error' in result:\n"; - stream << "\t\t\t\terror = \'\"\' + result[\'error\'] + \'\"\'\n"; + stream << "\t\t\t\terror = '\"' + result['error'] + '\"'\n"; stream << "\t\t\telse:\n"; - stream << "\t\t\t\terror = \'No additional error message received\'\n"; - stream << "\t\t\traise APIError(\'TestRail API returned HTTP %s (%s)\' % \n"; + stream << "\t\t\t\terror = 'No additional error message received'\n"; + stream << "\t\t\traise APIError('TestRail API returned HTTP %s (%s)' % \n"; stream << "\t\t\t\t(e.code, error))\n"; stream << "\n"; stream << "\t\treturn result\n"; @@ -143,7 +147,7 @@ void TestRailInterface::createStackDotPyScript(const QString& outputDirectory) { QFile file(outputDirectory + "/stack.py"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Could not create \'stack.py\'"); + "Could not create 'stack.py'"); exit(-1); } @@ -205,27 +209,27 @@ bool TestRailInterface::isAValidTestDirectory(const QString& directory) { return false; } -void TestRailInterface::processDirecoryPython(const QString& directory, QTextStream& stream) { +void TestRailInterface::processDirectoryPython(const QString& directory, QTextStream& stream) { // Loop over all entries in directory QDirIterator it(directory.toStdString().c_str()); while (it.hasNext()) { QString nextDirectory = it.next(); - // Only process directories - if (!isAValidTestDirectory(nextDirectory)) { - continue; + QString objectName = getObject(nextDirectory); + + if (isAValidTestDirectory(nextDirectory)) { + // The name of the section is the directory at the end of the path + stream << "parent_id = parent_ids.peek()\n"; + stream << "data = { 'name': '" << objectName << "', 'parent_id': parent_id }\n"; + + stream << "section = client.send_post('add_section/' + str(" << _project << "), data)\n"; + + // Now we push the parent_id, and recursively process each directory + stream << "parent_ids.push(section['id'])\n\n"; + processDirectoryPython(nextDirectory, stream); + } else if (objectName == "test.js" || objectName == "testStory.js") { + processTestPython(nextDirectory, stream); } - - // The name of the section is the directory at the end of the path - stream << "parent_id = parent_ids.peek()\n"; - QString name = nextDirectory.right(nextDirectory.length() - nextDirectory.lastIndexOf("/") - 1); - stream << "data = { \'name\': \'" << name << "\', \'parent_id\': parent_id }\n"; - - stream << "section = client.send_post(\'add_section/\' + str(" << _project << "), data)\n"; - - // Now we push the parent_id, and recursively process each directory - stream << "parent_ids.push(section[\'id\'])\n\n"; - processDirecoryPython(nextDirectory, stream); } // pop the parent directory before leaving @@ -243,7 +247,7 @@ void TestRailInterface::createAddSectionsPythonScript(const QString& testDirecto QFile file(outputDirectory + "/addSections.py"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Could not create \'addSections.py\'"); + "Could not create 'addSections.py'"); exit(-1); } @@ -251,24 +255,26 @@ void TestRailInterface::createAddSectionsPythonScript(const QString& testDirecto // Code to access TestRail stream << "from testrail import *\n"; - stream << "client = APIClient(\'" << _url.toStdString().c_str() << "\')\n"; - stream << "client.user = \'" << _user << "\'\n"; - stream << "client.password = \'" << _password << "\'\n\n"; + stream << "client = APIClient('" << _url.toStdString().c_str() << "')\n"; + stream << "client.user = '" << _user << "'\n"; + stream << "client.password = '" << _password << "'\n\n"; stream << "from stack import *\n"; stream << "parent_ids = Stack()\n\n"; // top-level section - stream << "data = { \'name\': \'" - << "Test Suite - " << QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm") << "\'}\n"; + stream << "data = { 'name': '" + << "Test Suite - " << QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm") << "'}\n"; - stream << "section = client.send_post(\'add_section/\' + str(" << _project << "), data)\n"; + stream << "section = client.send_post('add_section/' + str(" << _project << "), data)\n"; // Now we push the parent_id, and recursively process each directory - stream << "parent_ids.push(section[\'id\'])\n\n"; - processDirecoryPython(testDirectory, stream); + stream << "parent_ids.push(section['id'])\n\n"; + processDirectoryPython(testDirectory, stream); file.close(); + + QMessageBox::information(0, "Success", "TestRail Python script has been created"); } void TestRailInterface::createTestSuitePython(const QString& testDirectory, @@ -332,7 +338,7 @@ QDomElement TestRailInterface::processDirectoryXML(const QString& directory, con QString nextDirectory = it.next(); // The object name appears after the last slash (we are assured there is at least 1). - QString objectName = nextDirectory.right(nextDirectory.length() - nextDirectory.lastIndexOf("/") - 1); + QString objectName = getObject(nextDirectory); // Only process directories if (isAValidTestDirectory(nextDirectory)) { @@ -352,7 +358,7 @@ QDomElement TestRailInterface::processDirectoryXML(const QString& directory, con QDomElement sectionElementName = _document.createElement("name"); sectionElementName.appendChild(_document.createTextNode("all")); sectionElement.appendChild(sectionElementName); - sectionElement.appendChild(processTest(nextDirectory, objectName, user, branch, _document.createElement("cases"))); + sectionElement.appendChild(processTestXML(nextDirectory, objectName, user, branch, _document.createElement("cases"))); result.appendChild(sectionElement); } } @@ -360,7 +366,7 @@ QDomElement TestRailInterface::processDirectoryXML(const QString& directory, con return result; } -QDomElement TestRailInterface::processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element) { +QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element) { QDomElement result = element; QDomElement caseElement = _document.createElement("case"); @@ -470,4 +476,35 @@ QDomElement TestRailInterface::processTest(const QString& fullDirectory, const Q result.appendChild(caseElement); return result; +} + +void TestRailInterface::processTestPython(const QString& fullDirectory, QTextStream& stream) { + // The name of the test is derived from the full path. + // The first term is the first word after "tests" + // The last word is the penultimate word + QStringList words = fullDirectory.split('/'); + int i = 0; + while (words[i] != "tests") { + ++i; + if (i >= words.length() - 1) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Folder \"tests\" not found in " + fullDirectory); + exit(-1); + } + } + + ++i; + QString title{ words[i] }; + for (++i; i < words.length() - 1; ++i) { + title += " / " + words[i]; + } + + stream << "section_id = parent_ids.peek()\n"; + stream << "data = {" + << "'title': '" << title << "', " + << "'template': '" << "Test Case (Steps)" << "', " + << "'custom_preconds': '" << "Tester is in an empty region of a domain in which they have edit rights\\n\\n*Note: Press \\'n\\' to advance test script'" + << " }\n"; + + stream << "case = client.send_post('add_case/' + str(section_id), data)\n"; } \ No newline at end of file diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 3285281577..5d8b932869 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -35,17 +35,23 @@ public: const QString& branch, const QDomElement& element); - QDomElement processTest(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element); + QDomElement processTestXML(const QString& fullDirectory, + const QString& test, + const QString& user, + const QString& branch, + const QDomElement& element); + + void processTestPython(const QString& fullDirectory, QTextStream& stream); void createTestRailDotPyScript(const QString& outputDirectory); void createStackDotPyScript(const QString& outputDirectory); void requestDataFromUser(); void createAddSectionsPythonScript(const QString& testDirectory, const QString& outputDirectory); - void processDirecoryPython(const QString& directory, QTextStream& stream); + void processDirectoryPython(const QString& directory, QTextStream& stream); bool isAValidTestDirectory(const QString& directory); - + QString getObject(const QString& path); private: QDomDocument _document; From 951b90d74cacb125baaf656c56a1490afe519652 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 27 Jul 2018 21:40:18 -0700 Subject: [PATCH 19/36] WIP - running Python process. --- tools/auto-tester/src/TestRailInterface.cpp | 92 +++++++++++++++------ tools/auto-tester/src/TestRailInterface.h | 31 ++++--- 2 files changed, 87 insertions(+), 36 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 987ce5a739..3ac8c8f9f8 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include TestRailInterface::TestRailInterface() { @@ -209,7 +210,10 @@ bool TestRailInterface::isAValidTestDirectory(const QString& directory) { return false; } -void TestRailInterface::processDirectoryPython(const QString& directory, QTextStream& stream) { +void TestRailInterface::processDirectoryPython(const QString& directory, + QTextStream& stream, + const QString& userGitHub, + const QString& branchGitHub) { // Loop over all entries in directory QDirIterator it(directory.toStdString().c_str()); while (it.hasNext()) { @@ -226,9 +230,9 @@ void TestRailInterface::processDirectoryPython(const QString& directory, QTextSt // Now we push the parent_id, and recursively process each directory stream << "parent_ids.push(section['id'])\n\n"; - processDirectoryPython(nextDirectory, stream); + processDirectoryPython(nextDirectory, stream, userGitHub, branchGitHub); } else if (objectName == "test.js" || objectName == "testStory.js") { - processTestPython(nextDirectory, stream); + processTestPython(nextDirectory, stream, userGitHub, branchGitHub); } } @@ -243,8 +247,11 @@ void TestRailInterface::processDirectoryPython(const QString& directory, QTextSt // Each node and leaf have an ID and a parent ID. // Therefore, the tree is built top-down, using a stack to store the IDs of each node // -void TestRailInterface::createAddSectionsPythonScript(const QString& testDirectory, const QString& outputDirectory) { - QFile file(outputDirectory + "/addSections.py"); +void TestRailInterface::createAddSectionsPythonScript(const QString& testDirectory, + const QString& outputDirectory, + const QString& userGitHub, + const QString& branchGitHub) { + QFile file(outputDirectory + "/addTestCases.py"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not create 'addSections.py'"); @@ -270,28 +277,42 @@ void TestRailInterface::createAddSectionsPythonScript(const QString& testDirecto // Now we push the parent_id, and recursively process each directory stream << "parent_ids.push(section['id'])\n\n"; - processDirectoryPython(testDirectory, stream); + processDirectoryPython(testDirectory, stream, userGitHub, branchGitHub); file.close(); - QMessageBox::information(0, "Success", "TestRail Python script has been created"); + if (QMessageBox::Yes == QMessageBox(QMessageBox::Information, "Python script has been created", "Do you want to run the script and update TestRail?", QMessageBox::Yes | QMessageBox::No).exec()) { + QString command("python"); + QStringList parameters = QStringList() << outputDirectory + "/addTestCases.py"; + QProcess* process = new QProcess(); + process->startDetached(command, parameters); + if (process->waitForStarted(3000)) { + QMessageBox::information(0, "Python process started", "TestRail is being updated"); + + process->waitForFinished(); + process->close(); + } else { + QMessageBox::critical(0, "Failure", "Could not start process to update TestRail"); + return; + } + } } void TestRailInterface::createTestSuitePython(const QString& testDirectory, const QString& outputDirectory, - const QString& user, - const QString& branch) { + const QString& userGitHub, + const QString& branchGitHub) { createTestRailDotPyScript(outputDirectory); createStackDotPyScript(outputDirectory); requestDataFromUser(); - createAddSectionsPythonScript(testDirectory, outputDirectory); + createAddSectionsPythonScript(testDirectory, outputDirectory, userGitHub, branchGitHub); } void TestRailInterface::createTestSuiteXML(const QString& testDirectory, const QString& outputDirectory, - const QString& user, - const QString& branch) { + const QString& userGitHub, + const QString& branchGitHub) { QDomProcessingInstruction instruction = _document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); _document.appendChild(instruction); @@ -308,7 +329,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, // This is the first call to 'process'. This is then called recursively to build the full XML tree QDomElement secondLevelSections = _document.createElement("sections"); - topLevelSection.appendChild(processDirectoryXML(testDirectory, user, branch, secondLevelSections)); + topLevelSection.appendChild(processDirectoryXML(testDirectory, userGitHub, branchGitHub, secondLevelSections)); topLevelSection.appendChild(secondLevelSections); root.appendChild(topLevelSection); @@ -329,7 +350,10 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, QMessageBox::information(0, "Success", "TestRail XML file has been created"); } -QDomElement TestRailInterface::processDirectoryXML(const QString& directory, const QString& user, const QString& branch, const QDomElement& element) { +QDomElement TestRailInterface::processDirectoryXML(const QString& directory, + const QString& userGitHub, + const QString& branchGitHub, + const QDomElement& element) { QDomElement result = element; // Loop over all entries in directory @@ -350,7 +374,7 @@ QDomElement TestRailInterface::processDirectoryXML(const QString& directory, con sectionElement.appendChild(sectionElementName); QDomElement testsElement = _document.createElement("sections"); - sectionElement.appendChild(processDirectoryXML(nextDirectory, user, branch, testsElement)); + sectionElement.appendChild(processDirectoryXML(nextDirectory, userGitHub, branchGitHub, testsElement)); result.appendChild(sectionElement); } else if (objectName == "test.js" || objectName == "testStory.js") { @@ -358,7 +382,9 @@ QDomElement TestRailInterface::processDirectoryXML(const QString& directory, con QDomElement sectionElementName = _document.createElement("name"); sectionElementName.appendChild(_document.createTextNode("all")); sectionElement.appendChild(sectionElementName); - sectionElement.appendChild(processTestXML(nextDirectory, objectName, user, branch, _document.createElement("cases"))); + sectionElement.appendChild( + processTestXML(nextDirectory, objectName, userGitHub, branchGitHub, _document.createElement("cases"))); + result.appendChild(sectionElement); } } @@ -366,7 +392,11 @@ QDomElement TestRailInterface::processDirectoryXML(const QString& directory, con return result; } -QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, const QString& test, const QString& user, const QString& branch, const QDomElement& element) { +QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, + const QString& test, + const QString& userGitHub, + const QString& branchGitHub, + const QDomElement& element) { QDomElement result = element; QDomElement caseElement = _document.createElement("case"); @@ -443,7 +473,7 @@ QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, cons added_to_releaseElementId.appendChild(_document.createTextNode("4")); added_to_releaseElement.appendChild(added_to_releaseElementId); QDomElement added_to_releaseElementValue = _document.createElement("value"); - added_to_releaseElementValue.appendChild(_document.createTextNode(branch)); + added_to_releaseElementValue.appendChild(_document.createTextNode(branchGitHub)); added_to_releaseElement.appendChild(added_to_releaseElementValue); customElement.appendChild(added_to_releaseElement); @@ -451,7 +481,8 @@ QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, cons precondsElement.appendChild(_document.createTextNode("Tester is in an empty region of a domain in which they have edit rights\n\n*Note: Press 'n' to advance test script")); customElement.appendChild(precondsElement); - QString testMDName = QString("https://github.com/") + user + "/hifi_tests/blob/" + branch + "/tests/content/entity/light/point/create/test.md"; + QString testMDName = QString("https://github.com/") + userGitHub + "/hifi_tests/blob/" + branchGitHub + + "/tests/content/entity/light/point/create/test.md"; QDomElement steps_seperatedElement = _document.createElement("steps_separated"); QDomElement stepElement = _document.createElement("step"); @@ -478,7 +509,10 @@ QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, cons return result; } -void TestRailInterface::processTestPython(const QString& fullDirectory, QTextStream& stream) { +void TestRailInterface::processTestPython(const QString& fullDirectory, + QTextStream& stream, + const QString& userGitHub, + const QString& branchGitHub) { // The name of the test is derived from the full path. // The first term is the first word after "tests" // The last word is the penultimate word @@ -500,11 +534,19 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, QTextStr } stream << "section_id = parent_ids.peek()\n"; - stream << "data = {" - << "'title': '" << title << "', " - << "'template': '" << "Test Case (Steps)" << "', " - << "'custom_preconds': '" << "Tester is in an empty region of a domain in which they have edit rights\\n\\n*Note: Press \\'n\\' to advance test script'" - << " }\n"; + + QString testMDName = QString("https://github.com/") + userGitHub + "/hifi_tests/blob/" + branchGitHub + + "/tests/content/entity/light/point/create/test.md"; + + QString testContent = QString("Execute instructions in [THIS TEST](") + testMDName + ")"; + QString testExpected = QString("Refer to the expected result in the linked description."); + + stream << "data = {\n\t" + << "'title': '" << title << "',\n\t" + << "'template_id': 2,\n\t" + << "'custom_preconds': " << "'Tester is in an empty region of a domain in which they have edit rights\\n\\n*Note: Press \\'n\\' to advance test script',\n\t" + << "'custom_steps_separated': " << "[\n\t\t{\n\t\t\t'content': '" << testContent << "',\n\t\t\t'expected': '" << testExpected << "'\n\t\t}\n\t]\n" + << "}\n"; stream << "case = client.send_post('add_case/' + str(section_id), data)\n"; } \ No newline at end of file diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 5d8b932869..b01e8158c1 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -22,33 +22,42 @@ public: void createTestSuiteXML(const QString& testDirectory, const QString& outputDirectory, - const QString& user, - const QString& branch); + const QString& userGitHub, + const QString& branchGitHub); void createTestSuitePython(const QString& testDirectory, const QString& outputDirectory, - const QString& user, - const QString& branch); + const QString& userGitHub, + const QString& branchGitHub); QDomElement processDirectoryXML(const QString& directory, - const QString& user, - const QString& branch, + const QString& useGitHubr, + const QString& branchGitHub, const QDomElement& element); QDomElement processTestXML(const QString& fullDirectory, const QString& test, - const QString& user, - const QString& branch, + const QString& userGitHub, + const QString& branchGitHub, const QDomElement& element); - void processTestPython(const QString& fullDirectory, QTextStream& stream); + void processTestPython(const QString& fullDirectory, + QTextStream& stream, + const QString& userGitHub, + const QString& branchGitHub); void createTestRailDotPyScript(const QString& outputDirectory); void createStackDotPyScript(const QString& outputDirectory); void requestDataFromUser(); - void createAddSectionsPythonScript(const QString& testDirectory, const QString& outputDirectory); + void createAddSectionsPythonScript(const QString& testDirectory, + const QString& outputDirectory, + const QString& userGitHub, + const QString& branchGitHub); - void processDirectoryPython(const QString& directory, QTextStream& stream); + void processDirectoryPython(const QString& directory, + QTextStream& stream, + const QString& userGitHub, + const QString& branchGitHub); bool isAValidTestDirectory(const QString& directory); QString getObject(const QString& path); From e0d14dd7021c72315362bc5b762c9421152e8086 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sun, 29 Jul 2018 00:25:02 -0700 Subject: [PATCH 20/36] Works, but does not yet wait for completion of Python process. --- tools/auto-tester/src/TestRailInterface.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index b01e8158c1..768de24ea3 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -49,10 +49,10 @@ public: void createTestRailDotPyScript(const QString& outputDirectory); void createStackDotPyScript(const QString& outputDirectory); void requestDataFromUser(); - void createAddSectionsPythonScript(const QString& testDirectory, - const QString& outputDirectory, - const QString& userGitHub, - const QString& branchGitHub); + void createAddTestCasesPythonScript(const QString& testDirectory, + const QString& outputDirectory, + const QString& userGitHub, + const QString& branchGitHub); void processDirectoryPython(const QString& directory, QTextStream& stream, From e191c65290f0508e6ac6914e058529bbe548dfce Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sun, 29 Jul 2018 00:27:15 -0700 Subject: [PATCH 21/36] Works, but does not yet wait for completion of Python process. --- tools/auto-tester/src/TestRailInterface.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 3ac8c8f9f8..2439623d6d 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -247,14 +247,14 @@ void TestRailInterface::processDirectoryPython(const QString& directory, // Each node and leaf have an ID and a parent ID. // Therefore, the tree is built top-down, using a stack to store the IDs of each node // -void TestRailInterface::createAddSectionsPythonScript(const QString& testDirectory, +void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirectory, const QString& outputDirectory, const QString& userGitHub, const QString& branchGitHub) { QFile file(outputDirectory + "/addTestCases.py"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Could not create 'addSections.py'"); + "Could not create 'addTestCases.py'"); exit(-1); } @@ -282,15 +282,11 @@ void TestRailInterface::createAddSectionsPythonScript(const QString& testDirecto file.close(); if (QMessageBox::Yes == QMessageBox(QMessageBox::Information, "Python script has been created", "Do you want to run the script and update TestRail?", QMessageBox::Yes | QMessageBox::No).exec()) { - QString command("python"); + QString command("C:\\Python37\\python"); QStringList parameters = QStringList() << outputDirectory + "/addTestCases.py"; QProcess* process = new QProcess(); - process->startDetached(command, parameters); - if (process->waitForStarted(3000)) { + if (process->startDetached(command, parameters)) { QMessageBox::information(0, "Python process started", "TestRail is being updated"); - - process->waitForFinished(); - process->close(); } else { QMessageBox::critical(0, "Failure", "Could not start process to update TestRail"); return; @@ -306,7 +302,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, createTestRailDotPyScript(outputDirectory); createStackDotPyScript(outputDirectory); requestDataFromUser(); - createAddSectionsPythonScript(testDirectory, outputDirectory, userGitHub, branchGitHub); + createAddTestCasesPythonScript(testDirectory, outputDirectory, userGitHub, branchGitHub); } void TestRailInterface::createTestSuiteXML(const QString& testDirectory, From 9247e8dc16b9f380b3abb9a86a17e1e7f86446f2 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sun, 29 Jul 2018 20:28:46 -0700 Subject: [PATCH 22/36] QProcess signals connected. --- .../src/AssignmentClientMonitor.cpp | 7 +++++-- tools/auto-tester/src/TestRailInterface.cpp | 19 ++++++++++++------- tools/auto-tester/src/TestRailInterface.h | 4 +++- tools/auto-tester/src/ui/MismatchWindow.h | 3 +-- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 2847d4ebf1..6a9826f877 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -242,8 +242,11 @@ void AssignmentClientMonitor::spawnChildClient() { if (assignmentClient->processId() > 0) { auto pid = assignmentClient->processId(); // make sure we hear that this process has finished when it does - connect(assignmentClient, static_cast(&QProcess::finished), - this, [this, pid](int exitCode, QProcess::ExitStatus exitStatus) { + connect( + assignmentClient, + static_cast(&QProcess::finished), + this, + [this, pid](int exitCode, QProcess::ExitStatus exitStatus) { childProcessFinished(pid, exitCode, exitStatus); }); diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 2439623d6d..26c2b69896 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -285,12 +285,17 @@ void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirect QString command("C:\\Python37\\python"); QStringList parameters = QStringList() << outputDirectory + "/addTestCases.py"; QProcess* process = new QProcess(); - if (process->startDetached(command, parameters)) { - QMessageBox::information(0, "Python process started", "TestRail is being updated"); - } else { - QMessageBox::critical(0, "Failure", "Could not start process to update TestRail"); - return; - } + connect( + process, &QProcess::started, + this, []() {QMessageBox::information(0, "Python process started", "TestRail is being updated"); } + ); + + connect( + process, static_cast(&QProcess::finished), + this, [](int exitCode, QProcess::ExitStatus exitStatus) {QMessageBox::information(0, "Python process finished", "TestRail tests have been added"); } + ); + + process->start(command, parameters); } } @@ -545,4 +550,4 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, << "}\n"; stream << "case = client.send_post('add_case/' + str(section_id), data)\n"; -} \ No newline at end of file +} diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 768de24ea3..2d7ca21f58 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -16,7 +16,9 @@ #include #include -class TestRailInterface { +class TestRailInterface : public QObject{ + Q_OBJECT + public: TestRailInterface(); diff --git a/tools/auto-tester/src/ui/MismatchWindow.h b/tools/auto-tester/src/ui/MismatchWindow.h index 30fca94469..f203a2be6a 100644 --- a/tools/auto-tester/src/ui/MismatchWindow.h +++ b/tools/auto-tester/src/ui/MismatchWindow.h @@ -14,8 +14,7 @@ #include "../common.h" -class MismatchWindow : public QDialog, public Ui::MismatchWindow -{ +class MismatchWindow : public QDialog, public Ui::MismatchWindow { Q_OBJECT public: From b72d94e56d3f32417436efffcb6ef65411d47974 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sun, 29 Jul 2018 20:58:07 -0700 Subject: [PATCH 23/36] Added a sweet "busy" window. --- tools/auto-tester/src/TestRailInterface.cpp | 9 ++- tools/auto-tester/src/TestRailInterface.h | 2 + tools/auto-tester/src/ui/BusyWindow.cpp | 18 ++++++ tools/auto-tester/src/ui/BusyWindow.h | 22 +++++++ tools/auto-tester/src/ui/BusyWindow.ui | 72 +++++++++++++++++++++ 5 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 tools/auto-tester/src/ui/BusyWindow.cpp create mode 100644 tools/auto-tester/src/ui/BusyWindow.h create mode 100644 tools/auto-tester/src/ui/BusyWindow.ui diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 26c2b69896..e92ef59c77 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -20,6 +20,7 @@ #include TestRailInterface::TestRailInterface() { + _busyWindow.setModal(true); _testRailSelectorWindow.setModal(true); ////_testRailSelectorWindow.setURL("https://highfidelity.testrail.net"); @@ -287,12 +288,16 @@ void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirect QProcess* process = new QProcess(); connect( process, &QProcess::started, - this, []() {QMessageBox::information(0, "Python process started", "TestRail is being updated"); } + this, [=]() { + _busyWindow.exec(); + } ); connect( process, static_cast(&QProcess::finished), - this, [](int exitCode, QProcess::ExitStatus exitStatus) {QMessageBox::information(0, "Python process finished", "TestRail tests have been added"); } + this, [=](int exitCode, QProcess::ExitStatus exitStatus) { + _busyWindow.hide(); + } ); process->start(command, parameters); diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 2d7ca21f58..1908c1bbd3 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -11,6 +11,7 @@ #ifndef hifi_test_testrail_interface_h #define hifi_test_testrail_interface_h +#include "ui/BusyWindow.h" #include "ui/TestRailSelectorWindow.h" #include #include @@ -67,6 +68,7 @@ public: private: QDomDocument _document; + BusyWindow _busyWindow; TestRailSelectorWindow _testRailSelectorWindow; QString _url; diff --git a/tools/auto-tester/src/ui/BusyWindow.cpp b/tools/auto-tester/src/ui/BusyWindow.cpp new file mode 100644 index 0000000000..904dc47d75 --- /dev/null +++ b/tools/auto-tester/src/ui/BusyWindow.cpp @@ -0,0 +1,18 @@ +// +// BusyWindow.cpp +// +// Created by Nissim Hadar on 26 Jul 2017. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "BusyWindow.h" + +#include + +#include + +BusyWindow::BusyWindow(QWidget *parent) { + setupUi(this); +} diff --git a/tools/auto-tester/src/ui/BusyWindow.h b/tools/auto-tester/src/ui/BusyWindow.h new file mode 100644 index 0000000000..62f2df7e04 --- /dev/null +++ b/tools/auto-tester/src/ui/BusyWindow.h @@ -0,0 +1,22 @@ +// +// BusyWindow.h +// +// Created by Nissim Hadar on 29 Jul 2017. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_BusyWindow_h +#define hifi_BusyWindow_h + +#include "ui_BusyWindow.h" + +class BusyWindow : public QDialog, public Ui::BusyWindow { + Q_OBJECT + +public: + BusyWindow(QWidget* parent = Q_NULLPTR); +}; + +#endif \ No newline at end of file diff --git a/tools/auto-tester/src/ui/BusyWindow.ui b/tools/auto-tester/src/ui/BusyWindow.ui new file mode 100644 index 0000000000..f04a39418b --- /dev/null +++ b/tools/auto-tester/src/ui/BusyWindow.ui @@ -0,0 +1,72 @@ + + + BusyWindow + + + + 0 + 0 + 542 + 189 + + + + Updating TestRail - please wait + + + + + 30 + 850 + 500 + 28 + + + + + 12 + + + + similarity + + + + + + 40 + 40 + 481 + 101 + + + + 0 + + + 0 + + + + + + 50 + 60 + 431 + 61 + + + + + 20 + + + + Please wait for this window to close + + + + + + + From ad0a1c289da68d50c887f8c83d3ba1dd70b94e7e Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sun, 29 Jul 2018 22:24:48 -0700 Subject: [PATCH 24/36] Use environment variable for Python path. --- tools/auto-tester/src/TestRailInterface.cpp | 14 +++++++++++++- tools/auto-tester/src/TestRailInterface.h | 4 ++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index e92ef59c77..d8784e5a86 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -283,7 +283,7 @@ void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirect file.close(); if (QMessageBox::Yes == QMessageBox(QMessageBox::Information, "Python script has been created", "Do you want to run the script and update TestRail?", QMessageBox::Yes | QMessageBox::No).exec()) { - QString command("C:\\Python37\\python"); + QString command(_pythonPath + "/" + pythonExe); QStringList parameters = QStringList() << outputDirectory + "/addTestCases.py"; QProcess* process = new QProcess(); connect( @@ -309,6 +309,18 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, const QString& userGitHub, const QString& branchGitHub) { + // First check that Python is available + QProcessEnvironment e = QProcessEnvironment::systemEnvironment(); + QStringList sl = e.toStringList(); + if (QProcessEnvironment::systemEnvironment().contains("PYTHON_PATH")) { + _pythonPath = QProcessEnvironment::systemEnvironment().value("PYTHON_PATH"); + if (!QFile::exists(_pythonPath + "/" + pythonExe)) { + QMessageBox::critical(0, pythonExe, QString("Python executable not found in ") + _pythonPath); + } + } else { + QMessageBox::critical(0, "PYTHON_PATH not defined", "Please set PYTHON_PATH to directory containing the Python executable"); + } + createTestRailDotPyScript(outputDirectory); createStackDotPyScript(outputDirectory); requestDataFromUser(); diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 1908c1bbd3..4c094a27f3 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -75,6 +75,10 @@ private: QString _user; QString _password; QString _project; + + QString _pythonPath; + + const QString pythonExe{ "python.exe" }; }; #endif \ No newline at end of file From 3402d7836a37f04bf437e3209c439176923af698 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 11:17:53 -0700 Subject: [PATCH 25/36] Added milestones to TestRail cases. --- tools/auto-tester/src/TestRailInterface.cpp | 163 +++++++++++++++--- tools/auto-tester/src/TestRailInterface.h | 20 ++- .../src/ui/TestRailSelectorWindow.cpp | 27 ++- .../src/ui/TestRailSelectorWindow.h | 4 + .../src/ui/TestRailSelectorWindow.ui | 112 +++++++++--- 5 files changed, 261 insertions(+), 65 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index d8784e5a86..1640918c47 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include TestRailInterface::TestRailInterface() { @@ -39,8 +38,8 @@ QString TestRailInterface::getObject(const QString& path) { // Creates the testrail.py script // This is the file linked to from http://docs.gurock.com/testrail-api2/bindings-python -void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory) { - QFile file(outputDirectory + "/testrail.py"); +void TestRailInterface::createTestRailDotPyScript() { + QFile file(_outputDirectory + "/testrail.py"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not create 'testrail.py'"); @@ -145,8 +144,13 @@ void TestRailInterface::createTestRailDotPyScript(const QString& outputDirectory } // Creates a Stack class -void TestRailInterface::createStackDotPyScript(const QString& outputDirectory) { - QFile file(outputDirectory + "/stack.py"); +void TestRailInterface::createStackDotPyScript() { + QString filename = _outputDirectory + "/stack.py"; + if (QFile::exists(filename)) { + QFile::remove(filename); + } + QFile file(filename); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not create 'stack.py'"); @@ -184,7 +188,7 @@ void TestRailInterface::createStackDotPyScript(const QString& outputDirectory) { file.close(); } -void TestRailInterface::requestDataFromUser() { +void TestRailInterface::requestTestRailDataFromUser() { _testRailSelectorWindow.exec(); if (_testRailSelectorWindow.getUserCancelled()) { @@ -249,10 +253,15 @@ void TestRailInterface::processDirectoryPython(const QString& directory, // Therefore, the tree is built top-down, using a stack to store the IDs of each node // void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirectory, - const QString& outputDirectory, - const QString& userGitHub, - const QString& branchGitHub) { - QFile file(outputDirectory + "/addTestCases.py"); + const QString& userGitHub, + const QString& branchGitHub) { + + QString filename = _outputDirectory + "/addTestCases.py"; + if (QFile::exists(filename)) { + QFile::remove(filename); + } + QFile file(filename); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not create 'addTestCases.py'"); @@ -283,48 +292,141 @@ void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirect file.close(); if (QMessageBox::Yes == QMessageBox(QMessageBox::Information, "Python script has been created", "Do you want to run the script and update TestRail?", QMessageBox::Yes | QMessageBox::No).exec()) { - QString command(_pythonPath + "/" + pythonExe); - QStringList parameters = QStringList() << outputDirectory + "/addTestCases.py"; QProcess* process = new QProcess(); - connect( - process, &QProcess::started, - this, [=]() { + connect(process, &QProcess::started, this, + [=]() { _busyWindow.exec(); } ); - connect( - process, static_cast(&QProcess::finished), - this, [=](int exitCode, QProcess::ExitStatus exitStatus) { + connect(process, static_cast(&QProcess::finished), this, + [=](int exitCode, QProcess::ExitStatus exitStatus) { _busyWindow.hide(); } ); - process->start(command, parameters); + QStringList parameters = QStringList() << _outputDirectory + "/addTestCases.py"; + process->start(_pythonCommand, parameters); } } +void TestRailInterface::updateMilestonesComboData(int exitCode, QProcess::ExitStatus exitStatus) { + // Check if process completed successfully + if (exitStatus != QProcess::NormalExit) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not get milestones from TestRail"); + exit(-1); + } + + // Create map of milestones from the file created by the process + _milestoneNames.clear(); + + QString filename = _outputDirectory + "/milestones.txt"; + if (!QFile::exists(filename)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not find milestones.txt in " + _outputDirectory); + exit(-1); + } + + QFile file(filename); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not open " + _outputDirectory + "/milestones.txt"); + exit(-1); + } + + QTextStream in(&file); + QString line = in.readLine(); + while (!line.isNull()) { + QStringList words = line.split(' '); + _milestones[words[0]] = words[1].toInt(); + _milestoneNames << words[0]; + + line = in.readLine(); + } + + file.close(); + + // Update the combo + _testRailSelectorWindow.updateMilestoneComboBoxData(_milestoneNames); + + _testRailSelectorWindow.exec(); + + if (_testRailSelectorWindow.getUserCancelled()) { + return; + } + + createAddTestCasesPythonScript(_testDirectory, _userGitHub, _branchGitHub); +} + +void TestRailInterface::getMilestonesFromTestRail() { + QString filename = _outputDirectory + "/getMilestones.py"; + if (QFile::exists(filename)) { + QFile::remove(filename); + } + QFile file(filename); + + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not create 'getMilestones.py'"); + exit(-1); + } + + QTextStream stream(&file); + + // Code to access TestRail + stream << "from testrail import *\n"; + stream << "client = APIClient('" << _url.toStdString().c_str() << "')\n"; + stream << "client.user = '" << _user << "'\n"; + stream << "client.password = '" << _password << "'\n\n"; + + // Print the list of uncompleted milestones + stream << "file = open('" + _outputDirectory + "/milestones.txt', 'w')\n\n"; + stream << "milestones = client.send_get('get_milestones/" + _project + "')\n"; + stream << "for milestone in milestones:\n"; + stream << "\tif milestone['is_completed'] == False:\n"; + stream << "\t\tfile.write(milestone['name'] + ' ' + str(milestone['id']) + '\\n')\n\n"; + stream << "file.close()\n"; + + file.close(); + + QProcess* process = new QProcess(); + connect(process, static_cast(&QProcess::finished), this, + [=](int exitCode, QProcess::ExitStatus exitStatus) { + updateMilestonesComboData(exitCode, exitStatus); + } + ); + + QStringList parameters = QStringList() << _outputDirectory + "/getMilestones.py "; + process->start(_pythonCommand, parameters); +} + void TestRailInterface::createTestSuitePython(const QString& testDirectory, const QString& outputDirectory, const QString& userGitHub, const QString& branchGitHub) { - + + _testDirectory = testDirectory; + _outputDirectory = outputDirectory; + _userGitHub = userGitHub; + _branchGitHub = branchGitHub; + // First check that Python is available - QProcessEnvironment e = QProcessEnvironment::systemEnvironment(); - QStringList sl = e.toStringList(); if (QProcessEnvironment::systemEnvironment().contains("PYTHON_PATH")) { - _pythonPath = QProcessEnvironment::systemEnvironment().value("PYTHON_PATH"); + QString _pythonPath = QProcessEnvironment::systemEnvironment().value("PYTHON_PATH"); if (!QFile::exists(_pythonPath + "/" + pythonExe)) { QMessageBox::critical(0, pythonExe, QString("Python executable not found in ") + _pythonPath); } + _pythonCommand = _pythonPath + "/" + pythonExe; } else { QMessageBox::critical(0, "PYTHON_PATH not defined", "Please set PYTHON_PATH to directory containing the Python executable"); + return; } - createTestRailDotPyScript(outputDirectory); - createStackDotPyScript(outputDirectory); - requestDataFromUser(); - createAddTestCasesPythonScript(testDirectory, outputDirectory, userGitHub, branchGitHub); + requestTestRailDataFromUser(); + getMilestonesFromTestRail(); + createTestRailDotPyScript(); + createStackDotPyScript(); } void TestRailInterface::createTestSuiteXML(const QString& testDirectory, @@ -332,6 +434,8 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, const QString& userGitHub, const QString& branchGitHub) { + _outputDirectory = outputDirectory; + QDomProcessingInstruction instruction = _document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); _document.appendChild(instruction); @@ -353,7 +457,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, root.appendChild(topLevelSection); // Write to file - const QString testRailsFilename{ outputDirectory + "/TestRailSuite.xml" }; + const QString testRailsFilename{ _outputDirectory + "/TestRailSuite.xml" }; QFile file(testRailsFilename); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not create XML file"); @@ -559,9 +663,12 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, QString testContent = QString("Execute instructions in [THIS TEST](") + testMDName + ")"; QString testExpected = QString("Refer to the expected result in the linked description."); + int milestone_id = _milestones[_milestoneNames[_testRailSelectorWindow.getMilestoneID()]]; + stream << "data = {\n\t" << "'title': '" << title << "',\n\t" << "'template_id': 2,\n\t" + << "'milestone_id': " << milestone_id << ",\n\t" << "'custom_preconds': " << "'Tester is in an empty region of a domain in which they have edit rights\\n\\n*Note: Press \\'n\\' to advance test script',\n\t" << "'custom_steps_separated': " << "[\n\t\t{\n\t\t\t'content': '" << testContent << "',\n\t\t\t'expected': '" << testExpected << "'\n\t\t}\n\t]\n" << "}\n"; diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 4c094a27f3..f7fe131416 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -15,6 +15,7 @@ #include "ui/TestRailSelectorWindow.h" #include #include +#include #include class TestRailInterface : public QObject{ @@ -49,11 +50,12 @@ public: const QString& userGitHub, const QString& branchGitHub); - void createTestRailDotPyScript(const QString& outputDirectory); - void createStackDotPyScript(const QString& outputDirectory); - void requestDataFromUser(); + void getMilestonesFromTestRail(); + void createTestRailDotPyScript(); + void createStackDotPyScript(); + void requestTestRailDataFromUser(); + void requestMilestoneFromUser(); void createAddTestCasesPythonScript(const QString& testDirectory, - const QString& outputDirectory, const QString& userGitHub, const QString& branchGitHub); @@ -65,6 +67,8 @@ public: bool isAValidTestDirectory(const QString& directory); QString getObject(const QString& path); + void updateMilestonesComboData(int exitCode, QProcess::ExitStatus exitStatus); + private: QDomDocument _document; @@ -76,9 +80,15 @@ private: QString _password; QString _project; - QString _pythonPath; + QString _testDirectory; + QString _outputDirectory; + QString _userGitHub; + QString _branchGitHub; const QString pythonExe{ "python.exe" }; + QString _pythonCommand; + std::map _milestones; + QStringList _milestoneNames; }; #endif \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp index b2555ae4ad..9f07c25f3a 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp @@ -19,6 +19,17 @@ TestRailSelectorWindow::TestRailSelectorWindow(QWidget *parent) { projectLineEdit->setValidator(new QIntValidator(1, 999, this)); } +void TestRailSelectorWindow::on_acceptButton_clicked() { + urlLineEdit->setDisabled(true); + userLineEdit->setDisabled(true); + passwordLineEdit->setDisabled(true); + projectLineEdit->setDisabled(true); + + OKButton->setDisabled(false); + milestoneComboBox->setDisabled(false); + close(); +} + void TestRailSelectorWindow::on_OKButton_clicked() { userCancelled = false; close(); @@ -34,19 +45,19 @@ bool TestRailSelectorWindow::getUserCancelled() { } void TestRailSelectorWindow::setURL(const QString& user) { - URLTextEdit->setText(user); + urlLineEdit->setText(user); } QString TestRailSelectorWindow::getURL() { - return URLTextEdit->toPlainText(); + return urlLineEdit->text(); } void TestRailSelectorWindow::setUser(const QString& user) { - userTextEdit->setText(user); + userLineEdit->setText(user); } QString TestRailSelectorWindow::getUser() { - return userTextEdit->toPlainText(); + return userLineEdit->text(); } QString TestRailSelectorWindow::getPassword() { @@ -60,3 +71,11 @@ void TestRailSelectorWindow::setProject(const int project) { int TestRailSelectorWindow::getProject() { return projectLineEdit->text().toInt(); } + +void TestRailSelectorWindow::updateMilestoneComboBoxData(QStringList data) { + milestoneComboBox->insertItems(0, data); +} + +int TestRailSelectorWindow::getMilestoneID() { + return milestoneComboBox->currentIndex(); +} \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.h b/tools/auto-tester/src/ui/TestRailSelectorWindow.h index 821102b6bc..7072c1cd46 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.h +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.h @@ -33,7 +33,11 @@ public: bool userCancelled{ false }; + void updateMilestoneComboBoxData(QStringList data); + int getMilestoneID(); + private slots: + void on_acceptButton_clicked(); void on_OKButton_clicked(); void on_cancelButton_clicked(); }; diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui index dfc477deb0..98c52f3194 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui @@ -7,7 +7,7 @@ 0 0 489 - 312 + 415 @@ -35,7 +35,7 @@ 70 - 115 + 125 121 20 @@ -67,21 +67,14 @@ TestRail URL - - - - 200 - 25 - 231 - 24 - - - + + false + 120 - 240 + 350 93 28 @@ -94,7 +87,7 @@ 280 - 240 + 350 93 28 @@ -107,7 +100,7 @@ 200 - 115 + 120 231 24 @@ -116,21 +109,11 @@ QLineEdit::Password - - - - 200 - 70 - 231 - 24 - - - 70 - 70 + 75 121 20 @@ -148,7 +131,7 @@ 200 - 160 + 170 231 24 @@ -161,7 +144,7 @@ 70 - 160 + 175 121 20 @@ -175,6 +158,79 @@ TestRail Project + + + + 200 + 220 + 231 + 28 + + + + Accept + + + + + false + + + + 270 + 280 + 161 + 22 + + + + + + true + + + + 140 + 280 + 121 + 20 + + + + + 10 + + + + TestRail Milestone + + + + + + 200 + 20 + 231 + 24 + + + + QLineEdit::Normal + + + + + + 200 + 70 + 231 + 24 + + + + QLineEdit::Normal + + From c98d43bb32f5ebbae191c8b9bca76926a5326fd5 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 13:06:04 -0700 Subject: [PATCH 26/36] Problem = last test is created twice. --- tools/auto-tester/src/TestRailInterface.cpp | 55 ++++++++++-------- tools/auto-tester/src/TestRailInterface.h | 9 ++- .../src/ui/TestRailSelectorWindow.cpp | 20 +++++-- .../src/ui/TestRailSelectorWindow.h | 7 ++- .../src/ui/TestRailSelectorWindow.ui | 58 ++++++++++++++++--- 5 files changed, 108 insertions(+), 41 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 1640918c47..31594fe66a 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -22,14 +22,15 @@ TestRailInterface::TestRailInterface() { _busyWindow.setModal(true); _testRailSelectorWindow.setModal(true); - ////_testRailSelectorWindow.setURL("https://highfidelity.testrail.net"); - _testRailSelectorWindow.setURL("https://nissimhadar.testrail.io"); - ////_testRailSelectorWindow.setUser("@highfidelity.io"); - _testRailSelectorWindow.setUser("nissim.hadar@gmail.com"); + _testRailSelectorWindow.setURL("https://highfidelity.testrail.net"); + ////_testRailSelectorWindow.setURL("https://nissimhadar.testrail.io"); + _testRailSelectorWindow.setUser("@highfidelity.io"); + ////_testRailSelectorWindow.setUser("nissim.hadar@gmail.com"); - // 24 is the HighFidelity Interface project id in TestRail - ////_testRailSelectorWindow.setProject(24); - _testRailSelectorWindow.setProject(1); + _testRailSelectorWindow.setProjectID(INTERFACE_PROJECT_ID); + ////_testRailSelectorWindow.setProject(1); + + _testRailSelectorWindow.setSuiteID(INTERFACE_SUITE_ID); } QString TestRailInterface::getObject(const QString& path) { @@ -197,9 +198,10 @@ void TestRailInterface::requestTestRailDataFromUser() { _url = _testRailSelectorWindow.getURL() + "/"; _user = _testRailSelectorWindow.getUser(); - ////_password = _testRailSelectorWindow.getPassword(); - _password = "tutKA76"; - _project = QString::number(_testRailSelectorWindow.getProject()); + _password = _testRailSelectorWindow.getPassword(); + ////_password = "tutKA76"; + _projectID = QString::number(_testRailSelectorWindow.getProjectID()); + _suiteID = QString::number(_testRailSelectorWindow.getSuiteID()); } bool TestRailInterface::isAValidTestDirectory(const QString& directory) { @@ -218,7 +220,8 @@ bool TestRailInterface::isAValidTestDirectory(const QString& directory) { void TestRailInterface::processDirectoryPython(const QString& directory, QTextStream& stream, const QString& userGitHub, - const QString& branchGitHub) { + const QString& branchGitHub +) { // Loop over all entries in directory QDirIterator it(directory.toStdString().c_str()); while (it.hasNext()) { @@ -229,9 +232,9 @@ void TestRailInterface::processDirectoryPython(const QString& directory, if (isAValidTestDirectory(nextDirectory)) { // The name of the section is the directory at the end of the path stream << "parent_id = parent_ids.peek()\n"; - stream << "data = { 'name': '" << objectName << "', 'parent_id': parent_id }\n"; + stream << "data = { 'name': '" << objectName << "', 'suite_id': " + _suiteID + ", 'parent_id': parent_id }\n"; - stream << "section = client.send_post('add_section/' + str(" << _project << "), data)\n"; + stream << "section = client.send_post('add_section/' + str(" << _projectID << "), data)\n"; // Now we push the parent_id, and recursively process each directory stream << "parent_ids.push(section['id'])\n\n"; @@ -254,8 +257,8 @@ void TestRailInterface::processDirectoryPython(const QString& directory, // void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirectory, const QString& userGitHub, - const QString& branchGitHub) { - + const QString& branchGitHub +) { QString filename = _outputDirectory + "/addTestCases.py"; if (QFile::exists(filename)) { QFile::remove(filename); @@ -281,9 +284,10 @@ void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirect // top-level section stream << "data = { 'name': '" - << "Test Suite - " << QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm") << "'}\n"; + << "Test Suite - " << QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm") + "', " + << "'suite_id': " + _suiteID + "}\n"; - stream << "section = client.send_post('add_section/' + str(" << _project << "), data)\n"; + stream << "section = client.send_post('add_section/' + str(" << _projectID << "), data)\n"; // Now we push the parent_id, and recursively process each directory stream << "parent_ids.push(section['id'])\n\n"; @@ -382,7 +386,7 @@ void TestRailInterface::getMilestonesFromTestRail() { // Print the list of uncompleted milestones stream << "file = open('" + _outputDirectory + "/milestones.txt', 'w')\n\n"; - stream << "milestones = client.send_get('get_milestones/" + _project + "')\n"; + stream << "milestones = client.send_get('get_milestones/" + _projectID + "')\n"; stream << "for milestone in milestones:\n"; stream << "\tif milestone['is_completed'] == False:\n"; stream << "\t\tfile.write(milestone['name'] + ' ' + str(milestone['id']) + '\\n')\n\n"; @@ -665,12 +669,15 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, int milestone_id = _milestones[_milestoneNames[_testRailSelectorWindow.getMilestoneID()]]; - stream << "data = {\n\t" - << "'title': '" << title << "',\n\t" - << "'template_id': 2,\n\t" - << "'milestone_id': " << milestone_id << ",\n\t" - << "'custom_preconds': " << "'Tester is in an empty region of a domain in which they have edit rights\\n\\n*Note: Press \\'n\\' to advance test script',\n\t" - << "'custom_steps_separated': " << "[\n\t\t{\n\t\t\t'content': '" << testContent << "',\n\t\t\t'expected': '" << testExpected << "'\n\t\t}\n\t]\n" + stream << "data = {\n" + << "\t'title': '" << title << "',\n" + << "\t'template_id': 2,\n" + << "\t'milestone_id': " << milestone_id << ",\n" + << "\t'custom_tester_count': 1,\n" + << "\t'custom_domain_bot_load': 1,\n" + << "\t'custom_added_to_release': 4,\n" + << "\t'custom_preconds': " << "'Tester is in an empty region of a domain in which they have edit rights\\n\\n*Note: Press \\'n\\' to advance test script',\n" + << "\t'custom_steps_separated': " << "[\n\t\t{\n\t\t\t'content': '" << testContent << "',\n\t\t\t'expected': '" << testExpected << "'\n\t\t}\n\t]\n" << "}\n"; stream << "case = client.send_post('add_case/' + str(section_id), data)\n"; diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index f7fe131416..4d12145021 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -70,6 +70,12 @@ public: void updateMilestonesComboData(int exitCode, QProcess::ExitStatus exitStatus); private: + // HighFidelity Interface project ID in TestRail + const int INTERFACE_PROJECT_ID{ 24 }; + + // Rendering suite ID + const int INTERFACE_SUITE_ID{ 1147 }; + QDomDocument _document; BusyWindow _busyWindow; @@ -78,7 +84,8 @@ private: QString _url; QString _user; QString _password; - QString _project; + QString _projectID; + QString _suiteID; QString _testDirectory; QString _outputDirectory; diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp index 9f07c25f3a..afa94b31d0 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp @@ -16,14 +16,14 @@ TestRailSelectorWindow::TestRailSelectorWindow(QWidget *parent) { setupUi(this); - projectLineEdit->setValidator(new QIntValidator(1, 999, this)); + projectIDLineEdit->setValidator(new QIntValidator(1, 999, this)); } void TestRailSelectorWindow::on_acceptButton_clicked() { urlLineEdit->setDisabled(true); userLineEdit->setDisabled(true); passwordLineEdit->setDisabled(true); - projectLineEdit->setDisabled(true); + projectIDLineEdit->setDisabled(true); OKButton->setDisabled(false); milestoneComboBox->setDisabled(false); @@ -64,12 +64,20 @@ QString TestRailSelectorWindow::getPassword() { return passwordLineEdit->text(); } -void TestRailSelectorWindow::setProject(const int project) { - projectLineEdit->setText(QString::number(project)); +void TestRailSelectorWindow::setProjectID(const int project) { + projectIDLineEdit->setText(QString::number(project)); } -int TestRailSelectorWindow::getProject() { - return projectLineEdit->text().toInt(); +int TestRailSelectorWindow::getProjectID() { + return projectIDLineEdit->text().toInt(); +} + +void TestRailSelectorWindow::setSuiteID(const int project) { + suiteIDLineEdit->setText(QString::number(project)); +} + +int TestRailSelectorWindow::getSuiteID() { + return suiteIDLineEdit->text().toInt(); } void TestRailSelectorWindow::updateMilestoneComboBoxData(QStringList data) { diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.h b/tools/auto-tester/src/ui/TestRailSelectorWindow.h index 7072c1cd46..20bb012723 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.h +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.h @@ -28,8 +28,11 @@ public: QString getPassword(); - void setProject(const int project); - int getProject(); + void setProjectID(const int project); + int getProjectID(); + + void setSuiteID(const int project); + int getSuiteID(); bool userCancelled{ false }; diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui index 98c52f3194..5276b458e3 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui @@ -7,7 +7,7 @@ 0 0 489 - 415 + 474 @@ -74,7 +74,7 @@ 120 - 350 + 420 93 28 @@ -87,7 +87,7 @@ 280 - 350 + 420 93 28 @@ -127,7 +127,7 @@ TestRail User - + 200 @@ -155,14 +155,14 @@ - TestRail Project + TestRail Project ID 200 - 220 + 270 231 28 @@ -178,7 +178,7 @@ 270 - 280 + 350 161 22 @@ -191,7 +191,7 @@ 140 - 280 + 350 121 20 @@ -231,8 +231,50 @@ QLineEdit::Normal + + + + 200 + 215 + 231 + 24 + + + + QLineEdit::Normal + + + + + + 70 + 220 + 121 + 20 + + + + + 10 + + + + TestRail Suite ID + + + + urlLineEdit + userLineEdit + passwordLineEdit + projectIDLineEdit + suiteIDLineEdit + acceptButton + milestoneComboBox + OKButton + cancelButton + From 87e7eb78a801349f8cd0257d5e7dc73261a6f0f6 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 13:30:30 -0700 Subject: [PATCH 27/36] Corrected links to MD files. --- tools/auto-tester/src/TestRailInterface.cpp | 13 ++++++++++--- tools/auto-tester/src/ui/TestRailSelectorWindow.cpp | 11 +++++++++++ tools/auto-tester/src/ui/TestRailSelectorWindow.h | 2 ++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 31594fe66a..9142e24986 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -190,6 +190,8 @@ void TestRailInterface::createStackDotPyScript() { } void TestRailInterface::requestTestRailDataFromUser() { + // Make sure correct fields are enabled before calling + _testRailSelectorWindow.reset(); _testRailSelectorWindow.exec(); if (_testRailSelectorWindow.getUserCancelled()) { @@ -428,10 +430,12 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, } requestTestRailDataFromUser(); - getMilestonesFromTestRail(); createTestRailDotPyScript(); createStackDotPyScript(); - } + + // TestRail will be updated after the process initiated by getMilestonesFromTestRail has completed + getMilestonesFromTestRail(); +} void TestRailInterface::createTestSuiteXML(const QString& testDirectory, const QString& outputDirectory, @@ -659,10 +663,13 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, title += " / " + words[i]; } + // To create the path to test.md, prefix by tests, and remove blanks + QString pathToTestMD = QString("/tests/") + title.remove(" "); + stream << "section_id = parent_ids.peek()\n"; QString testMDName = QString("https://github.com/") + userGitHub + "/hifi_tests/blob/" + branchGitHub + - "/tests/content/entity/light/point/create/test.md"; + pathToTestMD + "/test.md "; QString testContent = QString("Execute instructions in [THIS TEST](") + testMDName + ")"; QString testExpected = QString("Refer to the expected result in the linked description."); diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp index afa94b31d0..cb1c805923 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp @@ -19,6 +19,17 @@ TestRailSelectorWindow::TestRailSelectorWindow(QWidget *parent) { projectIDLineEdit->setValidator(new QIntValidator(1, 999, this)); } + +void TestRailSelectorWindow::reset() { + urlLineEdit->setDisabled(false); + userLineEdit->setDisabled(false); + passwordLineEdit->setDisabled(false); + projectIDLineEdit->setDisabled(false); + + OKButton->setDisabled(true); + milestoneComboBox->setDisabled(true); +} + void TestRailSelectorWindow::on_acceptButton_clicked() { urlLineEdit->setDisabled(true); userLineEdit->setDisabled(true); diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.h b/tools/auto-tester/src/ui/TestRailSelectorWindow.h index 20bb012723..89af63d1e2 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.h +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.h @@ -18,6 +18,8 @@ class TestRailSelectorWindow : public QDialog, public Ui::TestRailSelectorWindow public: TestRailSelectorWindow(QWidget* parent = Q_NULLPTR); + void reset(); + bool getUserCancelled(); void setURL(const QString& user); From 22953e6ab022afae18d9e7c90d0145f811b95e30 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 13:48:17 -0700 Subject: [PATCH 28/36] Fixed appearance of dual tests. --- tools/auto-tester/src/TestRailInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 9142e24986..49b497353f 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -241,7 +241,7 @@ void TestRailInterface::processDirectoryPython(const QString& directory, // Now we push the parent_id, and recursively process each directory stream << "parent_ids.push(section['id'])\n\n"; processDirectoryPython(nextDirectory, stream, userGitHub, branchGitHub); - } else if (objectName == "test.js" || objectName == "testStory.js") { + } else if (objectName == "test.js") { processTestPython(nextDirectory, stream, userGitHub, branchGitHub); } } From b3c84408d048451c9652a6a699ef0cb3edf8c1c9 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 13:49:39 -0700 Subject: [PATCH 29/36] oopsy --- assignment-client/src/AssignmentClientMonitor.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 6a9826f877..2847d4ebf1 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -242,11 +242,8 @@ void AssignmentClientMonitor::spawnChildClient() { if (assignmentClient->processId() > 0) { auto pid = assignmentClient->processId(); // make sure we hear that this process has finished when it does - connect( - assignmentClient, - static_cast(&QProcess::finished), - this, - [this, pid](int exitCode, QProcess::ExitStatus exitStatus) { + connect(assignmentClient, static_cast(&QProcess::finished), + this, [this, pid](int exitCode, QProcess::ExitStatus exitStatus) { childProcessFinished(pid, exitCode, exitStatus); }); From 3f91c552231440a0f90d080ee903276e22c7a488 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 15:20:43 -0700 Subject: [PATCH 30/36] Corrected window title. --- tools/auto-tester/src/ui/TestRailSelectorWindow.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui index 5276b458e3..24be35b92f 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui +++ b/tools/auto-tester/src/ui/TestRailSelectorWindow.ui @@ -11,7 +11,7 @@ - MismatchWindow + TestRail Selector Window From 0cf10a649f183304fd19392794dee6c22b68d235 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 16:25:13 -0700 Subject: [PATCH 31/36] WIP - implementing creation of TestRail runs. --- tools/auto-tester/src/Test.cpp | 6 +++- tools/auto-tester/src/Test.h | 3 +- tools/auto-tester/src/TestRailInterface.cpp | 3 ++ tools/auto-tester/src/TestRailInterface.h | 2 ++ tools/auto-tester/src/ui/AutoTester.cpp | 8 +++-- tools/auto-tester/src/ui/AutoTester.h | 3 +- tools/auto-tester/src/ui/AutoTester.ui | 35 ++++++++++++++------- 7 files changed, 44 insertions(+), 16 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index f708137305..93a71d0d28 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -821,7 +821,7 @@ void Test::createTestsOutline() { QMessageBox::information(0, "Success", "Test outline file " + testsOutlineFilename + " has been created"); } -void Test::createTestRailTestSuite() { +void Test::createTestRailTestCases() { QString previousSelection = _testDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { @@ -854,6 +854,10 @@ void Test::createTestRailTestSuite() { } } +void Test::createTestRailRun() { + _testRailInterface.createTestRailRun(); +} + QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { _imageDirectory = QDir(pathToImageDirectory); QStringList nameFilters; diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 36b4cdd897..6d7506b738 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -57,7 +57,8 @@ public: void createTestsOutline(); - void createTestRailTestSuite(); + void createTestRailTestCases(); + void createTestRailRun(); bool compareImageLists(bool isInteractiveMode, QProgressBar* progressBar); diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 49b497353f..962012a3d7 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -689,3 +689,6 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, stream << "case = client.send_post('add_case/' + str(section_id), data)\n"; } + +void TestRailInterface::createTestRailRun() { +} \ No newline at end of file diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 4d12145021..4d863a0e3c 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -69,6 +69,8 @@ public: void updateMilestonesComboData(int exitCode, QProcess::ExitStatus exitStatus); + void createTestRailRun(); + private: // HighFidelity Interface project ID in TestRail const int INTERFACE_PROJECT_ID{ 24 }; diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index 02c3c49a53..697711c4eb 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -68,8 +68,12 @@ void AutoTester::on_createTestsOutlineButton_clicked() { _test->createTestsOutline(); } -void AutoTester::on_createTestRailTestSuiteButton_clicked() { - _test->createTestRailTestSuite(); +void AutoTester::on_createTestRailTestCasesButton_clicked() { + _test->createTestRailTestCases(); +} + +void AutoTester::on_createTestRailRunButton_clicked() { + _test->createTestRailRun(); } // To toggle between show and hide diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index 7f04bd1c49..236a1ed733 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -45,7 +45,8 @@ private slots: void on_createMDFileButton_clicked(); void on_createAllMDFilesButton_clicked(); void on_createTestsOutlineButton_clicked(); - void on_createTestRailTestSuiteButton_clicked(); + void on_createTestRailTestCasesButton_clicked(); + void on_createTestRailRunButton_clicked(); void on_hideTaskbarButton_clicked(); void on_showTaskbarButton_clicked(); diff --git a/tools/auto-tester/src/ui/AutoTester.ui b/tools/auto-tester/src/ui/AutoTester.ui index 9030016f34..680fe17785 100644 --- a/tools/auto-tester/src/ui/AutoTester.ui +++ b/tools/auto-tester/src/ui/AutoTester.ui @@ -7,7 +7,7 @@ 0 0 645 - 570 + 814 @@ -18,7 +18,7 @@ 380 - 450 + 620 101 40 @@ -44,7 +44,7 @@ 430 - 320 + 490 101 40 @@ -57,7 +57,7 @@ 330 - 170 + 340 220 40 @@ -70,7 +70,7 @@ 320 - 330 + 500 131 20 @@ -86,7 +86,7 @@ 320 - 380 + 550 255 23 @@ -99,7 +99,7 @@ 330 - 230 + 400 220 40 @@ -229,17 +229,17 @@ - + - 409 + 410 100 - 141 + 140 40 - Create TestRail Test Suite + Create TestRail Test Cases @@ -271,6 +271,19 @@ XML + + + + 410 + 180 + 140 + 40 + + + + Create TestRail Run + + From 431db7c40fb9925d48a6781d11d365bf4303bbfd Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 17:47:55 -0700 Subject: [PATCH 32/36] Added new window for Runs (not used yet). --- tools/auto-tester/src/TestRailInterface.cpp | 38 ++- tools/auto-tester/src/TestRailInterface.h | 4 +- ...ndow.cpp => TestRailRunSelectorWindow.cpp} | 40 +-- .../src/ui/TestRailRunSelectorWindow.h | 50 ++++ ...Window.ui => TestRailRunSelectorWindow.ui} | 6 +- .../ui/TestRailTestCasesSelectorWindow.cpp | 100 +++++++ ...ow.h => TestRailTestCasesSelectorWindow.h} | 12 +- .../src/ui/TestRailTestCasesSelectorWindow.ui | 280 ++++++++++++++++++ 8 files changed, 479 insertions(+), 51 deletions(-) rename tools/auto-tester/src/ui/{TestRailSelectorWindow.cpp => TestRailRunSelectorWindow.cpp} (57%) create mode 100644 tools/auto-tester/src/ui/TestRailRunSelectorWindow.h rename tools/auto-tester/src/ui/{TestRailSelectorWindow.ui => TestRailRunSelectorWindow.ui} (97%) create mode 100644 tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.cpp rename tools/auto-tester/src/ui/{TestRailSelectorWindow.h => TestRailTestCasesSelectorWindow.h} (70%) create mode 100644 tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.ui diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 962012a3d7..e696f38d0c 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -11,8 +11,6 @@ #include "TestRailInterface.h" #include "Test.h" -#include "ui/TestRailSelectorWindow.h" - #include #include #include @@ -20,17 +18,17 @@ TestRailInterface::TestRailInterface() { _busyWindow.setModal(true); - _testRailSelectorWindow.setModal(true); + _testRailTestCasesSelectorWindow.setModal(true); - _testRailSelectorWindow.setURL("https://highfidelity.testrail.net"); - ////_testRailSelectorWindow.setURL("https://nissimhadar.testrail.io"); - _testRailSelectorWindow.setUser("@highfidelity.io"); + _testRailTestCasesSelectorWindow.setURL("https://highfidelity.testrail.net"); + ////_testRailTestCasesSelectorWindow.setURL("https://nissimhadar.testrail.io"); + _testRailTestCasesSelectorWindow.setUser("@highfidelity.io"); ////_testRailSelectorWindow.setUser("nissim.hadar@gmail.com"); - _testRailSelectorWindow.setProjectID(INTERFACE_PROJECT_ID); + _testRailTestCasesSelectorWindow.setProjectID(INTERFACE_PROJECT_ID); ////_testRailSelectorWindow.setProject(1); - _testRailSelectorWindow.setSuiteID(INTERFACE_SUITE_ID); + _testRailTestCasesSelectorWindow.setSuiteID(INTERFACE_SUITE_ID); } QString TestRailInterface::getObject(const QString& path) { @@ -191,19 +189,19 @@ void TestRailInterface::createStackDotPyScript() { void TestRailInterface::requestTestRailDataFromUser() { // Make sure correct fields are enabled before calling - _testRailSelectorWindow.reset(); - _testRailSelectorWindow.exec(); + _testRailTestCasesSelectorWindow.reset(); + _testRailTestCasesSelectorWindow.exec(); - if (_testRailSelectorWindow.getUserCancelled()) { + if (_testRailTestCasesSelectorWindow.getUserCancelled()) { return; } - _url = _testRailSelectorWindow.getURL() + "/"; - _user = _testRailSelectorWindow.getUser(); - _password = _testRailSelectorWindow.getPassword(); + _url = _testRailTestCasesSelectorWindow.getURL() + "/"; + _user = _testRailTestCasesSelectorWindow.getUser(); + _password = _testRailTestCasesSelectorWindow.getPassword(); ////_password = "tutKA76"; - _projectID = QString::number(_testRailSelectorWindow.getProjectID()); - _suiteID = QString::number(_testRailSelectorWindow.getSuiteID()); + _projectID = QString::number(_testRailTestCasesSelectorWindow.getProjectID()); + _suiteID = QString::number(_testRailTestCasesSelectorWindow.getSuiteID()); } bool TestRailInterface::isAValidTestDirectory(const QString& directory) { @@ -354,11 +352,11 @@ void TestRailInterface::updateMilestonesComboData(int exitCode, QProcess::ExitSt file.close(); // Update the combo - _testRailSelectorWindow.updateMilestoneComboBoxData(_milestoneNames); + _testRailTestCasesSelectorWindow.updateMilestoneComboBoxData(_milestoneNames); - _testRailSelectorWindow.exec(); + _testRailTestCasesSelectorWindow.exec(); - if (_testRailSelectorWindow.getUserCancelled()) { + if (_testRailTestCasesSelectorWindow.getUserCancelled()) { return; } @@ -674,7 +672,7 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, QString testContent = QString("Execute instructions in [THIS TEST](") + testMDName + ")"; QString testExpected = QString("Refer to the expected result in the linked description."); - int milestone_id = _milestones[_milestoneNames[_testRailSelectorWindow.getMilestoneID()]]; + int milestone_id = _milestones[_milestoneNames[_testRailTestCasesSelectorWindow.getMilestoneID()]]; stream << "data = {\n" << "\t'title': '" << title << "',\n" diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 4d863a0e3c..b6fe53bc30 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -12,7 +12,7 @@ #define hifi_test_testrail_interface_h #include "ui/BusyWindow.h" -#include "ui/TestRailSelectorWindow.h" +#include "ui/TestRailTestCasesSelectorWindow.h" #include #include #include @@ -81,7 +81,7 @@ private: QDomDocument _document; BusyWindow _busyWindow; - TestRailSelectorWindow _testRailSelectorWindow; + TestRailTestCasesSelectorWindow _testRailTestCasesSelectorWindow; QString _url; QString _user; diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.cpp similarity index 57% rename from tools/auto-tester/src/ui/TestRailSelectorWindow.cpp rename to tools/auto-tester/src/ui/TestRailRunSelectorWindow.cpp index cb1c805923..4da4b1493f 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.cpp +++ b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.cpp @@ -1,26 +1,26 @@ // -// TestRailSelectorWindow.cpp +// TestRailRunSelectorWindow.cpp // -// Created by Nissim Hadar on 26 Jul 2017. +// Created by Nissim Hadar on 31 Jul 2017. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "TestRailSelectorWindow.h" +#include "TestRailRunSelectorWindow.h" #include #include -TestRailSelectorWindow::TestRailSelectorWindow(QWidget *parent) { +TestRailRunSelectorWindow::TestRailRunSelectorWindow(QWidget *parent) { setupUi(this); projectIDLineEdit->setValidator(new QIntValidator(1, 999, this)); } -void TestRailSelectorWindow::reset() { +void TestRailRunSelectorWindow::reset() { urlLineEdit->setDisabled(false); userLineEdit->setDisabled(false); passwordLineEdit->setDisabled(false); @@ -30,7 +30,7 @@ void TestRailSelectorWindow::reset() { milestoneComboBox->setDisabled(true); } -void TestRailSelectorWindow::on_acceptButton_clicked() { +void TestRailRunSelectorWindow::on_acceptButton_clicked() { urlLineEdit->setDisabled(true); userLineEdit->setDisabled(true); passwordLineEdit->setDisabled(true); @@ -41,60 +41,60 @@ void TestRailSelectorWindow::on_acceptButton_clicked() { close(); } -void TestRailSelectorWindow::on_OKButton_clicked() { +void TestRailRunSelectorWindow::on_OKButton_clicked() { userCancelled = false; close(); } -void TestRailSelectorWindow::on_cancelButton_clicked() { +void TestRailRunSelectorWindow::on_cancelButton_clicked() { userCancelled = true; close(); } -bool TestRailSelectorWindow::getUserCancelled() { +bool TestRailRunSelectorWindow::getUserCancelled() { return userCancelled; } -void TestRailSelectorWindow::setURL(const QString& user) { +void TestRailRunSelectorWindow::setURL(const QString& user) { urlLineEdit->setText(user); } -QString TestRailSelectorWindow::getURL() { +QString TestRailRunSelectorWindow::getURL() { return urlLineEdit->text(); } -void TestRailSelectorWindow::setUser(const QString& user) { +void TestRailRunSelectorWindow::setUser(const QString& user) { userLineEdit->setText(user); } -QString TestRailSelectorWindow::getUser() { +QString TestRailRunSelectorWindow::getUser() { return userLineEdit->text(); } -QString TestRailSelectorWindow::getPassword() { +QString TestRailRunSelectorWindow::getPassword() { return passwordLineEdit->text(); } -void TestRailSelectorWindow::setProjectID(const int project) { +void TestRailRunSelectorWindow::setProjectID(const int project) { projectIDLineEdit->setText(QString::number(project)); } -int TestRailSelectorWindow::getProjectID() { +int TestRailRunSelectorWindow::getProjectID() { return projectIDLineEdit->text().toInt(); } -void TestRailSelectorWindow::setSuiteID(const int project) { +void TestRailRunSelectorWindow::setSuiteID(const int project) { suiteIDLineEdit->setText(QString::number(project)); } -int TestRailSelectorWindow::getSuiteID() { +int TestRailRunSelectorWindow::getSuiteID() { return suiteIDLineEdit->text().toInt(); } -void TestRailSelectorWindow::updateMilestoneComboBoxData(QStringList data) { +void TestRailRunSelectorWindow::updateMilestoneComboBoxData(QStringList data) { milestoneComboBox->insertItems(0, data); } -int TestRailSelectorWindow::getMilestoneID() { +int TestRailRunSelectorWindow::getMilestoneID() { return milestoneComboBox->currentIndex(); } \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailRunSelectorWindow.h b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.h new file mode 100644 index 0000000000..ece70124b9 --- /dev/null +++ b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.h @@ -0,0 +1,50 @@ +// +// TestRailRunSelectorWindow.h +// +// Created by Nissim Hadar on 31 Jul 2017. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_TestRailRunSelectorWindow_h +#define hifi_TestRailRunSelectorWindow_h + +#include "ui_TestRailRunSelectorWindow.h" + +class TestRailRunSelectorWindow : public QDialog, public Ui::TestRailRunSelectorWindow { + Q_OBJECT + +public: + TestRailRunSelectorWindow(QWidget* parent = Q_NULLPTR); + + void reset(); + + bool getUserCancelled(); + + void setURL(const QString& user); + QString getURL(); + + void setUser(const QString& user); + QString getUser(); + + QString getPassword(); + + void setProjectID(const int project); + int getProjectID(); + + void setSuiteID(const int project); + int getSuiteID(); + + bool userCancelled{ false }; + + void updateMilestoneComboBoxData(QStringList data); + int getMilestoneID(); + +private slots: + void on_acceptButton_clicked(); + void on_OKButton_clicked(); + void on_cancelButton_clicked(); +}; + +#endif \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui similarity index 97% rename from tools/auto-tester/src/ui/TestRailSelectorWindow.ui rename to tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui index 24be35b92f..c83b98c5cc 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.ui +++ b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui @@ -1,7 +1,7 @@ - TestRailSelectorWindow - + TestRailRunSelectorWindow + 0 @@ -11,7 +11,7 @@ - TestRail Selector Window + TestRail Run Selector Window diff --git a/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.cpp new file mode 100644 index 0000000000..afef51a321 --- /dev/null +++ b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.cpp @@ -0,0 +1,100 @@ +// +// TestRailTestCasesSelectorWindow.cpp +// +// Created by Nissim Hadar on 26 Jul 2017. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "TestRailTestCasesSelectorWindow.h" + +#include + +#include + +TestRailTestCasesSelectorWindow::TestRailTestCasesSelectorWindow(QWidget *parent) { + setupUi(this); + + projectIDLineEdit->setValidator(new QIntValidator(1, 999, this)); +} + + +void TestRailTestCasesSelectorWindow::reset() { + urlLineEdit->setDisabled(false); + userLineEdit->setDisabled(false); + passwordLineEdit->setDisabled(false); + projectIDLineEdit->setDisabled(false); + + OKButton->setDisabled(true); + milestoneComboBox->setDisabled(true); +} + +void TestRailTestCasesSelectorWindow::on_acceptButton_clicked() { + urlLineEdit->setDisabled(true); + userLineEdit->setDisabled(true); + passwordLineEdit->setDisabled(true); + projectIDLineEdit->setDisabled(true); + + OKButton->setDisabled(false); + milestoneComboBox->setDisabled(false); + close(); +} + +void TestRailTestCasesSelectorWindow::on_OKButton_clicked() { + userCancelled = false; + close(); +} + +void TestRailTestCasesSelectorWindow::on_cancelButton_clicked() { + userCancelled = true; + close(); +} + +bool TestRailTestCasesSelectorWindow::getUserCancelled() { + return userCancelled; +} + +void TestRailTestCasesSelectorWindow::setURL(const QString& user) { + urlLineEdit->setText(user); +} + +QString TestRailTestCasesSelectorWindow::getURL() { + return urlLineEdit->text(); +} + +void TestRailTestCasesSelectorWindow::setUser(const QString& user) { + userLineEdit->setText(user); +} + +QString TestRailTestCasesSelectorWindow::getUser() { + return userLineEdit->text(); +} + +QString TestRailTestCasesSelectorWindow::getPassword() { + return passwordLineEdit->text(); +} + +void TestRailTestCasesSelectorWindow::setProjectID(const int project) { + projectIDLineEdit->setText(QString::number(project)); +} + +int TestRailTestCasesSelectorWindow::getProjectID() { + return projectIDLineEdit->text().toInt(); +} + +void TestRailTestCasesSelectorWindow::setSuiteID(const int project) { + suiteIDLineEdit->setText(QString::number(project)); +} + +int TestRailTestCasesSelectorWindow::getSuiteID() { + return suiteIDLineEdit->text().toInt(); +} + +void TestRailTestCasesSelectorWindow::updateMilestoneComboBoxData(QStringList data) { + milestoneComboBox->insertItems(0, data); +} + +int TestRailTestCasesSelectorWindow::getMilestoneID() { + return milestoneComboBox->currentIndex(); +} \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailSelectorWindow.h b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.h similarity index 70% rename from tools/auto-tester/src/ui/TestRailSelectorWindow.h rename to tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.h index 89af63d1e2..fb9d741bab 100644 --- a/tools/auto-tester/src/ui/TestRailSelectorWindow.h +++ b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.h @@ -1,5 +1,5 @@ // -// TestRailSelectorWindow.h +// TestRailTestCasesSelectorWindow.h // // Created by Nissim Hadar on 26 Jul 2017. // Copyright 2013 High Fidelity, Inc. @@ -7,16 +7,16 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_TestRailSelectorWindow_h -#define hifi_TestRailSelectorWindow_h +#ifndef hifi_TestRailTestCasesSelectorWindow_h +#define hifi_TestRailTestCasesSelectorWindow_h -#include "ui_TestRailSelectorWindow.h" +#include "ui_TestRailTestCasesSelectorWindow.h" -class TestRailSelectorWindow : public QDialog, public Ui::TestRailSelectorWindow { +class TestRailTestCasesSelectorWindow : public QDialog, public Ui::TestRailTestCasesSelectorWindow { Q_OBJECT public: - TestRailSelectorWindow(QWidget* parent = Q_NULLPTR); + TestRailTestCasesSelectorWindow(QWidget* parent = Q_NULLPTR); void reset(); diff --git a/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.ui new file mode 100644 index 0000000000..9233f7a629 --- /dev/null +++ b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.ui @@ -0,0 +1,280 @@ + + + TestRailTestCasesSelectorWindow + + + + 0 + 0 + 489 + 474 + + + + TestRail Test Case Selector Window + + + + + 30 + 850 + 500 + 28 + + + + + 12 + + + + similarity + + + + + + 70 + 125 + 121 + 20 + + + + + 10 + + + + TestRail Password + + + + + + 70 + 25 + 121 + 20 + + + + + 10 + + + + TestRail URL + + + + + false + + + + 120 + 420 + 93 + 28 + + + + OK + + + + + + 280 + 420 + 93 + 28 + + + + Cancel + + + + + + 200 + 120 + 231 + 24 + + + + QLineEdit::Password + + + + + + 70 + 75 + 121 + 20 + + + + + 10 + + + + TestRail User + + + + + + 200 + 170 + 231 + 24 + + + + QLineEdit::Normal + + + + + + 70 + 175 + 121 + 20 + + + + + 10 + + + + TestRail Project ID + + + + + + 200 + 270 + 231 + 28 + + + + Accept + + + + + false + + + + 270 + 350 + 161 + 22 + + + + + + true + + + + 140 + 350 + 121 + 20 + + + + + 10 + + + + TestRail Milestone + + + + + + 200 + 20 + 231 + 24 + + + + QLineEdit::Normal + + + + + + 200 + 70 + 231 + 24 + + + + QLineEdit::Normal + + + + + + 200 + 215 + 231 + 24 + + + + QLineEdit::Normal + + + + + + 70 + 220 + 121 + 20 + + + + + 10 + + + + TestRail Suite ID + + + + + + urlLineEdit + userLineEdit + passwordLineEdit + projectIDLineEdit + suiteIDLineEdit + acceptButton + milestoneComboBox + OKButton + cancelButton + + + + From 121f5e012956ab9b105d174cb3bfd62d89f28e78 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 17:58:11 -0700 Subject: [PATCH 33/36] Set window modality in UI files. --- tools/auto-tester/src/TestRailInterface.cpp | 4 +--- tools/auto-tester/src/TestRailInterface.h | 6 +++++- tools/auto-tester/src/ui/BusyWindow.ui | 3 +++ tools/auto-tester/src/ui/MismatchWindow.ui | 5 ++++- tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui | 3 +++ 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index e696f38d0c..d82add0db7 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -17,9 +17,6 @@ #include TestRailInterface::TestRailInterface() { - _busyWindow.setModal(true); - _testRailTestCasesSelectorWindow.setModal(true); - _testRailTestCasesSelectorWindow.setURL("https://highfidelity.testrail.net"); ////_testRailTestCasesSelectorWindow.setURL("https://nissimhadar.testrail.io"); _testRailTestCasesSelectorWindow.setUser("@highfidelity.io"); @@ -689,4 +686,5 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, } void TestRailInterface::createTestRailRun() { + } \ No newline at end of file diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index b6fe53bc30..53d4bee618 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -12,7 +12,10 @@ #define hifi_test_testrail_interface_h #include "ui/BusyWindow.h" + #include "ui/TestRailTestCasesSelectorWindow.h" +#include "ui/TestRailRunSelectorWindow.h" + #include #include #include @@ -54,7 +57,7 @@ public: void createTestRailDotPyScript(); void createStackDotPyScript(); void requestTestRailDataFromUser(); - void requestMilestoneFromUser(); + void createAddTestCasesPythonScript(const QString& testDirectory, const QString& userGitHub, const QString& branchGitHub); @@ -82,6 +85,7 @@ private: BusyWindow _busyWindow; TestRailTestCasesSelectorWindow _testRailTestCasesSelectorWindow; + TestRailRunSelectorWindow _testRailRunSelectorWindow; QString _url; QString _user; diff --git a/tools/auto-tester/src/ui/BusyWindow.ui b/tools/auto-tester/src/ui/BusyWindow.ui index f04a39418b..c237566a5e 100644 --- a/tools/auto-tester/src/ui/BusyWindow.ui +++ b/tools/auto-tester/src/ui/BusyWindow.ui @@ -2,6 +2,9 @@ BusyWindow + + Qt::ApplicationModal + 0 diff --git a/tools/auto-tester/src/ui/MismatchWindow.ui b/tools/auto-tester/src/ui/MismatchWindow.ui index 72f86261ab..8a174989d4 100644 --- a/tools/auto-tester/src/ui/MismatchWindow.ui +++ b/tools/auto-tester/src/ui/MismatchWindow.ui @@ -2,6 +2,9 @@ MismatchWindow + + Qt::ApplicationModal + 0 @@ -193,4 +196,4 @@ - \ No newline at end of file + diff --git a/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui index c83b98c5cc..a15c1b6d0c 100644 --- a/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui +++ b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui @@ -2,6 +2,9 @@ TestRailRunSelectorWindow + + Qt::ApplicationModal + 0 From 36d131592d71095a5ab81d3142c4c8d35505e854 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 31 Jul 2018 22:23:10 -0700 Subject: [PATCH 34/36] WIP --- tools/auto-tester/src/TestRailInterface.cpp | 34 +++++++++++++++++++-- tools/auto-tester/src/TestRailInterface.h | 7 ++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index d82add0db7..3161e4109c 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -26,6 +26,16 @@ TestRailInterface::TestRailInterface() { ////_testRailSelectorWindow.setProject(1); _testRailTestCasesSelectorWindow.setSuiteID(INTERFACE_SUITE_ID); + + _testRailRunSelectorWindow.setURL("https://highfidelity.testrail.net"); + ////_testRailRunSelectorWindow.setURL("https://nissimhadar.testrail.io"); + _testRailRunSelectorWindow.setUser("@highfidelity.io"); + ////_testRailSelectorWindow.setUser("nissim.hadar@gmail.com"); + + _testRailRunSelectorWindow.setProjectID(INTERFACE_PROJECT_ID); + ////_testRailSelectorWindow.setProject(1); + + _testRailRunSelectorWindow.setSuiteID(INTERFACE_SUITE_ID); } QString TestRailInterface::getObject(const QString& path) { @@ -184,7 +194,7 @@ void TestRailInterface::createStackDotPyScript() { file.close(); } -void TestRailInterface::requestTestRailDataFromUser() { +void TestRailInterface::requestTestRailTestCasesDataFromUser() { // Make sure correct fields are enabled before calling _testRailTestCasesSelectorWindow.reset(); _testRailTestCasesSelectorWindow.exec(); @@ -312,6 +322,11 @@ void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirect } void TestRailInterface::updateMilestonesComboData(int exitCode, QProcess::ExitStatus exitStatus) { + // Quit if user has previously cancelled + if (_testRailTestCasesSelectorWindow.getUserCancelled()) { + return; + } + // Check if process completed successfully if (exitStatus != QProcess::NormalExit) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), @@ -424,7 +439,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, return; } - requestTestRailDataFromUser(); + requestTestRailTestCasesDataFromUser(); createTestRailDotPyScript(); createStackDotPyScript(); @@ -685,6 +700,19 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, stream << "case = client.send_post('add_case/' + str(section_id), data)\n"; } +void TestRailInterface::requestTestRailRunDataFromUser() { + _testRailRunSelectorWindow.reset(); + _testRailRunSelectorWindow.exec(); +} + +void TestRailInterface::getTestCasesFromTestRail() { +} + void TestRailInterface::createTestRailRun() { - + requestTestRailRunDataFromUser(); + createTestRailDotPyScript(); + createStackDotPyScript(); + + // TestRail will be updated after the process initiated by getTestCasesFromTestRail has completed + getTestCasesFromTestRail(); } \ No newline at end of file diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 53d4bee618..4501be2d87 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -54,9 +54,13 @@ public: const QString& branchGitHub); void getMilestonesFromTestRail(); + void getTestCasesFromTestRail(); + void createTestRailDotPyScript(); void createStackDotPyScript(); - void requestTestRailDataFromUser(); + + void requestTestRailTestCasesDataFromUser(); + void requestTestRailRunDataFromUser(); void createAddTestCasesPythonScript(const QString& testDirectory, const QString& userGitHub, @@ -68,6 +72,7 @@ public: const QString& branchGitHub); bool isAValidTestDirectory(const QString& directory); + QString getObject(const QString& path); void updateMilestonesComboData(int exitCode, QProcess::ExitStatus exitStatus); From 9957fc9474849bc3c061e2059f827809870febc1 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 1 Aug 2018 15:13:44 -0700 Subject: [PATCH 35/36] Can create list of highest level sections. --- tools/auto-tester/src/Test.cpp | 6 +- tools/auto-tester/src/TestRailInterface.cpp | 167 ++++++++++++------ tools/auto-tester/src/TestRailInterface.h | 5 +- .../src/ui/TestRailRunSelectorWindow.cpp | 13 +- .../src/ui/TestRailRunSelectorWindow.h | 4 +- .../src/ui/TestRailRunSelectorWindow.ui | 12 +- .../ui/TestRailTestCasesSelectorWindow.cpp | 10 +- .../src/ui/TestRailTestCasesSelectorWindow.h | 2 +- .../src/ui/TestRailTestCasesSelectorWindow.ui | 4 +- 9 files changed, 139 insertions(+), 84 deletions(-) diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 93a71d0d28..eba1cf231b 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -838,7 +838,7 @@ void Test::createTestRailTestCases() { } QString outputDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store generated files in", - parent, QFileDialog::ShowDirsOnly); + nullptr, QFileDialog::ShowDirsOnly); // If user cancelled then return if (outputDirectory == "") { @@ -855,7 +855,9 @@ void Test::createTestRailTestCases() { } void Test::createTestRailRun() { - _testRailInterface.createTestRailRun(); + QString outputDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store generated files in", + nullptr, QFileDialog::ShowDirsOnly); + _testRailInterface.createTestRailRun(outputDirectory); } QStringList Test::createListOfAll_imagesInDirectory(const QString& imageFormat, const QString& pathToImageDirectory) { diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 3161e4109c..9520ee645b 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -227,8 +227,7 @@ bool TestRailInterface::isAValidTestDirectory(const QString& directory) { void TestRailInterface::processDirectoryPython(const QString& directory, QTextStream& stream, const QString& userGitHub, - const QString& branchGitHub -) { + const QString& branchGitHub) { // Loop over all entries in directory QDirIterator it(directory.toStdString().c_str()); while (it.hasNext()) { @@ -255,7 +254,7 @@ void TestRailInterface::processDirectoryPython(const QString& directory, stream << "parent_ids.pop()\n\n"; } - // A suite of TestRail test cases contains trees. +// A suite of TestRail test cases contains trees. // The nodes of the trees are sections // The leaves are the test cases // @@ -264,8 +263,7 @@ void TestRailInterface::processDirectoryPython(const QString& directory, // void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirectory, const QString& userGitHub, - const QString& branchGitHub -) { + const QString& branchGitHub) { QString filename = _outputDirectory + "/addTestCases.py"; if (QFile::exists(filename)) { QFile::remove(filename); @@ -302,19 +300,15 @@ void TestRailInterface::createAddTestCasesPythonScript(const QString& testDirect file.close(); - if (QMessageBox::Yes == QMessageBox(QMessageBox::Information, "Python script has been created", "Do you want to run the script and update TestRail?", QMessageBox::Yes | QMessageBox::No).exec()) { + if (QMessageBox::Yes == QMessageBox(QMessageBox::Information, "Python script has been created", + "Do you want to run the script and update TestRail?", + QMessageBox::Yes | QMessageBox::No) + .exec()) { QProcess* process = new QProcess(); - connect(process, &QProcess::started, this, - [=]() { - _busyWindow.exec(); - } - ); + connect(process, &QProcess::started, this, [=]() { _busyWindow.exec(); }); - connect(process, static_cast(&QProcess::finished), this, - [=](int exitCode, QProcess::ExitStatus exitStatus) { - _busyWindow.hide(); - } - ); + connect(process, static_cast(&QProcess::finished), this, + [=](int exitCode, QProcess::ExitStatus exitStatus) { _busyWindow.hide(); }); QStringList parameters = QStringList() << _outputDirectory + "/addTestCases.py"; process->start(_pythonCommand, parameters); @@ -331,7 +325,7 @@ void TestRailInterface::updateMilestonesComboData(int exitCode, QProcess::ExitSt if (exitStatus != QProcess::NormalExit) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not get milestones from TestRail"); - exit(-1); + exit(-1); } // Create map of milestones from the file created by the process @@ -347,7 +341,7 @@ void TestRailInterface::updateMilestonesComboData(int exitCode, QProcess::ExitSt QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), - "Could not open " + _outputDirectory + "/milestones.txt"); + "Could not open " + _outputDirectory + "/milestones.txt"); exit(-1); } @@ -364,7 +358,7 @@ void TestRailInterface::updateMilestonesComboData(int exitCode, QProcess::ExitSt file.close(); // Update the combo - _testRailTestCasesSelectorWindow.updateMilestoneComboBoxData(_milestoneNames); + _testRailTestCasesSelectorWindow.updateMilestonesComboBoxData(_milestoneNames); _testRailTestCasesSelectorWindow.exec(); @@ -375,6 +369,9 @@ void TestRailInterface::updateMilestonesComboData(int exitCode, QProcess::ExitSt createAddTestCasesPythonScript(_testDirectory, _userGitHub, _branchGitHub); } +void TestRailInterface::updateSectionsComboData(int exitCode, QProcess::ExitStatus exitStatus) { +} + void TestRailInterface::getMilestonesFromTestRail() { QString filename = _outputDirectory + "/getMilestones.py"; if (QFile::exists(filename)) { @@ -408,10 +405,7 @@ void TestRailInterface::getMilestonesFromTestRail() { QProcess* process = new QProcess(); connect(process, static_cast(&QProcess::finished), this, - [=](int exitCode, QProcess::ExitStatus exitStatus) { - updateMilestonesComboData(exitCode, exitStatus); - } - ); + [=](int exitCode, QProcess::ExitStatus exitStatus) { updateMilestonesComboData(exitCode, exitStatus); }); QStringList parameters = QStringList() << _outputDirectory + "/getMilestones.py "; process->start(_pythonCommand, parameters); @@ -421,7 +415,6 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, const QString& outputDirectory, const QString& userGitHub, const QString& branchGitHub) { - _testDirectory = testDirectory; _outputDirectory = outputDirectory; _userGitHub = userGitHub; @@ -435,7 +428,8 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, } _pythonCommand = _pythonPath + "/" + pythonExe; } else { - QMessageBox::critical(0, "PYTHON_PATH not defined", "Please set PYTHON_PATH to directory containing the Python executable"); + QMessageBox::critical(0, "PYTHON_PATH not defined", + "Please set PYTHON_PATH to directory containing the Python executable"); return; } @@ -447,12 +441,11 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, getMilestonesFromTestRail(); } - void TestRailInterface::createTestSuiteXML(const QString& testDirectory, - const QString& outputDirectory, - const QString& userGitHub, - const QString& branchGitHub) { - - _outputDirectory = outputDirectory; +void TestRailInterface::createTestSuiteXML(const QString& testDirectory, + const QString& outputDirectory, + const QString& userGitHub, + const QString& branchGitHub) { + _outputDirectory = outputDirectory; QDomProcessingInstruction instruction = _document.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); _document.appendChild(instruction); @@ -464,7 +457,8 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, QDomElement topLevelSection = _document.createElement("section"); QDomElement suiteName = _document.createElement("name"); - suiteName.appendChild(_document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm"))); + suiteName.appendChild( + _document.createTextNode("Test Suite - " + QDateTime::currentDateTime().toString("yyyy-MM-ddTHH:mm"))); topLevelSection.appendChild(suiteName); // This is the first call to 'process'. This is then called recursively to build the full XML tree @@ -475,10 +469,11 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, root.appendChild(topLevelSection); // Write to file - const QString testRailsFilename{ _outputDirectory + "/TestRailSuite.xml" }; + const QString testRailsFilename{ _outputDirectory + "/TestRailSuite.xml" }; QFile file(testRailsFilename); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Could not create XML file"); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not create XML file"); exit(-1); } @@ -499,10 +494,10 @@ QDomElement TestRailInterface::processDirectoryXML(const QString& directory, // Loop over all entries in directory QDirIterator it(directory.toStdString().c_str()); while (it.hasNext()) { - QString nextDirectory = it.next(); + QString nextDirectory = it.next(); - // The object name appears after the last slash (we are assured there is at least 1). - QString objectName = getObject(nextDirectory); + // The object name appears after the last slash (we are assured there is at least 1). + QString objectName = getObject(nextDirectory); // Only process directories if (isAValidTestDirectory(nextDirectory)) { @@ -538,7 +533,7 @@ QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, const QString& branchGitHub, const QDomElement& element) { QDomElement result = element; - + QDomElement caseElement = _document.createElement("case"); caseElement.appendChild(_document.createElement("id")); @@ -551,7 +546,8 @@ QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, while (words[i] != "tests") { ++i; if (i >= words.length() - 1) { - QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Folder \"tests\" not found in " + fullDirectory); + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Folder \"tests\" not found in " + fullDirectory); exit(-1); } } @@ -595,7 +591,8 @@ QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, domain_bot_loadElementId.appendChild(_document.createTextNode("1")); domain_bot_loadElement.appendChild(domain_bot_loadElementId); QDomElement domain_bot_loadElementValue = _document.createElement("value"); - domain_bot_loadElementValue.appendChild(_document.createTextNode(" Without Bots (hifiqa-rc / hifi-qa-stable / hifiqa-master)")); + domain_bot_loadElementValue.appendChild( + _document.createTextNode(" Without Bots (hifiqa-rc / hifi-qa-stable / hifiqa-master)")); domain_bot_loadElement.appendChild(domain_bot_loadElementValue); customElement.appendChild(domain_bot_loadElement); @@ -618,7 +615,8 @@ QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, customElement.appendChild(added_to_releaseElement); QDomElement precondsElement = _document.createElement("preconds"); - precondsElement.appendChild(_document.createTextNode("Tester is in an empty region of a domain in which they have edit rights\n\n*Note: Press 'n' to advance test script")); + precondsElement.appendChild(_document.createTextNode( + "Tester is in an empty region of a domain in which they have edit rights\n\n*Note: Press 'n' to advance test script")); customElement.appendChild(precondsElement); QString testMDName = QString("https://github.com/") + userGitHub + "/hifi_tests/blob/" + branchGitHub + @@ -630,7 +628,8 @@ QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, stepIndexElement.appendChild(_document.createTextNode("1")); stepElement.appendChild(stepIndexElement); QDomElement stepContentElement = _document.createElement("content"); - stepContentElement.appendChild(_document.createTextNode(QString("Execute instructions in [THIS TEST](") + testMDName + ")")); + stepContentElement.appendChild( + _document.createTextNode(QString("Execute instructions in [THIS TEST](") + testMDName + ")")); stepElement.appendChild(stepContentElement); QDomElement stepExpectedElement = _document.createElement("expected"); stepExpectedElement.appendChild(_document.createTextNode("Refer to the expected result in the linked description.")); @@ -645,7 +644,7 @@ QDomElement TestRailInterface::processTestXML(const QString& fullDirectory, caseElement.appendChild(customElement); result.appendChild(caseElement); - + return result; } @@ -678,24 +677,27 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, stream << "section_id = parent_ids.peek()\n"; - QString testMDName = QString("https://github.com/") + userGitHub + "/hifi_tests/blob/" + branchGitHub + - pathToTestMD + "/test.md "; + QString testMDName = + QString("https://github.com/") + userGitHub + "/hifi_tests/blob/" + branchGitHub + pathToTestMD + "/test.md "; QString testContent = QString("Execute instructions in [THIS TEST](") + testMDName + ")"; QString testExpected = QString("Refer to the expected result in the linked description."); int milestone_id = _milestones[_milestoneNames[_testRailTestCasesSelectorWindow.getMilestoneID()]]; - stream << "data = {\n" - << "\t'title': '" << title << "',\n" - << "\t'template_id': 2,\n" - << "\t'milestone_id': " << milestone_id << ",\n" - << "\t'custom_tester_count': 1,\n" - << "\t'custom_domain_bot_load': 1,\n" - << "\t'custom_added_to_release': 4,\n" - << "\t'custom_preconds': " << "'Tester is in an empty region of a domain in which they have edit rights\\n\\n*Note: Press \\'n\\' to advance test script',\n" - << "\t'custom_steps_separated': " << "[\n\t\t{\n\t\t\t'content': '" << testContent << "',\n\t\t\t'expected': '" << testExpected << "'\n\t\t}\n\t]\n" - << "}\n"; + stream << "data = {\n" + << "\t'title': '" << title << "',\n" + << "\t'template_id': 2,\n" + << "\t'milestone_id': " << milestone_id << ",\n" + << "\t'custom_tester_count': 1,\n" + << "\t'custom_domain_bot_load': 1,\n" + << "\t'custom_added_to_release': 4,\n" + << "\t'custom_preconds': " + << "'Tester is in an empty region of a domain in which they have edit rights\\n\\n*Note: Press \\'n\\' to advance " + "test script',\n" + << "\t'custom_steps_separated': " + << "[\n\t\t{\n\t\t\t'content': '" << testContent << "',\n\t\t\t'expected': '" << testExpected << "'\n\t\t}\n\t]\n" + << "}\n"; stream << "case = client.send_post('add_case/' + str(section_id), data)\n"; } @@ -703,16 +705,65 @@ void TestRailInterface::processTestPython(const QString& fullDirectory, void TestRailInterface::requestTestRailRunDataFromUser() { _testRailRunSelectorWindow.reset(); _testRailRunSelectorWindow.exec(); + + if (_testRailRunSelectorWindow.getUserCancelled()) { + return; + } + + _url = _testRailRunSelectorWindow.getURL() + "/"; + _user = _testRailRunSelectorWindow.getUser(); + _password = _testRailRunSelectorWindow.getPassword(); + ////_password = "tutKA76"; + _projectID = QString::number(_testRailRunSelectorWindow.getProjectID()); + _suiteID = QString::number(_testRailRunSelectorWindow.getSuiteID()); } -void TestRailInterface::getTestCasesFromTestRail() { +void TestRailInterface::getTestSectionsFromTestRail() { + QString filename = _outputDirectory + "/getSections.py"; + if (QFile::exists(filename)) { + QFile::remove(filename); + } + QFile file(filename); + + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not create 'getSections.py'"); + exit(-1); + } + + QTextStream stream(&file); + + // Code to access TestRail + stream << "from testrail import *\n"; + stream << "client = APIClient('" << _url.toStdString().c_str() << "')\n"; + stream << "client.user = '" << _user << "'\n"; + stream << "client.password = '" << _password << "'\n\n"; + + // Print the list of sections without parents + stream << "sections = client.send_get('get_sections/" + _projectID + "&suite_id=" + _suiteID + "')\n\n"; + stream << "file = open('" + _outputDirectory + "/sections.txt', 'w')\n\n"; + stream << "for section in sections:\n"; + stream << "\tif section['parent_id'] == None:\n"; + stream << "\t\tfile.write(section['name'] + ' ' + str(section['id']) + '\\n')\n\n"; + stream << "file.close()\n"; + + file.close(); + + QProcess* process = new QProcess(); + connect(process, static_cast(&QProcess::finished), this, + [=](int exitCode, QProcess::ExitStatus exitStatus) { updateSectionsComboData(exitCode, exitStatus); }); + + QStringList parameters = QStringList() << _outputDirectory + "/getSections.py "; + process->start(_pythonCommand, parameters); } -void TestRailInterface::createTestRailRun() { +void TestRailInterface::createTestRailRun(const QString& outputDirectory) { + _outputDirectory = outputDirectory; + requestTestRailRunDataFromUser(); createTestRailDotPyScript(); createStackDotPyScript(); // TestRail will be updated after the process initiated by getTestCasesFromTestRail has completed - getTestCasesFromTestRail(); + getTestSectionsFromTestRail(); } \ No newline at end of file diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 4501be2d87..0c5f11971c 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -54,7 +54,7 @@ public: const QString& branchGitHub); void getMilestonesFromTestRail(); - void getTestCasesFromTestRail(); + void getTestSectionsFromTestRail(); void createTestRailDotPyScript(); void createStackDotPyScript(); @@ -76,8 +76,9 @@ public: QString getObject(const QString& path); void updateMilestonesComboData(int exitCode, QProcess::ExitStatus exitStatus); + void updateSectionsComboData(int exitCode, QProcess::ExitStatus exitStatus); - void createTestRailRun(); + void createTestRailRun(const QString& outputDirectory); private: // HighFidelity Interface project ID in TestRail diff --git a/tools/auto-tester/src/ui/TestRailRunSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.cpp index 4da4b1493f..9d960b16c1 100644 --- a/tools/auto-tester/src/ui/TestRailRunSelectorWindow.cpp +++ b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.cpp @@ -27,7 +27,7 @@ void TestRailRunSelectorWindow::reset() { projectIDLineEdit->setDisabled(false); OKButton->setDisabled(true); - milestoneComboBox->setDisabled(true); + sectionsComboBox->setDisabled(true); } void TestRailRunSelectorWindow::on_acceptButton_clicked() { @@ -37,7 +37,7 @@ void TestRailRunSelectorWindow::on_acceptButton_clicked() { projectIDLineEdit->setDisabled(true); OKButton->setDisabled(false); - milestoneComboBox->setDisabled(false); + sectionsComboBox->setDisabled(false); close(); } @@ -91,10 +91,11 @@ int TestRailRunSelectorWindow::getSuiteID() { return suiteIDLineEdit->text().toInt(); } -void TestRailRunSelectorWindow::updateMilestoneComboBoxData(QStringList data) { - milestoneComboBox->insertItems(0, data); +void TestRailRunSelectorWindow::updateSectionsComboBoxData(QStringList data) { + sectionsComboBox->insertItems(0, data); } -int TestRailRunSelectorWindow::getMilestoneID() { - return milestoneComboBox->currentIndex(); +int TestRailRunSelectorWindow::getSectionID() { + return 0; + sectionsComboBox->currentIndex(); } \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailRunSelectorWindow.h b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.h index ece70124b9..d6428bb476 100644 --- a/tools/auto-tester/src/ui/TestRailRunSelectorWindow.h +++ b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.h @@ -38,8 +38,8 @@ public: bool userCancelled{ false }; - void updateMilestoneComboBoxData(QStringList data); - int getMilestoneID(); + void updateSectionsComboBoxData(QStringList data); + int getSectionID(); private slots: void on_acceptButton_clicked(); diff --git a/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui index a15c1b6d0c..ad39b5cc64 100644 --- a/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui +++ b/tools/auto-tester/src/ui/TestRailRunSelectorWindow.ui @@ -174,15 +174,15 @@ Accept - + false - 270 + 140 350 - 161 + 311 22 @@ -193,7 +193,7 @@ - 140 + 20 350 121 20 @@ -205,7 +205,7 @@ - TestRail Milestone + TestRail Sections @@ -274,7 +274,7 @@ projectIDLineEdit suiteIDLineEdit acceptButton - milestoneComboBox + sectionsComboBox OKButton cancelButton diff --git a/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.cpp b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.cpp index afef51a321..27d91df1ac 100644 --- a/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.cpp +++ b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.cpp @@ -27,7 +27,7 @@ void TestRailTestCasesSelectorWindow::reset() { projectIDLineEdit->setDisabled(false); OKButton->setDisabled(true); - milestoneComboBox->setDisabled(true); + milestonesComboBox->setDisabled(true); } void TestRailTestCasesSelectorWindow::on_acceptButton_clicked() { @@ -37,7 +37,7 @@ void TestRailTestCasesSelectorWindow::on_acceptButton_clicked() { projectIDLineEdit->setDisabled(true); OKButton->setDisabled(false); - milestoneComboBox->setDisabled(false); + milestonesComboBox->setDisabled(false); close(); } @@ -91,10 +91,10 @@ int TestRailTestCasesSelectorWindow::getSuiteID() { return suiteIDLineEdit->text().toInt(); } -void TestRailTestCasesSelectorWindow::updateMilestoneComboBoxData(QStringList data) { - milestoneComboBox->insertItems(0, data); +void TestRailTestCasesSelectorWindow::updateMilestonesComboBoxData(QStringList data) { + milestonesComboBox->insertItems(0, data); } int TestRailTestCasesSelectorWindow::getMilestoneID() { - return milestoneComboBox->currentIndex(); + return milestonesComboBox->currentIndex(); } \ No newline at end of file diff --git a/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.h b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.h index fb9d741bab..51e3a562ae 100644 --- a/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.h +++ b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.h @@ -38,7 +38,7 @@ public: bool userCancelled{ false }; - void updateMilestoneComboBoxData(QStringList data); + void updateMilestonesComboBoxData(QStringList data); int getMilestoneID(); private slots: diff --git a/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.ui b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.ui index 9233f7a629..2dc43d08f1 100644 --- a/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.ui +++ b/tools/auto-tester/src/ui/TestRailTestCasesSelectorWindow.ui @@ -171,7 +171,7 @@ Accept - + false @@ -271,7 +271,7 @@ projectIDLineEdit suiteIDLineEdit acceptButton - milestoneComboBox + milestonesComboBox OKButton cancelButton From 69660cae813b8ba36709a7247c4208e95cc3f018 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Wed, 1 Aug 2018 17:07:53 -0700 Subject: [PATCH 36/36] Can populate Test Section combo. --- tools/auto-tester/src/TestRailInterface.cpp | 88 ++++++++++++++++++--- tools/auto-tester/src/TestRailInterface.h | 6 ++ 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/tools/auto-tester/src/TestRailInterface.cpp b/tools/auto-tester/src/TestRailInterface.cpp index 9520ee645b..f5fe8cefdb 100644 --- a/tools/auto-tester/src/TestRailInterface.cpp +++ b/tools/auto-tester/src/TestRailInterface.cpp @@ -42,6 +42,24 @@ QString TestRailInterface::getObject(const QString& path) { return path.right(path.length() - path.lastIndexOf("/") - 1); } + +bool TestRailInterface::setPythonCommand() { + if (QProcessEnvironment::systemEnvironment().contains("PYTHON_PATH")) { + QString _pythonPath = QProcessEnvironment::systemEnvironment().value("PYTHON_PATH"); + if (!QFile::exists(_pythonPath + "/" + pythonExe)) { + QMessageBox::critical(0, pythonExe, QString("Python executable not found in ") + _pythonPath); + } + _pythonCommand = _pythonPath + "/" + pythonExe; + return true; + } else { + QMessageBox::critical(0, "PYTHON_PATH not defined", + "Please set PYTHON_PATH to directory containing the Python executable"); + return false; + } + + return false; +} + // Creates the testrail.py script // This is the file linked to from http://docs.gurock.com/testrail-api2/bindings-python void TestRailInterface::createTestRailDotPyScript() { @@ -370,6 +388,61 @@ void TestRailInterface::updateMilestonesComboData(int exitCode, QProcess::ExitSt } void TestRailInterface::updateSectionsComboData(int exitCode, QProcess::ExitStatus exitStatus) { + // Quit if user has previously cancelled + if (_testRailRunSelectorWindow.getUserCancelled()) { + return; + } + + // Check if process completed successfully + if (exitStatus != QProcess::NormalExit) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not get sections from TestRail"); + exit(-1); + } + + // Create map of sections from the file created by the process + _sectionNames.clear(); + + QString filename = _outputDirectory + "/sections.txt"; + if (!QFile::exists(filename)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not find sections.txt in " + _outputDirectory); + exit(-1); + } + + QFile file(filename); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), + "Could not open " + _outputDirectory + "/sections.txt"); + exit(-1); + } + + QTextStream in(&file); + QString line = in.readLine(); + while (!line.isNull()) { + // The section name is all the words except for the last + // The id is the last word + QString section = line.left(line.lastIndexOf(" ")); + QString id = line.right(line.length() - line.lastIndexOf(" ") - 1); + + _sections[section] = id.toInt(); + _sectionNames << section; + + line = in.readLine(); + } + + file.close(); + + // Update the combo + _testRailRunSelectorWindow.updateSectionsComboBoxData(_sectionNames); + + _testRailRunSelectorWindow.exec(); + + if (_testRailRunSelectorWindow.getUserCancelled()) { + return; + } + + ////createAddTestCasesPythonScript(_testDirectory, _userGitHub, _branchGitHub); } void TestRailInterface::getMilestonesFromTestRail() { @@ -420,16 +493,7 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory, _userGitHub = userGitHub; _branchGitHub = branchGitHub; - // First check that Python is available - if (QProcessEnvironment::systemEnvironment().contains("PYTHON_PATH")) { - QString _pythonPath = QProcessEnvironment::systemEnvironment().value("PYTHON_PATH"); - if (!QFile::exists(_pythonPath + "/" + pythonExe)) { - QMessageBox::critical(0, pythonExe, QString("Python executable not found in ") + _pythonPath); - } - _pythonCommand = _pythonPath + "/" + pythonExe; - } else { - QMessageBox::critical(0, "PYTHON_PATH not defined", - "Please set PYTHON_PATH to directory containing the Python executable"); + if (!setPythonCommand()) { return; } @@ -760,6 +824,10 @@ void TestRailInterface::getTestSectionsFromTestRail() { void TestRailInterface::createTestRailRun(const QString& outputDirectory) { _outputDirectory = outputDirectory; + if (!setPythonCommand()) { + return; + } + requestTestRailRunDataFromUser(); createTestRailDotPyScript(); createStackDotPyScript(); diff --git a/tools/auto-tester/src/TestRailInterface.h b/tools/auto-tester/src/TestRailInterface.h index 0c5f11971c..4c2bc7b937 100644 --- a/tools/auto-tester/src/TestRailInterface.h +++ b/tools/auto-tester/src/TestRailInterface.h @@ -80,6 +80,8 @@ public: void createTestRailRun(const QString& outputDirectory); + bool setPythonCommand(); + private: // HighFidelity Interface project ID in TestRail const int INTERFACE_PROJECT_ID{ 24 }; @@ -106,8 +108,12 @@ private: const QString pythonExe{ "python.exe" }; QString _pythonCommand; + std::map _milestones; QStringList _milestoneNames; + + std::map _sections; + QStringList _sectionNames; }; #endif \ No newline at end of file