Merge branch 'exportToTestRail1' of github.com:NissimHadar/hifi into exportToTestRail1

This commit is contained in:
NissimHadar 2018-08-04 09:04:38 -07:00
commit e61a686923
7 changed files with 269 additions and 47 deletions

View file

@ -830,7 +830,7 @@ void Test::createTestRailTestCases() {
QFileDialog::getExistingDirectory(nullptr, "Please select the tests root folder", parent, QFileDialog::ShowDirsOnly);
// If user cancelled then restore previous selection and return
if (_testDirectory == "") {
if (_testDirectory.isNull()) {
_testDirectory = previousSelection;
return;
}
@ -839,7 +839,7 @@ void Test::createTestRailTestCases() {
nullptr, QFileDialog::ShowDirsOnly);
// If user cancelled then return
if (outputDirectory == "") {
if (outputDirectory.isNull()) {
return;
}
@ -855,15 +855,26 @@ void Test::createTestRailTestCases() {
void Test::createTestRailRun() {
QString outputDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store generated files in",
nullptr, QFileDialog::ShowDirsOnly);
if (outputDirectory.isNull()) {
return;
}
_testRailInterface.createTestRailRun(outputDirectory);
}
void Test::updateTestRailRunResult() {
QString testResults = QFileDialog::getOpenFileName(nullptr, "Please select the zipped test results to update from", nullptr,
"Zipped Test Results (*.zip)");
"Zipped Test Results (*.zip)");
if (testResults.isNull()) {
return;
}
QString tempDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select a folder to store temporary files in",
nullptr, QFileDialog::ShowDirsOnly);
if (tempDirectory.isNull()) {
return;
}
_testRailInterface.updateTestRailRunResults(testResults, tempDirectory);
}

View file

@ -41,6 +41,17 @@ TestRailInterface::TestRailInterface() {
_testRailRunSelectorWindow.setSuiteID(INTERFACE_SUITE_ID);
////_testRailRunSelectorWindow.setSuiteID(2);
_testRailResultsSelectorWindow.setURL("https://highfidelity.testrail.net");
////_testRailResultsSelectorWindow.setURL("https://nissimhadar.testrail.io");
_testRailResultsSelectorWindow.setUser("@highfidelity.io");
////_testRailResultsSelectorWindow.setUser("nissim.hadar@gmail.com");
_testRailResultsSelectorWindow.setProjectID(INTERFACE_PROJECT_ID);
////_testRailResultsSelectorWindow.setProjectID(2);
_testRailResultsSelectorWindow.setSuiteID(INTERFACE_SUITE_ID);
////_testRailResultsSelectorWindow.setSuiteID(2);
}
QString TestRailInterface::getObject(const QString& path) {
@ -217,13 +228,13 @@ void TestRailInterface::createStackDotPyScript() {
file.close();
}
void TestRailInterface::requestTestRailTestCasesDataFromUser() {
bool TestRailInterface::requestTestRailTestCasesDataFromUser() {
// Make sure correct fields are enabled before calling
_testRailTestCasesSelectorWindow.reset();
_testRailTestCasesSelectorWindow.exec();
if (_testRailTestCasesSelectorWindow.getUserCancelled()) {
return;
return false;
}
_url = _testRailTestCasesSelectorWindow.getURL() + "/";
@ -232,6 +243,44 @@ void TestRailInterface::requestTestRailTestCasesDataFromUser() {
////_password = "tutKA76";////
_projectID = QString::number(_testRailTestCasesSelectorWindow.getProjectID());
_suiteID = QString::number(_testRailTestCasesSelectorWindow.getSuiteID());
return true;
}
bool TestRailInterface::requestTestRailRunDataFromUser() {
_testRailRunSelectorWindow.reset();
_testRailRunSelectorWindow.exec();
if (_testRailRunSelectorWindow.getUserCancelled()) {
return false;
}
_url = _testRailRunSelectorWindow.getURL() + "/";
_user = _testRailRunSelectorWindow.getUser();
_password = _testRailRunSelectorWindow.getPassword();
////_password = "tutKA76";////
_projectID = QString::number(_testRailRunSelectorWindow.getProjectID());
_suiteID = QString::number(_testRailRunSelectorWindow.getSuiteID());
return true;
}
bool TestRailInterface::requestTestRailResultsDataFromUser() {
_testRailResultsSelectorWindow.reset();
_testRailResultsSelectorWindow.exec();
if (_testRailResultsSelectorWindow.getUserCancelled()) {
return false;
}
_url = _testRailResultsSelectorWindow.getURL() + "/";
_user = _testRailResultsSelectorWindow.getUser();
_password = _testRailResultsSelectorWindow.getPassword();
////_password = "tutKA76";////
_projectID = QString::number(_testRailResultsSelectorWindow.getProjectID());
_suiteID = QString::number(_testRailResultsSelectorWindow.getSuiteID());
return true;
}
bool TestRailInterface::isAValidTestDirectory(const QString& directory) {
@ -398,7 +447,7 @@ void TestRailInterface::addRun() {
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__),
"Could not create 'addRun.py'");
"Could not create " + filename);
exit(-1);
}
@ -462,6 +511,58 @@ void TestRailInterface::addRun() {
process->start(_pythonCommand, parameters);
}
}
void TestRailInterface::updateRunWithResults() {
QString filename = _outputDirectory + "/updateRunWithResults.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 " + filename);
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";
// It is assumed that all the tests that haven't failed have passed
// The failed tests are read, formatted and inserted into a set
// A failure named 'Failure_1--tests.content.entity.material.apply.avatars.00000' is formatted to 'content/entity/material/apply/avatars'
// This is the name of the test in TestRail
stream << "from os import listdir\n";
stream << "failed_tests = set()\n";
stream << "for entry in listdir('" + _outputDirectory + "/" + tempName + "'):\n";
stream << "\tparts = entry.split('--tests.')[1].split('.')\n";
stream << "\tfailed_test = parts[0]\n";
stream << "\tfor i in range(1, len(parts) - 1):\n";
stream << "\t\tfailed_test = failed_test + '/' + parts[i]\n";
stream << "\tfailed_tests.add(failed_test)\n\n";
int runID = _runIDs[_testRailResultsSelectorWindow.getRunID()];
stream << "tests = client.send_get('get_tests/" + QString::number(runID) + "')\n\n";
stream << "for test in tests:\n";
// status_id's: 1 - Passed
// 2 - Blocked
// 3 - Untested
// 4 - Retest
// 5 - Failed
stream << "\tstatus_id = 1\n";
stream << "\tif test['title'] in failed_tests:\n";
stream << "\t\tstatus_id = 5\n";
file.close();
}
void TestRailInterface::updateSectionsComboData(int exitCode, QProcess::ExitStatus exitStatus) {
// Quit if user has previously cancelled
@ -489,7 +590,7 @@ void TestRailInterface::updateSectionsComboData(int exitCode, QProcess::ExitStat
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");
"Could not open " + filename);
exit(-1);
}
@ -523,6 +624,66 @@ void TestRailInterface::updateSectionsComboData(int exitCode, QProcess::ExitStat
addRun();
}
void TestRailInterface::updateRunsComboData(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 runs from TestRail");
exit(-1);
}
// Create map of sections from the file created by the process
_runNames.clear();
QString filename = _outputDirectory + "/runs.txt";
if (!QFile::exists(filename)) {
QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__),
"Could not find runs.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 " + filename);
exit(-1);
}
QTextStream in(&file);
QString line = in.readLine();
while (!line.isNull()) {
// The run 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);
_runIDs.push_back(id.toInt());
_runNames << section;
line = in.readLine();
}
file.close();
// Update the combo
_testRailResultsSelectorWindow.updateRunsComboBoxData(_runNames);
_testRailResultsSelectorWindow.exec();
if (_testRailResultsSelectorWindow.getUserCancelled()) {
return;
}
// The test cases are now read from TestRail
// When this is complete, the Run can be updated
updateRunWithResults();
}
void TestRailInterface::getReleasesFromTestRail() {
QString filename = _outputDirectory + "/getReleases.py";
if (QFile::exists(filename)) {
@ -587,7 +748,10 @@ void TestRailInterface::createTestSuitePython(const QString& testDirectory,
return;
}
requestTestRailTestCasesDataFromUser();
if (!requestTestRailTestCasesDataFromUser()) {
return;
}
createTestRailDotPyScript();
createStackDotPyScript();
@ -854,22 +1018,6 @@ 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();
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::getTestSectionsFromTestRail() {
QString filename = _outputDirectory + "/getSections.py";
if (QFile::exists(filename)) {
@ -909,6 +1057,45 @@ void TestRailInterface::getTestSectionsFromTestRail() {
process->start(_pythonCommand, parameters);
}
void TestRailInterface::getRunsFromTestRail() {
QString filename = _outputDirectory + "/getRuns.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 " + filename);
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 runs
stream << "runs = client.send_get('get_runs/" + _projectID + "')\n\n";
stream << "file = open('" + _outputDirectory + "/runs.txt', 'w')\n\n";
stream << "for run in runs:\n";
stream << "\tfile.write(run['name'] + ' ' + str(run['id']) + '\\n')\n\n";
stream << "file.close()\n";
file.close();
QProcess* process = new QProcess();
connect(process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this,
[=](int exitCode, QProcess::ExitStatus exitStatus) { updateRunsComboData(exitCode, exitStatus); });
QStringList parameters = QStringList() << filename;
process->start(_pythonCommand, parameters);
}
void TestRailInterface::createTestRailRun(const QString& outputDirectory) {
_outputDirectory = outputDirectory;
@ -916,7 +1103,10 @@ void TestRailInterface::createTestRailRun(const QString& outputDirectory) {
return;
}
requestTestRailRunDataFromUser();
if (!requestTestRailRunDataFromUser()) {
return;
}
createTestRailDotPyScript();
createStackDotPyScript();
@ -924,8 +1114,20 @@ void TestRailInterface::createTestRailRun(const QString& outputDirectory) {
getTestSectionsFromTestRail();
}
void TestRailInterface::updateTestRailRunResults(const QString& testResults, const QString& tempDirectory) {
_outputDirectory = tempDirectory;
if (!setPythonCommand()) {
return;
}
if (!requestTestRailResultsDataFromUser()) {
return;
}
// TestRail will be updated after the process initiated by getTestRunFromTestRail has completed
getRunsFromTestRail();
// Extract test failures from zipped folder
QString tempSubDirectory = tempDirectory + "/" + tempName;
QDir dir = tempSubDirectory;

View file

@ -15,6 +15,7 @@
#include "ui/TestRailTestCasesSelectorWindow.h"
#include "ui/TestRailRunSelectorWindow.h"
#include "ui/TestRailResultsSelectorWindow.h"
#include <QDirIterator>
#include <QtXml/QDomDocument>
@ -55,12 +56,14 @@ public:
void getReleasesFromTestRail();
void getTestSectionsFromTestRail();
void getRunsFromTestRail();
void createTestRailDotPyScript();
void createStackDotPyScript();
void requestTestRailTestCasesDataFromUser();
void requestTestRailRunDataFromUser();
bool requestTestRailTestCasesDataFromUser();
bool requestTestRailRunDataFromUser();
bool requestTestRailResultsDataFromUser();
void createAddTestCasesPythonScript(const QString& testDirectory,
const QString& userGitHub,
@ -77,11 +80,13 @@ public:
void updateReleasesComboData(int exitCode, QProcess::ExitStatus exitStatus);
void updateSectionsComboData(int exitCode, QProcess::ExitStatus exitStatus);
void updateRunsComboData(int exitCode, QProcess::ExitStatus exitStatus);
void createTestRailRun(const QString& outputDirectory);
void updateTestRailRunResults(const QString& testResults, const QString& tempDirectory);
void addRun();
void updateRunWithResults();
bool setPythonCommand();
@ -97,6 +102,7 @@ private:
BusyWindow _busyWindow;
TestRailTestCasesSelectorWindow _testRailTestCasesSelectorWindow;
TestRailRunSelectorWindow _testRailRunSelectorWindow;
TestRailResultsSelectorWindow _testRailResultsSelectorWindow;
QString _url;
QString _user;
@ -117,6 +123,9 @@ private:
QStringList _sectionNames;
std::vector<int> _sectionIDs;
QStringList _runNames;
std::vector<int> _runIDs;
QString tempName{ "fgadhcUDHSFaidsfh3478JJJFSDFIUSOEIrf" };
};

View file

@ -28,8 +28,8 @@ void TestRailResultsSelectorWindow::reset() {
OKButton->setDisabled(true);
releasesLabel->setDisabled(true);
releasesComboBox->setDisabled(true);
runsLabel->setDisabled(true);
runsComboBox->setDisabled(true);
}
void TestRailResultsSelectorWindow::on_acceptButton_clicked() {
@ -40,8 +40,8 @@ void TestRailResultsSelectorWindow::on_acceptButton_clicked() {
OKButton->setDisabled(false);
releasesLabel->setDisabled(false);
releasesComboBox->setDisabled(false);
runsLabel->setDisabled(false);
runsComboBox->setDisabled(false);
close();
}
@ -95,10 +95,10 @@ int TestRailResultsSelectorWindow::getSuiteID() {
return suiteIDLineEdit->text().toInt();
}
void TestRailResultsSelectorWindow::updateReleasesComboBoxData(QStringList data) {
releasesComboBox->insertItems(0, data);
void TestRailResultsSelectorWindow::updateRunsComboBoxData(QStringList data) {
runsComboBox->insertItems(0, data);
}
int TestRailResultsSelectorWindow::getReleaseID() {
return releasesComboBox->currentIndex();
int TestRailResultsSelectorWindow::getRunID() {
return runsComboBox->currentIndex();
}

View file

@ -38,8 +38,8 @@ public:
bool userCancelled{ false };
void updateReleasesComboBoxData(QStringList data);
int getReleaseID();
void updateRunsComboBoxData(QStringList data);
int getRunID();
private slots:
void on_acceptButton_clicked();

View file

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>489</width>
<width>533</width>
<height>474</height>
</rect>
</property>
@ -171,20 +171,20 @@
<string>Accept</string>
</property>
</widget>
<widget class="QComboBox" name="releasesComboBox">
<widget class="QComboBox" name="runsComboBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>270</x>
<x>160</x>
<y>350</y>
<width>161</width>
<width>271</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="releasesLabel">
<widget class="QLabel" name="runsLabel">
<property name="enabled">
<bool>true</bool>
</property>
@ -192,7 +192,7 @@
<rect>
<x>80</x>
<y>350</y>
<width>181</width>
<width>71</width>
<height>20</height>
</rect>
</property>
@ -202,7 +202,7 @@
</font>
</property>
<property name="text">
<string>TestRail Added for release</string>
<string>TestRail Run</string>
</property>
</widget>
<widget class="QLineEdit" name="urlLineEdit">
@ -271,7 +271,7 @@
<tabstop>projectIDLineEdit</tabstop>
<tabstop>suiteIDLineEdit</tabstop>
<tabstop>acceptButton</tabstop>
<tabstop>releasesComboBox</tabstop>
<tabstop>runsComboBox</tabstop>
<tabstop>OKButton</tabstop>
<tabstop>cancelButton</tabstop>
</tabstops>

View file

@ -202,7 +202,7 @@
</font>
</property>
<property name="text">
<string>TestRail Added for release</string>
<string>TestRail Added for Release</string>
</property>
</widget>
<widget class="QLineEdit" name="urlLineEdit">