summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--non-puppet/qtmetrics2/index.php118
-rw-r--r--non-puppet/qtmetrics2/project_search.php64
-rw-r--r--non-puppet/qtmetrics2/scripts/project_autocomplete.js84
-rw-r--r--non-puppet/qtmetrics2/src/ConfRun.php121
-rw-r--r--non-puppet/qtmetrics2/src/Database.php295
-rw-r--r--non-puppet/qtmetrics2/src/Factory.php63
-rw-r--r--non-puppet/qtmetrics2/src/TestsetRun.php9
-rw-r--r--non-puppet/qtmetrics2/src/test/DatabaseTest.php181
-rw-r--r--non-puppet/qtmetrics2/src/test/FactoryTest.php70
-rw-r--r--non-puppet/qtmetrics2/templates/about.html6
-rw-r--r--non-puppet/qtmetrics2/templates/build_project.html342
-rw-r--r--non-puppet/qtmetrics2/templates/home.html103
-rw-r--r--non-puppet/qtmetrics2/templates/overview.html237
-rw-r--r--non-puppet/qtmetrics2/templates/testset.html464
-rw-r--r--non-puppet/qtmetrics2/templates/testset_project.html346
15 files changed, 2169 insertions, 334 deletions
diff --git a/non-puppet/qtmetrics2/index.php b/non-puppet/qtmetrics2/index.php
index 746ffbe..811c126 100644
--- a/non-puppet/qtmetrics2/index.php
+++ b/non-puppet/qtmetrics2/index.php
@@ -34,8 +34,8 @@
/**
* Qt Metrics API
- * @version 0.5
- * @since 25-06-2015
+ * @version 0.7
+ * @since 30-06-2015
* @author Juha Sippola
*/
@@ -67,16 +67,106 @@ $app->get('/', function() use($app)
'platformRoute' => Slim\Slim::getInstance()->urlFor('root') . 'platform',
'testRoute' => Slim\Slim::getInstance()->urlFor('root') . 'test',
'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
- 'states' => Factory::db()->getStates(),
+ 'masterProject' => $ini['master_build_project'],
+ 'masterState' => $ini['master_build_state'],
'branches' => Factory::db()->getBranches(),
- 'projects' => Factory::createProjects(
- $ini['master_build_project'],
- $ini['master_build_state']), // managed as objects
'platforms' => Factory::db()->getTargetPlatforms()
));
})->name('root');
/**
+ * UI route: /overview (GET)
+ */
+
+$app->get('/overview', function() use($app)
+{
+ $ini = Factory::conf();
+ $breadcrumb = array(
+ array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root'))
+ );
+ $app->render('overview.html', array(
+ 'root' => Slim\Slim::getInstance()->urlFor('root'),
+ 'breadcrumb' => $breadcrumb,
+ 'buildProjectRoute' => Slim\Slim::getInstance()->urlFor('root') . 'buildproject',
+ 'testsetProjectRoute' => Slim\Slim::getInstance()->urlFor('root') . 'testsetproject',
+ 'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
+ 'masterProject' => $ini['master_build_project'],
+ 'masterState' => $ini['master_build_state'],
+ 'latestProjectRuns' => Factory::db()->getLatestProjectBranchBuildResults(
+ $ini['master_build_project'],
+ $ini['master_build_state']),
+ 'latestTestsetRuns' => Factory::db()->getLatestProjectBranchTestsetResults(
+ $ini['master_build_project'],
+ $ini['master_build_state'])
+ ));
+});
+
+/**
+ * UI route: /buildproject (GET)
+ */
+
+$app->get('/buildproject/:project', function($project) use($app)
+{
+ $project = strip_tags($project);
+ $ini = Factory::conf();
+ $breadcrumb = array(
+ array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root'))
+ );
+ $app->render('build_project.html', array(
+ 'root' => Slim\Slim::getInstance()->urlFor('root'),
+ 'breadcrumb' => $breadcrumb,
+ 'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
+ 'masterProject' => $ini['master_build_project'],
+ 'masterState' => $ini['master_build_state'],
+ 'latestProjectRuns' => Factory::db()->getLatestProjectBranchBuildResults(
+ $project,
+ $ini['master_build_state']),
+ 'projectBuilds' => Factory::db()->getProjectBuildsByBranch(
+ $ini['master_build_project'],
+ $ini['master_build_state']),
+ 'project' => Factory::createProject(
+ $project,
+ $ini['master_build_project'],
+ $ini['master_build_state']), // managed as object
+ 'confRuns' => Factory::createConfRuns(
+ $ini['master_build_project'],
+ $ini['master_build_state']) // managed as objects
+ ));
+});
+
+/**
+ * UI route: /testsetproject (GET)
+ */
+
+$app->get('/testsetproject/:project', function($project) use($app)
+{
+ $project = strip_tags($project);
+ $ini = Factory::conf();
+ $breadcrumb = array(
+ array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root'))
+ );
+ $app->render('testset_project.html', array(
+ 'root' => Slim\Slim::getInstance()->urlFor('root'),
+ 'breadcrumb' => $breadcrumb,
+ 'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
+ 'masterProject' => $ini['master_build_project'],
+ 'masterState' => $ini['master_build_state'],
+ 'project' => $project,
+ 'latestTestsetRuns' => Factory::db()->getLatestTestsetProjectBranchTestsetResults(
+ $project,
+ $ini['master_build_project'],
+ $ini['master_build_state']),
+ 'projectBuilds' => Factory::db()->getProjectBuildsByBranch(
+ $ini['master_build_project'],
+ $ini['master_build_state']),
+ 'confBuilds' => Factory::db()->getTestsetProjectResultsByBranchConf(
+ $project,
+ $ini['master_build_project'],
+ $ini['master_build_state'])
+ ));
+});
+
+/**
* UI route: /test/top (GET)
*/
@@ -183,6 +273,22 @@ $app->run();
/**
+ * Handle the project name input selection on home page and redirect to testset project page
+ */
+
+if (isset($_POST["projectInputSubmit"])) {
+ if (empty($_POST["projectInputValue"])) {
+ header('Location: ' . Slim\Slim::getInstance()->urlFor('root'));
+ exit();
+ }
+ if (isset($_POST["projectInputValue"])) {
+ $project = htmlspecialchars($_POST['projectInputValue']);
+ header('Location: ' . Slim\Slim::getInstance()->urlFor('root') . 'testsetproject/' . $project);
+ exit();
+ }
+}
+
+/**
* Handle the testset name input selection on home page and redirect to testset page
*/
diff --git a/non-puppet/qtmetrics2/project_search.php b/non-puppet/qtmetrics2/project_search.php
new file mode 100644
index 0000000..c43c431
--- /dev/null
+++ b/non-puppet/qtmetrics2/project_search.php
@@ -0,0 +1,64 @@
+<?php
+#############################################################################
+##
+## Copyright (C) 2015 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Quality Assurance module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL21$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see http://www.qt.io/terms-conditions. For further
+## information use the contact form at http://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 or version 3 as published by the Free
+## Software Foundation and appearing in the file LICENSE.LGPLv21 and
+## LICENSE.LGPLv3 included in the packaging of this file. Please review the
+## following information to ensure the GNU Lesser General Public License
+## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## As a special exception, The Qt Company gives you certain additional
+## rights. These rights are described in The Qt Company LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+/**
+ * Project autocomplete search
+ * @version 0.1
+ * @since 30-06-2015
+ * @author Juha Sippola
+ */
+
+header('Content-Type: application/json');
+require 'src/Factory.php';
+
+// Get the filter and make database search
+if (isset($_GET['term'])) {
+ $list = array();
+ $rows = Factory::getProjectsFiltered($_GET['term']);
+ foreach ($rows as $row) {
+ foreach ($row as $key => $value) {
+ if ($key === 'name')
+ $name = $value;
+ }
+ $list[] = $name;
+ }
+ // Return list as json string
+ echo json_encode($list);
+
+// Return empty string if filter not set
+} else {
+ echo json_encode([]);
+}
+
+?>
diff --git a/non-puppet/qtmetrics2/scripts/project_autocomplete.js b/non-puppet/qtmetrics2/scripts/project_autocomplete.js
new file mode 100644
index 0000000..6970c8e
--- /dev/null
+++ b/non-puppet/qtmetrics2/scripts/project_autocomplete.js
@@ -0,0 +1,84 @@
+/*
+#############################################################################
+##
+## Copyright (C) 2015 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Quality Assurance module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL21$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see http://www.qt.io/terms-conditions. For further
+## information use the contact form at http://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 or version 3 as published by the Free
+## Software Foundation and appearing in the file LICENSE.LGPLv21 and
+## LICENSE.LGPLv3 included in the packaging of this file. Please review the
+## following information to ensure the GNU Lesser General Public License
+## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## As a special exception, The Qt Company gives you certain additional
+## rights. These rights are described in The Qt Company LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+/**
+ * Project autocomplete
+ * @version 0.1
+ * @since 30-06-2015
+ * @author Juha Sippola
+ */
+
+$(function() {
+ var cache = {};
+ $( "#projectInput" ).autocomplete({
+ minLength: 2,
+
+ // get the filtered list (cached)
+ source: function( request, response ) {
+ var term = request.term;
+ if ( term in cache ) {
+ response( cache[ term ] );
+ return;
+ }
+ $.getJSON( "project_search.php", request, function( data, status, xhr ) {
+ cache[ term ] = data;
+ response( data );
+ });
+ },
+
+ // detect the case without any matches
+ response: function (event, ui) {
+ if (ui.content.length === 0) {
+ ui.content.push({
+ 'label': '(no match)',
+ 'value': ''
+ });
+ }
+ }
+ })
+
+ // fill the list
+ .data("ui-autocomplete")._renderItem = function (ul, item) {
+ if (item.value === '') {
+ // 'no match' case
+ return $('<li class="ui-state-disabled">'+item.label+'</li>')
+ .appendTo(ul);
+ } else {
+ // list of matches
+ return $("<li>")
+ .append("<a>" + item.label + "</a>")
+ .appendTo(ul);
+ }
+ };
+});
diff --git a/non-puppet/qtmetrics2/src/ConfRun.php b/non-puppet/qtmetrics2/src/ConfRun.php
new file mode 100644
index 0000000..80089f4
--- /dev/null
+++ b/non-puppet/qtmetrics2/src/ConfRun.php
@@ -0,0 +1,121 @@
+<?php
+#############################################################################
+##
+## Copyright (C) 2015 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Quality Assurance module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL21$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see http://www.qt.io/terms-conditions. For further
+## information use the contact form at http://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 or version 3 as published by the Free
+## Software Foundation and appearing in the file LICENSE.LGPLv21 and
+## LICENSE.LGPLv3 included in the packaging of this file. Please review the
+## following information to ensure the GNU Lesser General Public License
+## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## As a special exception, The Qt Company gives you certain additional
+## rights. These rights are described in The Qt Company LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+/**
+ * ConfRun class
+ * @version 0.1
+ * @since 30-06-2015
+ * @author Juha Sippola
+ */
+
+class ConfRun extends ProjectRun {
+
+ /**
+ * Conf build results (these must follow the enumeration in the database)
+ */
+ const RESULT_NOT_SET = NULL;
+ const RESULT_EMPTY = "";
+ const RESULT_SUCCESS = "SUCCESS";
+ const RESULT_FAILURE = "FAILURE";
+ const RESULT_ABORTED = "ABORTED";
+ const RESULT_UNDEF = "undef";
+
+ /**
+ * Conf name.
+ * @var string
+ */
+ private $name;
+
+ /**
+ * Forcesuccess flag (true = forcesuccess on).
+ * @var bool
+ */
+ private $forcesuccess;
+
+ /**
+ * Insignificance flag (true = insignificant).
+ * @var bool
+ */
+ private $insignificant;
+
+ /**
+ * ConfRun constructor.
+ * @param string $name
+ * @param string $projectName
+ * @param string $branchName
+ * @param string $stateName
+ * @param int $buildKey
+ * @param string $result
+ * @param bool $forcesuccess (true = forcesuccess on)
+ * @param bool $insignificant (true = insignificant)
+ * @param int $timestamp
+ * @param int $duration
+ */
+ public function __construct($name, $projectName, $branchName, $stateName, $buildKey, $result, $forcesuccess, $insignificant, $timestamp, $duration) {
+ parent::__construct($projectName, $branchName, $stateName, $buildKey, $result, $timestamp, $duration);
+ $this->name = $name;
+ $this->forcesuccess = $forcesuccess;
+ $this->insignificant = $insignificant;
+ }
+
+ /**
+ * Get name of the conf.
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Get forcesuccess flag.
+ * @return bool (true = forcesuccess on)
+ */
+ public function getForcesuccess()
+ {
+ return $this->forcesuccess;
+ }
+
+ /**
+ * Get insignificance flag.
+ * @return bool (true = insignificant)
+ */
+ public function getInsignificant()
+ {
+ return $this->insignificant;
+ }
+
+}
+
+?>
diff --git a/non-puppet/qtmetrics2/src/Database.php b/non-puppet/qtmetrics2/src/Database.php
index efc87c3..5ebf6e1 100644
--- a/non-puppet/qtmetrics2/src/Database.php
+++ b/non-puppet/qtmetrics2/src/Database.php
@@ -34,8 +34,8 @@
/**
* Database class
- * @version 0.4
- * @since 22-06-2015
+ * @version 0.6
+ * @since 30-06-2015
* @author Juha Sippola
*/
@@ -106,6 +106,31 @@ class Database {
}
/**
+ * Get list of projects matching the filter string.
+ * @param string $filter
+ * @return array (string name)
+ */
+ public function getProjectsFiltered($filter)
+ {
+ $result = array();
+ $query = $this->db->prepare("
+ SELECT name
+ FROM project
+ WHERE name LIKE ?
+ ORDER BY name;
+ ");
+ $query->execute(array(
+ '%' . $filter . '%'
+ ));
+ while($row = $query->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = array(
+ 'name' => $row['name']
+ );
+ }
+ return $result;
+ }
+
+ /**
* Get list of testsets matching the filter string.
* @param string $filter
* @return array (string name)
@@ -185,12 +210,12 @@ class Database {
/**
* Get the latest build key for given project, branch and state
- * @param string $project
- * @param string $branch
- * @param string $state
+ * @param string $runProject
+ * @param string $runBranch
+ * @param string $runState
* @return string
*/
- public function getLatestProjectBranchBuildKey($project, $branch, $state)
+ public function getLatestProjectBranchBuildKey($runProject, $runBranch, $runState)
{
$result = array();
$query = $this->db->prepare("
@@ -204,9 +229,9 @@ class Database {
LIMIT 1
");
$query->execute(array(
- $project,
- $branch,
- $state
+ $runProject,
+ $runBranch,
+ $runState
));
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
$result= $row['latest_build'];
@@ -216,17 +241,17 @@ class Database {
/**
* Get the latest build keys by branch for given project and state
- * @param string $project
- * @param string $state
+ * @param string $runProject
+ * @param string $runState
* @return array (string name, string key)
*/
- public function getLatestProjectBranchBuildKeys($project, $state)
+ public function getLatestProjectBranchBuildKeys($runProject, $runState)
{
$result = array();
$branches = self::getBranches();
foreach ($branches as $branch) {
- $key = self::getLatestProjectBranchBuildKey($project, $branch['name'], $state);
+ $key = self::getLatestProjectBranchBuildKey($runProject, $branch['name'], $runState);
if ($key) {
$result[] = array(
'name' => $branch['name'],
@@ -239,17 +264,22 @@ class Database {
/**
* Get the latest build result by branch for given project and state
- * @param string $project
- * @param string $state
- * @return array (string name, string result)
+ * @param string $runProject
+ * @param string $runState
+ * @return array (string name, string result, string buildKey, string timestamp, string duration)
*/
- public function getLatestProjectBranchBuildResults($project, $state)
+ public function getLatestProjectBranchBuildResults($runProject, $runState)
{
$result = array();
- $builds = self::getLatestProjectBranchBuildKeys($project, $state);
+ $builds = self::getLatestProjectBranchBuildKeys($runProject, $runState);
foreach ($builds as $build) {
$query = $this->db->prepare("
- SELECT branch.name, project_run.result
+ SELECT
+ branch.name,
+ project_run.result,
+ project_run.build_key,
+ project_run.timestamp,
+ project_run.duration
FROM project_run
INNER JOIN branch ON branch_id = branch.id
WHERE
@@ -259,15 +289,128 @@ class Database {
build_key = ?;
");
$query->execute(array(
- $project,
- $state,
+ $runProject,
+ $runState,
$build['name'],
$build['key']
));
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
$result[] = array(
'name' => $row['name'],
- 'result' => $row['result']
+ 'result' => $row['result'],
+ 'buildKey' => $row['build_key'],
+ 'timestamp' => $row['timestamp'],
+ 'duration' => $row['duration']
+ );
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Get the latest testset result by branch for given project and state
+ * @param string $runProject
+ * @param string $runState
+ * @return array (string project, string branch, string buildKey, string timestamp, int passed, int failed)
+ */
+ public function getLatestProjectBranchTestsetResults($runProject, $runState)
+ {
+ $result = array();
+ $builds = self::getLatestProjectBranchBuildKeys($runProject, $runState);
+ foreach ($builds as $build) {
+ $query = $this->db->prepare("
+ SELECT
+ project.name AS project,
+ branch.name AS branch,
+ project_run.build_key,
+ project_run.timestamp,
+ COUNT(CASE WHEN testset_run.result LIKE '%passed' THEN testset_run.result END) AS passed,
+ COUNT(CASE WHEN testset_run.result LIKE '%failed' THEN testset_run.result END) AS failed
+ FROM testset_run
+ INNER JOIN testset ON testset_run.testset_id = testset.id
+ INNER JOIN project ON testset.project_id = project.id
+ INNER JOIN conf_run ON testset_run.conf_run_id = conf_run.id
+ INNER JOIN conf ON conf_run.conf_id = conf.id
+ INNER JOIN project_run ON conf_run.project_run_id = project_run.id
+ INNER JOIN branch ON project_run.branch_id = branch.id
+ WHERE
+ project_run.project_id = (SELECT id FROM project WHERE name = ?) AND
+ project_run.state_id = (SELECT id FROM state WHERE name = ?) AND
+ project_run.branch_id = (SELECT id from branch WHERE name = ?) AND
+ project_run.build_key = ?
+ GROUP BY project.name;
+ ");
+ $query->execute(array(
+ $runProject,
+ $runState,
+ $build['name'],
+ $build['key']
+ ));
+ while($row = $query->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = array(
+ 'project' => $row['project'],
+ 'branch' => $row['branch'],
+ 'buildKey' => $row['build_key'],
+ 'timestamp' => $row['timestamp'],
+ 'passed' => $row['passed'],
+ 'failed' => $row['failed']
+ );
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * Get the latest testset result by branch for given project and state, for selected testset project.
+ * Similar to getLatestProjectBranchTestsetResults but listing only the selected testset project.
+ * @param string $testsetProject
+ * @param string $runProject
+ * @param string $runState
+ * @return array (string project, string branch, string buildKey, string timestamp, int passed, int failed)
+ */
+ public function getLatestTestsetProjectBranchTestsetResults($testsetProject, $runProject, $runState)
+ {
+ $result = array();
+ $builds = self::getLatestProjectBranchBuildKeys($runProject, $runState);
+ foreach ($builds as $build) {
+ $query = $this->db->prepare("
+ SELECT
+ project.name AS project,
+ branch.name AS branch,
+ project_run.build_key,
+ project_run.timestamp,
+ COUNT(CASE WHEN testset_run.result LIKE '%passed' THEN testset_run.result END) AS passed,
+ COUNT(CASE WHEN testset_run.result LIKE '%failed' THEN testset_run.result END) AS failed
+ FROM testset_run
+ INNER JOIN testset ON testset_run.testset_id = testset.id
+ INNER JOIN project ON testset.project_id = project.id
+ INNER JOIN conf_run ON testset_run.conf_run_id = conf_run.id
+ INNER JOIN conf ON conf_run.conf_id = conf.id
+ INNER JOIN project_run ON conf_run.project_run_id = project_run.id
+ INNER JOIN branch ON project_run.branch_id = branch.id
+ WHERE
+ project.name = ? AND
+ project_run.project_id = (SELECT id FROM project WHERE name = ?) AND
+ project_run.state_id = (SELECT id FROM state WHERE name = ?) AND
+ project_run.branch_id = (SELECT id from branch WHERE name = ?) AND
+ project_run.build_key = ?
+ GROUP BY project.name;
+ ");
+ $query->execute(array(
+ $testsetProject,
+ $runProject,
+ $runState,
+ $build['name'],
+ $build['key']
+ ));
+ while($row = $query->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = array(
+ 'project' => $row['project'],
+ 'branch' => $row['branch'],
+ 'buildKey' => $row['build_key'],
+ 'timestamp' => $row['timestamp'],
+ 'passed' => $row['passed'],
+ 'failed' => $row['failed']
);
}
}
@@ -288,7 +431,10 @@ class Database {
$builds = self::getLatestProjectBranchBuildKeys($runProject, $runState);
foreach ($builds as $build) {
$query = $this->db->prepare("
- SELECT conf.name AS conf, branch.name AS branch, testset_run.result
+ SELECT
+ conf.name AS conf,
+ branch.name AS branch,
+ testset_run.result
FROM testset_run
INNER JOIN conf_run ON testset_run.conf_run_id = conf_run.id
INNER JOIN conf ON conf_run.conf_id = conf.id
@@ -503,7 +649,7 @@ class Database {
}
/**
- * Get project build keys and timestamps by branch
+ * Get project run data by branch
* @param string $runProject
* @param string $runState
* @return array (string branch, string build_key, string timestamp)
@@ -538,12 +684,59 @@ class Database {
}
/**
+ * Get conf run data by branch
+ * @param string $runProject
+ * @param string $runState
+ * @return array (string branch, string conf, string build_key, bool forcesuccess, bool insignificant, string result, string timestamp, string duration)
+ */
+ public function getConfBuildsByBranch($runProject, $runState)
+ {
+ $result = array();
+ $query = $this->db->prepare("
+ SELECT
+ branch.name AS branch,
+ conf.name AS conf,
+ project_run.build_key,
+ conf_run.forcesuccess,
+ conf_run.insignificant,
+ conf_run.result,
+ conf_run.timestamp,
+ conf_run.duration
+ FROM conf_run
+ INNER JOIN conf ON conf_run.conf_id = conf.id
+ INNER JOIN project_run ON conf_run.project_run_id = project_run.id
+ INNER JOIN branch ON project_run.branch_id = branch.id
+ WHERE
+ project_run.project_id = (SELECT id FROM project WHERE name = ?) AND
+ project_run.state_id = (SELECT id FROM state WHERE name = ?)
+ ORDER BY branch.name, conf, project_run.timestamp DESC;
+ ");
+ $query->execute(array(
+ $runProject,
+ $runState
+ ));
+ while($row = $query->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = array(
+ 'branch' => $row['branch'],
+ 'conf' => $row['conf'],
+ 'buildKey' => $row['build_key'],
+ 'forcesuccess' => $row['forcesuccess'],
+ 'insignificant' => $row['insignificant'],
+ 'result' => $row['result'],
+ 'timestamp' => $row['timestamp'],
+ 'duration' => $row['duration']
+ );
+ }
+ return $result;
+ }
+
+ /**
* Get run results for a testset in specified builds by branch and configuration
* @param string $testset
* @param $testsetProject
* @param string $runProject
* @param string $runState
- * @return array (string branch, string conf, string build_key, string result)
+ * @return array (string branch, string conf, string build_key, string result, string timestamp, string duration, int run)
*/
public function getTestsetResultsByBranchConf($testset, $testsetProject, $runProject, $runState)
{
@@ -592,6 +785,58 @@ class Database {
}
/**
+ * Get result counts for a testset project in specified builds by branch and configuration
+ * @param $testsetProject
+ * @param string $runProject
+ * @param string $runState
+ * @return array (string branch, string conf, string build_key, int passed, int ipassed, int failed, int ifailed)
+ */
+ public function getTestsetProjectResultsByBranchConf($testsetProject, $runProject, $runState)
+ {
+ $result = array();
+ $query = $this->db->prepare("
+ SELECT
+ branch.name AS branch,
+ conf.name AS conf,
+ project_run.build_key,
+ COUNT(CASE WHEN testset_run.result = 'passed' THEN testset_run.result END) AS passed,
+ COUNT(CASE WHEN testset_run.result = 'ipassed' THEN testset_run.result END) AS ipassed,
+ COUNT(CASE WHEN testset_run.result = 'failed' THEN testset_run.result END) AS failed,
+ COUNT(CASE WHEN testset_run.result = 'ifailed' THEN testset_run.result END) AS ifailed
+ FROM testset_run
+ INNER JOIN testset ON testset_run.testset_id = testset.id
+ INNER JOIN project ON testset.project_id = project.id
+ INNER JOIN conf_run ON testset_run.conf_run_id = conf_run.id
+ INNER JOIN conf ON conf_run.conf_id = conf.id
+ INNER JOIN project_run ON conf_run.project_run_id = project_run.id
+ INNER JOIN branch ON project_run.branch_id = branch.id
+ WHERE
+ project.name = ? AND
+ project_run.project_id = (SELECT id FROM project WHERE name = ?) AND
+ project_run.state_id = (SELECT id FROM state WHERE name = ?)
+ GROUP BY branch.name, project_run.build_key, conf.name
+ ORDER BY branch.name, conf.name, project_run.build_key DESC;
+ ");
+ $query->execute(array(
+ $testsetProject,
+ $runProject,
+ $runState
+ ));
+ while($row = $query->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = array(
+ 'branch' => $row['branch'],
+ 'conf' => $row['conf'],
+ 'buildKey' => $row['build_key'],
+ 'passed' => $row['passed'],
+ 'ipassed' => $row['ipassed'],
+ 'failed' => $row['failed'],
+ 'ifailed' => $row['ifailed']
+ );
+ }
+ return $result;
+ }
+
+ /**
* Get the timestamp when database last refreshed
* @return string (timestamp)
*/
diff --git a/non-puppet/qtmetrics2/src/Factory.php b/non-puppet/qtmetrics2/src/Factory.php
index 0870f8c..f8e0378 100644
--- a/non-puppet/qtmetrics2/src/Factory.php
+++ b/non-puppet/qtmetrics2/src/Factory.php
@@ -34,14 +34,15 @@
/**
* Factory class
- * @version 0.3
- * @since 23-06-2015
+ * @version 0.4
+ * @since 30-06-2015
* @author Juha Sippola
*/
require_once 'Database.php';
require_once 'Project.php';
require_once 'ProjectRun.php';
+require_once 'ConfRun.php';
require_once 'Testset.php';
require_once 'TestsetRun.php';
@@ -125,6 +126,17 @@ class Factory {
}
/**
+ * Get list of projects matching the filter string.
+ * @param string $filter
+ * @return array (string name)
+ */
+ public static function getProjectsFiltered($filter)
+ {
+ $result = Factory::db()->getProjectsFiltered($filter);
+ return $result;
+ }
+
+ /**
* Get list of testsets matching the filter string.
* @param string $filter
* @return array (string name)
@@ -136,21 +148,17 @@ class Factory {
}
/**
- * Create Project objects for those in database
+ * Create Project object for that in database
+ * @param string $project
* @param string $runProject
* @param string $runState
- * @return array Project objects
+ * @return array Project object
*/
- public static function createProjects($runProject, $runState)
+ public static function createProject($project, $runProject, $runState)
{
- $objects = array();
- $dbEntries = self::db()->getProjects();
- foreach($dbEntries as $entry) {
- $obj = new Project($entry['name']);
- $obj->setStatus($runProject, $runState);
- $objects[] = $obj;
- }
- return $objects;
+ $obj = new Project($project);
+ $obj->setStatus($runProject, $runState);
+ return $obj;
}
/**
@@ -226,6 +234,35 @@ class Factory {
return $obj;
}
+/* NEW */
+ /**
+ * Create ConfRun objects for those in database
+ * @param string $runProject
+ * @param string $runState
+ * @return array ConfRun objects
+ */
+ public static function createConfRuns($runProject, $runState)
+ {
+ $objects = array();
+ $dbEntries = self::db()->getConfBuildsByBranch($runProject, $runState);
+ foreach($dbEntries as $entry) {
+ $obj = new ConfRun(
+ $entry['conf'],
+ $runProject,
+ $entry['branch'],
+ $runState,
+ $entry['buildKey'],
+ $entry['result'],
+ $entry['forcesuccess'],
+ $entry['insignificant'],
+ $entry['timestamp'],
+ $entry['duration']
+ );
+ $objects[] = $obj;
+ }
+ return $objects;
+ }
+
/**
* Create TestsetRun objects for those in database
* @param string $testset
diff --git a/non-puppet/qtmetrics2/src/TestsetRun.php b/non-puppet/qtmetrics2/src/TestsetRun.php
index f733712..e90f5cc 100644
--- a/non-puppet/qtmetrics2/src/TestsetRun.php
+++ b/non-puppet/qtmetrics2/src/TestsetRun.php
@@ -34,8 +34,8 @@
/**
* TestsetRun class
- * @version 0.3
- * @since 23-06-2015
+ * @version 0.4
+ * @since 30-06-2015
* @author Juha Sippola
*/
@@ -81,14 +81,13 @@ class TestsetRun extends ProjectRun {
/**
* TestsetRun constructor.
- * TestsetRun include the result in the project configuration build
- * @param string $testsetName
+ * @param string $name
* @param string $testsetProjectName
* @param string $projectName
* @param string $branchName
* @param string $stateName
* @param int $buildKey
- * @param string $configurationName
+ * @param string $confName
* @param int $run (ordinal number)
* @param string $result (plain result without any possible flags)
* @param bool $insignificant (true = insignificant)
diff --git a/non-puppet/qtmetrics2/src/test/DatabaseTest.php b/non-puppet/qtmetrics2/src/test/DatabaseTest.php
index afb6671..e15157f 100644
--- a/non-puppet/qtmetrics2/src/test/DatabaseTest.php
+++ b/non-puppet/qtmetrics2/src/test/DatabaseTest.php
@@ -38,8 +38,8 @@ require_once(__DIR__.'/../Factory.php');
* Database unit test class
* Some of the tests require the test data as inserted into database with qtmetrics_insert.sql
* @example To run (in qtmetrics root directory): php <path-to-phpunit>/phpunit.phar ./src/test
- * @version 0.4
- * @since 23-06-2015
+ * @version 0.6
+ * @since 30-06-2015
* @author Juha Sippola
*/
@@ -117,6 +117,29 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test getProjectsFiltered
+ * @dataProvider testGetProjectsFilteredData
+ */
+ public function testGetProjectsFiltered($filter, $exp_match_count_min)
+ {
+ $db = Factory::db();
+ $result = $db->getProjectsFiltered($filter);
+ $this->assertGreaterThanOrEqual($exp_match_count_min, count($result));
+ foreach($result as $row) {
+ $this->assertArrayHasKey('name', $row);
+ }
+ }
+ public function testGetProjectsFilteredData()
+ {
+ return array(
+ array('base', 1),
+ array('ba', 3),
+ array('qt', 35),
+ array('invalid-name', 0)
+ );
+ }
+
+ /**
* Test getTestsetsFiltered
* @dataProvider testGetTestsetsFilteredData
*/
@@ -265,6 +288,9 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
foreach($result as $row) {
$this->assertArrayHasKey('name', $row);
$this->assertArrayHasKey('result', $row);
+ $this->assertArrayHasKey('buildKey', $row);
+ $this->assertArrayHasKey('timestamp', $row);
+ $this->assertArrayHasKey('duration', $row);
$this->assertContains($row['result'], $exp_results);
$branches[] = $row['name'];
}
@@ -278,14 +304,68 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test getLatestProjectBranchTestsetResults
+ * @dataProvider testGetLatestProjectBranchTestsetResultsData
+ */
+ public function testGetLatestProjectBranchTestsetResults($runProject, $runState, $exp_branches)
+ {
+ $confs = array();
+ $db = Factory::db();
+ $result = $db->getLatestProjectBranchTestsetResults($runProject, $runState);
+ $this->assertNotEmpty($result);
+ foreach($result as $row) {
+ $this->assertArrayHasKey('project', $row);
+ $this->assertArrayHasKey('branch', $row);
+ $this->assertArrayHasKey('buildKey', $row);
+ $this->assertArrayHasKey('timestamp', $row);
+ $this->assertArrayHasKey('passed', $row);
+ $this->assertArrayHasKey('failed', $row);
+ $this->assertContains($row['branch'], $exp_branches);
+ }
+ }
+ public function testGetLatestProjectBranchTestsetResultsData()
+ {
+ return array(
+ array('Qt5', 'state', array('dev', 'stable', 'master'))
+ );
+ }
+
+ /**
+ * Test getLatestTestsetProjectBranchTestsetResults
+ * @dataProvider testGetLatestTestsetProjectBranchTestsetResultsData
+ */
+ public function testGetLatestTestsetProjectBranchTestsetResults($testsetProject, $runProject, $runState, $exp_branches)
+ {
+ $confs = array();
+ $db = Factory::db();
+ $result = $db->getLatestTestsetProjectBranchTestsetResults($testsetProject, $runProject, $runState);
+ $this->assertNotEmpty($result);
+ foreach($result as $row) {
+ $this->assertArrayHasKey('project', $row);
+ $this->assertArrayHasKey('branch', $row);
+ $this->assertArrayHasKey('buildKey', $row);
+ $this->assertArrayHasKey('timestamp', $row);
+ $this->assertArrayHasKey('passed', $row);
+ $this->assertArrayHasKey('failed', $row);
+ $this->assertContains($row['branch'], $exp_branches);
+ }
+ }
+ public function testGetLatestTestsetProjectBranchTestsetResultsData()
+ {
+ return array(
+ array('qtbase', 'Qt5', 'state', array('dev', 'stable', 'master'))
+ );
+ }
+
+ /**
* Test getLatestTestsetConfBuildResults
* @dataProvider testGetLatestTestsetConfBuildResultsData
*/
- public function testGetLatestTestsetConfBuildResults($testset, $testsetProject, $runProject, $state, $exp_conf, $exp_branches, $exp_results)
+ public function testGetLatestTestsetConfBuildResults($testset, $testsetProject, $runProject, $runState, $exp_conf, $exp_branches, $exp_results)
{
$confs = array();
$db = Factory::db();
- $result = $db->getLatestTestsetConfBuildResults($testset, $testsetProject, $runProject, $state);
+ $result = $db->getLatestTestsetConfBuildResults($testset, $testsetProject, $runProject, $runState);
$this->assertNotEmpty($result);
foreach($result as $row) {
$this->assertArrayHasKey('name', $row);
@@ -497,6 +577,54 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test getConfBuildsByBranch
+ * @dataProvider testGetConfBuildsByBranchData
+ */
+ public function testGetConfBuildsByBranch($runProject, $runState, $exp_branch, $exp_conf, $exp_key, $exp_result, $has_data)
+ {
+ $branches = array();
+ $confs = array();
+ $keys = array();
+ $results = array();
+ $db = Factory::db();
+ $result = $db->getConfBuildsByBranch($runProject, $runState);
+ foreach($result as $row) {
+ $this->assertArrayHasKey('branch', $row);
+ $this->assertArrayHasKey('conf', $row);
+ $this->assertArrayHasKey('buildKey', $row);
+ $this->assertArrayHasKey('forcesuccess', $row);
+ $this->assertArrayHasKey('insignificant', $row);
+ $this->assertArrayHasKey('result', $row);
+ $this->assertArrayHasKey('timestamp', $row);
+ $this->assertArrayHasKey('duration', $row);
+ $branches[] = $row['branch'];
+ $confs[] = $row['conf'];
+ $keys[] = $row['buildKey'];
+ $results[] = $row['result'];
+ }
+ if ($has_data) {
+ $this->assertNotEmpty($result);
+ $this->assertContains($exp_branch, $branches);
+ $this->assertContains($exp_conf, $confs);
+ $this->assertContains($exp_key, $keys);
+ $this->assertContains($exp_result, $results);
+ } else {
+ $this->assertEmpty($result);
+ }
+ }
+ public function testGetConfBuildsByBranchData()
+ {
+ return array(
+ array('Qt5', 'state', 'dev', 'linux-g++_developer-build_qtnamespace_qtlibinfix_Ubuntu_11.10_x64', '1023', 'FAILURE', 1),
+ array('Qt5', 'state', 'stable', 'win32-msvc2010_developer-build_angle_Windows_7', '1348', 'SUCCESS', 1),
+ array('Qt5', 'state', 'stable', 'macx-clang_developer-build_OSX_10.8', '1348', 'SUCCESS', 1),
+ array('Qt5', 'state', 'stable', 'win32-msvc2010_developer-build_angle_Windows_7', '1348', 'SUCCESS', 1),
+ array('Qt5', 'state', 'dev', 'linux-g++-32_developer-build_Ubuntu_10.04_x86', 'BuildKeyInStringFormat12345', 'FAILURE', 1),
+ array('Qt5', 'invalid', '', '', '', '', 0)
+ );
+ }
+
+ /**
* Test getTestsetResultsByBranchConf
* @dataProvider testGetTestsetResultsByBranchConfData
*/
@@ -544,6 +672,51 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test getTestsetProjectResultsByBranchConf
+ * @dataProvider testGetTestsetProjectResultsByBranchConfData
+ */
+ public function testGetTestsetProjectResultsByBranchConf($testsetProject, $runProject, $runState, $exp_branch, $exp_conf, $exp_key, $has_data)
+ {
+ $branches = array();
+ $confs = array();
+ $keys = array();
+ $results = array();
+ $db = Factory::db();
+ $result = $db->getTestsetProjectResultsByBranchConf($testsetProject, $runProject, $runState);
+ foreach($result as $row) {
+ $this->assertArrayHasKey('branch', $row);
+ $this->assertArrayHasKey('conf', $row);
+ $this->assertArrayHasKey('buildKey', $row);
+ $this->assertArrayHasKey('passed', $row);
+ $this->assertArrayHasKey('ipassed', $row);
+ $this->assertArrayHasKey('failed', $row);
+ $this->assertArrayHasKey('ifailed', $row);
+ $branches[] = $row['branch'];
+ $confs[] = $row['conf'];
+ $keys[] = $row['buildKey'];
+ }
+ if ($has_data) {
+ $this->assertNotEmpty($result);
+ $this->assertContains($exp_branch, $branches);
+ $this->assertContains($exp_conf, $confs);
+ $this->assertContains($exp_key, $keys);
+ } else {
+ $this->assertEmpty($result);
+ }
+ }
+ public function testGetTestsetProjectResultsByBranchConfData()
+ {
+ return array(
+ array('QtBase', 'Qt5', 'state', 'dev', 'linux-g++_developer-build_qtnamespace_qtlibinfix_Ubuntu_11.10_x64', '1023', 1),
+ array('QtBase', 'Qt5', 'state', 'stable', 'win32-msvc2010_developer-build_angle_Windows_7', '1348', 1),
+ array('QtBase', 'Qt5', 'state', 'stable', 'macx-clang_developer-build_OSX_10.8', '1348', 1),
+ array('QtBase', 'Qt5', 'state', 'stable', 'win32-msvc2010_developer-build_angle_Windows_7', '1348', 1),
+ array('QtBase', 'Qt5', 'state', 'dev', 'linux-g++-32_developer-build_Ubuntu_10.04_x86', 'BuildKeyInStringFormat12345', 1),
+ array('Qt5', 'Qt5', 'invalid', '', '', '', '', 0)
+ );
+ }
+
+ /**
* Test getDbRefreshed
*/
public function testGetDbRefreshed()
diff --git a/non-puppet/qtmetrics2/src/test/FactoryTest.php b/non-puppet/qtmetrics2/src/test/FactoryTest.php
index 5f1028a..aa852a6 100644
--- a/non-puppet/qtmetrics2/src/test/FactoryTest.php
+++ b/non-puppet/qtmetrics2/src/test/FactoryTest.php
@@ -37,8 +37,8 @@ require_once(__DIR__.'/../Factory.php');
/**
* Factory unit test class
* @example To run (in qtmetrics root directory): php <path-to-phpunit>/phpunit.phar ./src/test
- * @version 0.3
- * @since 23-06-2015
+ * @version 0.4
+ * @since 30-06-2015
* @author Juha Sippola
*/
@@ -100,6 +100,29 @@ class FactoryTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test getProjectsFiltered
+ * @dataProvider testGetProjectsFilteredData
+ */
+ public function testGetProjectsFiltered($project, $exp_count)
+ {
+ $result = Factory::getProjectsFiltered($project);
+ $this->assertEquals($exp_count, count($result));
+ }
+ public function testGetProjectsFilteredData()
+ {
+ return array(
+ array('', 35), // test data includes 35 projects
+ array('qt',35), // all
+ array('ba', 3),
+ array('bas', 1),
+ array('base', 1),
+ array('qtbase', 1),
+ array('QtBase', 1),
+ array('invalid-name', 0)
+ );
+ }
+
+ /**
* Test getTestsetsFiltered
* @dataProvider testGetTestsetsFilteredData
*/
@@ -125,23 +148,21 @@ class FactoryTest extends PHPUnit_Framework_TestCase
}
/**
- * Test createProjects
- * @dataProvider testCreateProjectsData
+ * Test createProject
+ * @dataProvider testCreateProjectData
*/
- public function testCreateProjects($runProject, $runState)
+ public function testCreateProject($project, $runProject, $runState)
{
- $projects = Factory::createProjects($runProject, $runState);
- foreach($projects as $project) {
- $this->assertTrue($project instanceof Project);
- if ($project->getName() === $runProject) { // check only the projects with project_run data
- $this->assertNotEmpty($project->getStatus());
- }
+ $project = Factory::createProject($project, $runProject, $runState);
+ $this->assertTrue($project instanceof Project);
+ if ($project->getName() === $runProject) { // check only the projects with project_run data
+ $this->assertNotEmpty($project->getStatus());
}
}
- public function testCreateProjectsData()
+ public function testCreateProjectData()
{
return array(
- array('Qt5', 'state',) // project with project_run data
+ array('Qt5', 'Qt5', 'state',) // project with project_run data
);
}
@@ -220,12 +241,31 @@ class FactoryTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test createConfRuns
+ * @dataProvider testCreateConfRunsData
+ */
+ public function testCreateConfRuns($name, $projectName, $branchName, $stateName, $buildKey, $result, $insignificant, $forcesuccess, $timestamp, $duration)
+ {
+ $runs = Factory::createConfRuns($name, $projectName, $branchName, $stateName, $buildKey, $result, $insignificant, $forcesuccess, $timestamp, $duration);
+ foreach($runs as $run) {
+ $this->assertTrue($run instanceof ConfRun);
+ }
+ }
+ public function testCreateConfRunsData()
+ {
+ return array(
+ array('win64-msvc2012_developer-build_qtnamespace_Windows_8', 'Qt5', 'stable', 'state', '1348', 'failed', true, false, '28.5.2013 0:54', 8130),
+ array('linux-g++-32_developer-build_Ubuntu_10.04_x86', 'Qt5', 'dev', 'state', 'BuildKeyInStringFormat12345', 'failed', false, true, '28.5.2013 0:54', 8130)
+ );
+ }
+
+ /**
* Test createTestsetRuns
* @dataProvider testCreateTestsetRunsData
*/
- public function testCreateTestsetRuns($name, $projectName, $projectName, $branchName, $stateName, $buildKey, $confName, $run, $result, $insignificant, $timestamp, $duration)
+ public function testCreateTestsetRuns($name, $testsetProject, $projectName, $branchName, $stateName, $buildKey, $confName, $run, $result, $insignificant, $timestamp, $duration)
{
- $runs = Factory::createTestsetRuns($name, $projectName, $projectName, $branchName, $stateName, $buildKey, $confName, $run, $result, $insignificant, $timestamp, $duration);
+ $runs = Factory::createTestsetRuns($name, $testsetProject, $projectName, $branchName, $stateName, $buildKey, $confName, $run, $result, $insignificant, $timestamp, $duration);
foreach($runs as $run) {
$this->assertTrue($run instanceof TestsetRun);
}
diff --git a/non-puppet/qtmetrics2/templates/about.html b/non-puppet/qtmetrics2/templates/about.html
index 1ba66fc..6e2ca7d 100644
--- a/non-puppet/qtmetrics2/templates/about.html
+++ b/non-puppet/qtmetrics2/templates/about.html
@@ -34,8 +34,8 @@
/**
* About window content
- * @version 0.6
- * @since 26-06-2015
+ * @version 0.7
+ * @since 30-06-2015
* @author Juha Sippola
*/
@@ -44,4 +44,4 @@
<p>This is Qt Metrics revision 2 with redesigned UI and database.</p>
<p>These pages are still <strong>under construction</strong> and therefore the views and functionality is limited.</p>
<p>See the <a href="https://wiki.qt.io/Qt_Metrics_2_Backlog" target="_blank">backlog</a> for development items currently identified or in progress.</p>
-<p><small>Version 0.6 (26-Jun-2015)</small></p>
+<p><small>Version 0.7 (30-Jun-2015)</small></p>
diff --git a/non-puppet/qtmetrics2/templates/build_project.html b/non-puppet/qtmetrics2/templates/build_project.html
new file mode 100644
index 0000000..c400e28
--- /dev/null
+++ b/non-puppet/qtmetrics2/templates/build_project.html
@@ -0,0 +1,342 @@
+{#
+#############################################################################
+##
+## Copyright (C) 2015 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Quality Assurance module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL21$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see http://www.qt.io/terms-conditions. For further
+## information use the contact form at http://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 or version 3 as published by the Free
+## Software Foundation and appearing in the file LICENSE.LGPLv21 and
+## LICENSE.LGPLv3 included in the packaging of this file. Please review the
+## following information to ensure the GNU Lesser General Public License
+## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## As a special exception, The Qt Company gives you certain additional
+## rights. These rights are described in The Qt Company LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+/**
+ * Build project page
+ * @version 0.1
+ * @since 30-06-2015
+ * @author Juha Sippola
+ */
+
+#}
+
+{% include "header.html" %}
+
+{# Failed/passed bar area size in px #}
+{% set BAR_AREA = 120 %}
+
+{# project as Project object
+/**
+ * @var Project[] project
+ */
+#}
+
+{# confRuns as ConfRun objects
+/**
+ * @var ConfRun[] confRuns
+ */
+#}
+
+<ol class="breadcrumb">
+ {% for link in breadcrumb %}
+ <li><a href="{{ link.link }}">{{ link.name }}</a></li>
+ {% endfor %}
+ <li class="active">{{ project.getName }}</li>
+</ol>
+
+<div class="container-fluid">
+ <div class="row">
+
+ <div class="col-sm-12 col-md-12 main">
+
+ {# Check if any runs available #}
+ {% set runsAvailable = 0 %}
+ {% for run in latestProjectRuns %}
+ {% set runsAvailable = 1 %}
+ {% endfor %}
+
+ {##### Title #####}
+
+ <h1 class="page-header">
+ {{ project.getName }}
+ <button type="button" class="btn btn-xs btn-info" data-toggle="collapse" data-target="#info" aria-expanded="false" aria-controls="info">
+ <span class="glyphicon glyphicon-info-sign"></span>
+ </button>
+ <small>{{ refreshed }}</small>
+ </h1>
+
+ {##### Info well #####}
+
+ <div class="collapse" id="info">
+ <div class="well infoWell">
+ <span class="glyphicon glyphicon-info-sign"></span> <strong>Build Project</strong><br>
+ <ul>
+ <li>In <strong>Latest Status</strong>, the <strong>latest result</strong> shows the overall project status based on the
+ latest <strong>{{ masterProject }} {{ masterState }}</strong> builds across all branches,
+ and the <strong>branch</strong> results across all configurations (both show failed if failed
+ in one or in several builds).</li>
+ <li><strong>Results in Branches</strong> shows the {{ project.getName }} run results by branch
+ and their configuration on <strong>{{ masterProject }} {{ masterState }}</strong> builds
+ (<span class="glyphicon glyphicon-ok green"></span> = {{ constant('ConfRun::RESULT_SUCCESS') }},
+ <span class="glyphicon glyphicon-ok-sign green"></span> = {{ constant('ConfRun::RESULT_SUCCESS') }} as forcesuccess,
+ <span class="glyphicon glyphicon-remove red"></span> = {{ constant('ConfRun::RESULT_FAILURE') }},
+ <span class="glyphicon glyphicon-ban-circle gray"></span> = {{ constant('ConfRun::RESULT_UNDEF') }});
+ details on the runs are available as tooltip on result icon.</li>
+ </ul>
+ </div>
+ </div>
+
+ {% if runsAvailable %}
+
+ {##### Latest Status #####}
+
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Latest Status</h4>
+ </div>
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th>project</th>
+ <th class="rightBorder">latest result</th>
+ {% for branch in latestProjectRuns %}
+ <th class="center">{{ branch.name }}</th>
+ {% endfor %}
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ {# Project name #}
+ <td>{{ project.getName }}</td>
+
+ {# Testset status according to the latest build results #}
+ {% if project.getStatus == constant('ConfRun::RESULT_SUCCESS') %}
+ {% set resultIcon = 'glyphicon glyphicon-ok green' %}
+ {% elseif project.getStatus == constant('ConfRun::RESULT_FAILURE') %}
+ {% set resultIcon = 'glyphicon glyphicon-remove red' %}
+ {% else %}
+ {% set resultIcon = '' %}
+ {% endif %}
+ <td class="rightBorder"><span class="spaceHorizontal {{ resultIcon }}"></span>{{ project.getStatus }}</td>
+
+ {# Result (by branch) #}
+ {% for run in latestProjectRuns %}
+ {% if run.result == constant('ConfRun::RESULT_SUCCESS') %}
+ {% set resultIcon = 'glyphicon glyphicon-ok green' %}
+ {% elseif run.result == constant('ConfRun::RESULT_FAILURE') %}
+ {% set resultIcon = 'glyphicon glyphicon-remove red' %}
+ {% else %}
+ {% set resultIcon = 'glyphicon glyphicon-ban-circle gray' %}
+ {% endif %}
+ <td class="center">
+ <span class="spaceHorizontal {{ resultIcon }} clickOnTouch"
+ data-toggle="tooltip" data-placement="top" data-html="true"
+ title="<table>
+ <tr><th>Branch: </td><td>{{ run.name }}</td></tr>
+ <tr><th>Build key: </td><td>{{ run.buildKey }}</td></tr>
+ <tr><th>Timestamp: </td><td>{{ run.timestamp }}</td></tr>
+ <tr><th>Result: </td><td>{{ run.result }}</td></tr>
+ <tr><th>Duration: </td><td>{{ run.duration}}</td></tr>
+ </table>">
+ </span>
+ </td>
+ {% endfor %}
+ </tr>
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
+
+ {##### Results in Branches #####}
+
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Results in Branches</h4>
+ </div>
+ </div>
+
+ {# Get branches #}
+ {% set branches = [] %}
+ {% for run in projectBuilds %}
+ {% if run.branch not in branches %}
+ {% set branches = branches|merge([run.branch]) %}
+ {% endif %}
+ {% endfor %}
+
+ {# Loop all the branches #}
+ {% for branch in branches %}
+
+ {# Get all build keys #}
+ {% set buildKey = '' %}
+ {% set buildKeys = [] %}
+ {% set dates = [] %}
+ {% for run in projectBuilds %}
+ {% if run.branch == branch %}
+ {% if buildKey != run.buildKey %}
+ {% set buildKey = run.buildKey %}
+ {% set buildKeys = buildKeys|merge([run.buildKey]) %}
+ {% set dates = dates|merge([run.timestamp]) %}
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+
+ {# Check if conf run for this branch #}
+ {% set confBranch = 0 %}
+ {% for run in confRuns if run.getBranchName == branch %}
+ {% set confBranch = 1 %}
+ {% endfor %}
+
+ {# Show branch if conf run for it #}
+ {% if confBranch %}
+ <div class="panel panel-info">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">{{ branch }}</h4>
+ </div>
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th class="bold rightBorder">{{ project.getName }}</th>
+ {% for key, buildKey in buildKeys %}
+ <th class="center">
+ {% if buildKey|length > 6 %}
+ <span class="clickOnTouch" data-toggle="tooltip" data-placement="top"
+ title="{{ buildKey }}">{{ buildKey|slice(0, 4) }}...
+ </span>
+ {% else %}
+ {{ buildKey }}
+ {% endif %}
+ <br>
+ <span class="gray"><small>{{ dates[key]|date("m-d") }}</small></span>
+ </th>
+ {% endfor %}
+ </tr>
+ </thead>
+ <tbody>
+ {% set confPrev = '' %}
+ {% set buildKeyIndexPrinted = -1 %}
+ {% set buildKeyFound = 0 %}
+ {% for run in confRuns if run.getBranchName == branch %}
+
+ {# New row for each conf #}
+ {% if confPrev != run.getName %}
+ {# Close previous row #}
+ {% if confPrev != '' %}
+ {# Fill empty cells at the end of the row #}
+ {% for key, buildKey in buildKeys %}
+ {% if key > buildKeyIndexPrinted %}
+ <td></td>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% endif %}
+ <tr>
+ <td class="rightBorder"><small>{{ run.getName }}</small></td>
+ {% set buildKeyIndexPrinted = -1 %}
+ {% endif %}
+
+ {# Result per build key #}
+ {% set buildKeyFound = 0 %}
+ {% for key, buildKey in buildKeys %}
+ {# Print each column only once (checked based on column index key and buildKeyFound flag) #}
+ {% if key > buildKeyIndexPrinted and not buildKeyFound %}
+ {% if buildKey == run.getBuildKey %}
+ {# Print result #}
+ {% set forcesuccess = '' %}
+ {% if run.getResult == constant('ConfRun::RESULT_SUCCESS') %}
+ {% if run.getForcesuccess == 0 %}
+ {% set resultIcon = 'glyphicon glyphicon-ok green' %}
+ {% else %}
+ {# Forcesuccess #}
+ {% set resultIcon = 'glyphicon glyphicon-ok-sign green' %}
+ {% set forcesuccess = ' (as forcesuccess)' %}
+ {% endif %}
+ {% elseif run.getResult == constant('ConfRun::RESULT_FAILURE') %}
+ {% set resultIcon = 'glyphicon glyphicon-remove red' %}
+ {% elseif run.getResult == constant('ConfRun::RESULT_UNDEF') %}
+ {% set resultIcon = 'glyphicon glyphicon-ban-circle gray' %}
+ {% else %}
+ {% set resultIcon = '' %}
+ {% endif %}
+ <td class="center">
+ <span class="spaceHorizontal {{ resultIcon }} clickOnTouch"
+ data-toggle="tooltip" data-placement="top" data-html="true"
+ title="<table>
+ <tr><th>Build key: </th><td>{{ buildKey }}</td></tr>
+ <tr><th>Configuration: </th><td>{{ run.getName }}</td></tr>
+ <tr><th>Timestamp: </th><td>{{ run.getTimestamp }}</td></tr>
+ <tr><th>Result: </th><td>{{ run.getResult }} {{ forcesuccess }}</td></tr>
+ <tr><th>Duration: </th><td>{{ run.getDuration }}</td></tr>
+ <tr><th>Forcesuccess: </th><td>{% if run.getForcesuccess %}yes{% else %}no{% endif %}</td></tr>
+ <tr><th>Insignificant: </th><td>{% if run.getInsignificant %}yes{% else %}no{% endif %}</td></tr>
+ </table>">
+ </span>
+ </td>
+ {% set buildKeyFound = 1 %}
+ {% else %}
+ {# Print empty cell #}
+ <td></td>
+ {% endif %}
+ {% set buildKeyIndexPrinted = key %}
+ {% endif %}
+ {% endfor %}
+ {% set confPrev = run.getName %}
+ {% endfor %}
+
+ {# Close last row (also fill empty cells at the end of the row) #}
+ {% for key, buildKey in buildKeys %}
+ {% if key > buildKeyIndexPrinted %}
+ <td></td>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
+ {% endif %} {# testsetBranch #}
+ {% endfor %}
+
+ {% else %} {# runsAvailable #}
+ <div class="alert alert-danger" role="alert">
+ No build data available for project {{ project.getName }}!
+ </div>
+ {% endif %}
+
+ </div> {# /col... #}
+ </div> {# /row #}
+
+</div> {# /container-fluid #}
+
+{% include "footer.html" %}
+
+{# Local scripts for this page #}
+<script src="scripts/tooltip.js"></script>
+
+{% include "close.html" %}
diff --git a/non-puppet/qtmetrics2/templates/home.html b/non-puppet/qtmetrics2/templates/home.html
index ed41f70..b9d3486 100644
--- a/non-puppet/qtmetrics2/templates/home.html
+++ b/non-puppet/qtmetrics2/templates/home.html
@@ -34,8 +34,8 @@
/**
* Home page
- * @version 0.2
- * @since 18-06-2015
+ * @version 0.4
+ * @since 30-06-2015
* @author Juha Sippola
*/
@@ -59,17 +59,23 @@
<div class="row">
- <div class="col-md-6">
+ <div class="col-md-1">
+ </div>
+
+ <div class="col-md-4">
+ <hr>
<h2>Overview</h2>
- <p>See the overview of the builds by projects across the latest branches:</p>
+ <p>See the latest build status across the branches:</p>
<div>
- {% for state in states %}
- <a class="btn btn-default btn-xs" disabled="disabled" href="{{ overviewRoute }}/{{ state.name }}" role="button">{{ state.name }}</a>
- {% endfor %}
+ <a class="btn btn-primary btn-xs" href="{{ overviewRoute }}" role="button">{{ masterProject }} {{ masterState }}</a>
</div>
</div>
- <div class="col-md-6">
+ <div class="col-md-1">
+ </div>
+
+ <div class="col-md-4">
+ <hr>
<h2>Platforms</h2>
<p>See target platform status:</p>
<div>
@@ -86,7 +92,9 @@
{% endfor %}
{% for name in os %}
<div class="btn-group">
- <button type="button" class="btn btn-default btn-xs dropdown-toggle" disabled="disabled" data-toggle="dropdown" aria-expanded="false">{{ name }}<span class="caret"></span></button>
+ <button type="button" class="btn btn-primary btn-xs dropdown-toggle" disabled="disabled"
+ data-toggle="dropdown" aria-expanded="false">{{ name }}<span class="caret"></span>
+ </button>
<ul class="dropdown-menu textSmall" role="menu">
{% for platform in platforms %}
{% if platform.os == name %}
@@ -100,62 +108,80 @@
{% endfor %}
</div>
</div>
+
</div>
<div class="row">
- <div class="col-md-6">
- <h2>Branches</h2>
- <p>See branch status:</p>
+ <div class="col-md-1">
+ </div>
+
+ <div class="col-md-4">
+ <hr>
+ <h2>Projects</h2>
+ <p>See testset status for a project:</p>
<div>
- {% for branch in branches %}
- <a class="btn btn-default btn-xs" disabled="disabled" href="{{ branchRoute }}/{{ branch.name }}" role="button">{{ branch.name }}</a>
- {% endfor %}
+ <form class="form-horizontal" role="form" method="post">
+ <div class="input-group input-group-sm">
+ <input id="projectInput" name="projectInputValue" type="text" class="form-control" placeholder="project name...">
+ <span class="input-group-btn">
+ <input id="projectInputSubmit" name="projectInputSubmit" type="submit" class="btn btn-primary" value="Show">
+ </span>
+ </div>
+ </form>
</div>
</div>
+ <div class="col-md-1">
+ </div>
+
<div class="col-md-4">
+ <hr>
<h2>Tests</h2>
- <p>See top failure lists or single testset results:</p>
- <div>
- <a class="btn btn-default btn-xs" href="{{ testRoute }}/top" role="button">top failures</a>
- <a class="btn btn-default btn-xs" href="{{ testRoute }}/flaky" role="button">flaky testsets</a>
- </div>
+ <p>See results for a testset:</p>
<div>
<form class="form-horizontal" role="form" method="post">
<div class="input-group input-group-sm">
<input id="testsetInput" name="testsetInputValue" type="text" class="form-control" placeholder="testset name...">
<span class="input-group-btn">
- <input id="testsetInputSubmit" name="testsetInputSubmit" type="submit" class="btn btn-default" value="Show">
+ <input id="testsetInputSubmit" name="testsetInputSubmit" type="submit" class="btn btn-primary" value="Show">
</span>
- </div> {# /input-group #}
+ </div>
</form>
</div>
+ <br>
+ <p>See testset lists:</p>
+ <div>
+ <a class="btn btn-primary btn-xs" href="{{ testRoute }}/top" role="button">top failures</a>
+ <a class="btn btn-primary btn-xs" href="{{ testRoute }}/flaky" role="button">flaky testsets</a>
+ </div>
</div>
+
</div>
<div class="row">
- <div class="col-md-6">
- <h2>Projects</h2>
- <p>See project status:</p>
+ <div class="col-md-1">
+ </div>
+
+ <div class="col-md-4">
+ <hr>
+ <h2>Branches</h2>
+ <p>See branch status:</p>
<div>
- {% for project in projects %}
- {# Show button color based on project status (according to the latest build results) #}
- {% if project.getStatus == constant('ProjectRun::RESULT_SUCCESS') %}
- {% set buttonStatus = 'btn-success' %}
- {% elseif project.getStatus == constant('ProjectRun::RESULT_FAILURE') %}
- {% set buttonStatus = 'btn-danger' %}
- {% else %}
- {% set buttonStatus = 'btn-default' %}
- {% endif %}
- {# Show only valid projects #}
- {% if project.getStatus != constant('ProjectRun::RESULT_EMPTY') %}
- <a class="btn {{ buttonStatus }} btn-xs" disabled="disabled" href="{{ overviewRoute }}/state/{{ project.getName }}" role="button">{{ project.getName }}</a>
- {% endif %}
+ {% for branch in branches %}
+ <a class="btn btn-primary btn-xs" disabled="disabled" href="{{ branchRoute }}/{{ branch.name }}" role="button">{{ branch.name }}</a>
{% endfor %}
</div>
</div>
+
+ <div class="col-md-1">
+ </div>
+
+ <div class="col-md-4">
+ <hr>
+ </div>
+
</div>
<br>
@@ -166,6 +192,7 @@
{% include "footer.html" %}
{# Local scripts for this page #}
+<script src="scripts/project_autocomplete.js"></script>
<script src="scripts/testset_autocomplete.js"></script>
{% include "close.html" %}
diff --git a/non-puppet/qtmetrics2/templates/overview.html b/non-puppet/qtmetrics2/templates/overview.html
new file mode 100644
index 0000000..8ccb955
--- /dev/null
+++ b/non-puppet/qtmetrics2/templates/overview.html
@@ -0,0 +1,237 @@
+{#
+#############################################################################
+##
+## Copyright (C) 2015 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Quality Assurance module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL21$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see http://www.qt.io/terms-conditions. For further
+## information use the contact form at http://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 or version 3 as published by the Free
+## Software Foundation and appearing in the file LICENSE.LGPLv21 and
+## LICENSE.LGPLv3 included in the packaging of this file. Please review the
+## following information to ensure the GNU Lesser General Public License
+## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## As a special exception, The Qt Company gives you certain additional
+## rights. These rights are described in The Qt Company LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+/**
+ * Overview page
+ * @version 0.1
+ * @since 30-06-2015
+ * @author Juha Sippola
+ */
+
+#}
+
+{% include "header.html" %}
+
+{# Failed/passed bar area size in px #}
+{% set BAR_AREA = 60 %}
+
+<ol class="breadcrumb">
+ {% for link in breadcrumb %}
+ <li><a href="{{ link.link }}">{{ link.name }}</a></li>
+ {% endfor %}
+ <li class="active">overview</li>
+</ol>
+
+<div class="container-fluid">
+ <div class="row">
+
+ <div class="col-sm-12 col-md-12 main">
+
+ {##### Title #####}
+
+ <h1 class="page-header">
+ Overview: {{ masterProject }} {{ masterState }}
+ <button type="button" class="btn btn-xs btn-info" data-toggle="collapse" data-target="#info" aria-expanded="false" aria-controls="info">
+ <span class="glyphicon glyphicon-info-sign"></span>
+ </button>
+ <small>{{ refreshed }}</small>
+ </h1>
+
+ {##### Info well #####}
+
+ <div class="collapse" id="info">
+ <div class="well infoWell">
+ <span class="glyphicon glyphicon-info-sign"></span> <strong>Overview</strong><br>
+ <ul>
+ <li><strong>Latest {{ masterProject }} {{ masterState }} Build Status</strong> shows
+ the overall result of the latest <strong>{{ masterProject }} {{ masterState }}</strong>
+ builds themselves by branch; details on the runs are available as tooltip on result icon.</li>
+ <li><strong>Latest Testing Status</strong> shows the status based on testset results
+ in the latest <strong>{{ masterProject }} {{ masterState }}</strong> builds in any
+ configuration by testset project across all branches.</li>
+ </ul>
+ </div>
+ </div>
+
+ {##### Latest Build Status #####}
+
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Latest {{ masterProject }} {{ masterState }} Build Status</h4>
+ </div>
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th class="rightBorder">project</th>
+ {% for branch in latestProjectRuns %}
+ <th class="center">{{ branch.name }}</th>
+ {% endfor %}
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ {# Project name #}
+ <td class="rightBorder"><a href="{{ buildProjectRoute }}/{{ masterProject }}">{{ masterProject }}</a></td>
+
+ {# Result (by branch) #}
+ {% for run in latestProjectRuns %}
+ {% if run.result == constant('projectRun::RESULT_SUCCESS') %}
+ {% set resultIcon = 'glyphicon glyphicon-ok green' %}
+ {% elseif run.result == constant('projectRun::RESULT_FAILURE') %}
+ {% set resultIcon = 'glyphicon glyphicon-remove red' %}
+ {% else %}
+ {% set resultIcon = 'glyphicon glyphicon-ban-circle gray' %}
+ {% endif %}
+ <td class="center">
+ <span class="spaceHorizontal {{ resultIcon }} clickOnTouch"
+ data-toggle="tooltip" data-placement="top" data-html="true"
+ title="<table>
+ <tr><th>Branch: </td><td>{{ run.name }}</td></tr>
+ <tr><th>Build key: </td><td>{{ run.buildKey }}</td></tr>
+ <tr><th>Timestamp: </td><td>{{ run.timestamp }}</td></tr>
+ <tr><th>Result: </td><td>{{ run.result }}</td></tr>
+ <tr><th>Duration: </td><td>{{ run.duration}}</td></tr>
+ </table>">
+ </span>
+ </td>
+ {% endfor %}
+ </tr>
+
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
+
+ {##### Latest Testing Status #####}
+
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Latest Testing Status</h4>
+ </div>
+
+ {# Get branches and projects #}
+ {% set branches = [] %}
+ {% set projects = [] %}
+ {% for run in latestTestsetRuns %}
+ {% if run.branch not in branches %}
+ {% set branches = branches|merge([run.branch]) %}
+ {% endif %}
+ {% if run.project not in projects %}
+ {% set projects = projects|merge([run.project]) %}
+ {% endif %}
+ {% endfor %}
+
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th class="rightBorder">testset project</th>
+ {% for branch in branches %}
+ <th class="center">{{ branch }}<br>
+ <small>failed <span class ="gray">(total)</span></small>
+ </th>
+ <th class="showInLargeDisplay"></th>
+ {% endfor %}
+ </tr>
+ </thead>
+ <tbody>
+ {# Calculate max failed result count for the bar #}
+ {% set maxCount = 1 %}
+ {% for run in latestTestsetRuns %}
+ {% if run.failed > maxCount %}
+ {% set maxCount = run.failed %}
+ {% endif %}
+ {% endfor %}
+
+ {% for project in projects %}
+ <tr>
+ {# Project name #}
+ <td class="rightBorder"><a href="{{ testsetProjectRoute }}/{{ project }}">{{ project }}</a></td>
+
+ {# Result (by branch) #}
+ {% for branch in branches %}
+ {% for run in latestTestsetRuns if project == run.project and branch == run.branch %}
+
+ {# Show results #}
+ {% set failed = run.failed %}
+ {% set passed = run.passed %}
+ {% set total = passed + failed %}
+ <td class="center">{{ failed }}<span class ="gray"> ({{ total }})</span></td>
+
+ {# Show results as bars (scaled to BAR_AREA px) #}
+ {% set failedBar = ((BAR_AREA/maxCount) * failed)|round(0, 'floor') %}
+ {% if (failed > 0) and (failedBar == 0) %}
+ {% set failedBar = 1 %}
+ {% endif %}
+ {% if failed == 0 %}
+ {% set failed = '' %}
+ {% endif %}
+ {% if (passed > 0) and (failed == 0) %}
+ {% set passedBar = maxCount %}
+ {% else %}
+ {% set passed = '' %}
+ {% endif %}
+ <td class="center showInLargeDisplay">
+ <div>
+ <div class="floatLeft redBackground" style="width: {{ failedBar }}px"><small>{{ failed }}</small></div>
+ <div class="floatLeft greenBackground" style="width: {{ passedBar }}px"><small>{{ passed }}</small></div>
+ </div>
+ </td>
+ {% else %}
+ <td></td>
+ {% endfor %}
+ {% endfor %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
+
+ </div> {# /col... #}
+ </div> {# /row #}
+
+</div> {# /container-fluid #}
+
+{% include "footer.html" %}
+
+{# Local scripts for this page #}
+<script src="scripts/tooltip.js"></script>
+
+{% include "close.html" %}
diff --git a/non-puppet/qtmetrics2/templates/testset.html b/non-puppet/qtmetrics2/templates/testset.html
index 59f98e4..9df501c 100644
--- a/non-puppet/qtmetrics2/templates/testset.html
+++ b/non-puppet/qtmetrics2/templates/testset.html
@@ -34,8 +34,8 @@
/**
* Testset page
- * @version 0.4
- * @since 26-06-2015
+ * @version 0.5
+ * @since 30-06-2015
* @author Juha Sippola
*/
@@ -70,6 +70,12 @@
<div class="col-sm-12 col-md-12 main">
+ {# Check if any runs available #}
+ {% set runsAvailable = 0 %}
+ {% for run in testsetRuns %}
+ {% set runsAvailable = 1 %}
+ {% endfor %}
+
{##### Title #####}
<h1 class="page-header">
@@ -97,256 +103,264 @@
(during the last {{ lastDaysFlaky }} days, since {{ sinceDateFlaky }}).</li>
<li><strong>Results in Branches</strong> shows the {{ testset.getName }} run results by branch
and their configuration on <strong>{{ masterProject }} {{ masterState }}</strong> builds
- (<span class="glyphicon glyphicon-ok green"></span> = passed,
- <span class="glyphicon glyphicon-ok-sign green"></span> = passed as flaky,
- <span class="glyphicon glyphicon-remove red"></span> = failed); details on the runs are
- available as tooltip on result icon.</li>
+ (<span class="glyphicon glyphicon-ok green"></span> = {{ constant('TestsetRun::RESULT_SUCCESS') }},
+ <span class="glyphicon glyphicon-ok-sign green"></span> = {{ constant('TestsetRun::RESULT_SUCCESS') }} as flaky,
+ <span class="glyphicon glyphicon-remove red"></span> = {{ constant('TestsetRun::RESULT_FAILURE') }});
+ details on the runs are available as tooltip on result icon.</li>
</ul>
</div>
</div>
- {##### Summary #####}
-
- <div class="panel panel-primary">
- <div class="panel-heading">
- <h4 class="panel-title bold">Summary</h4>
- </div>
- <div class="panel-body">
- <div class="table-responsive">
- <table class="table table-striped">
- <thead>
- <tr>
- <th>project</th>
- <th>latest result</th>
- <th class="leftBorder center"><span class="spaceHorizontal glyphicon glyphicon-remove red"></span>failed <span class ="gray">(total)</span></th>
- <th class="showInLargeDisplay"></th>
- <th class="leftBorder center"><span class="spaceHorizontal glyphicon glyphicon-ok-sign green"></span>flaky <span class ="gray">(total)</span></th>
- <th class="showInLargeDisplay"></th>
- </tr>
- </thead>
- <tbody>
- {# Calculate max result count for the bar #}
- {% set maxCount = 1 %}
- {% if (testset.getTestsetResultCounts.passed + testset.getTestsetResultCounts.failed) > maxCount %}
- {% set maxCount = testset.getTestsetResultCounts.passed + testset.getTestsetResultCounts.failed %}
- {% endif %}
- {% if testset.getTestsetFlakyCounts.flaky > maxCount %}
- {% set maxCount = testset.getTestsetFlakyCounts.flaky %}
- {% endif %}
-
- {# Print summary #}
- <tr>
- {# Project name #}
- <td>{{ testset.getProjectName }}</td>
-
- {# Testset status according to the latest build results #}
- {% if testset.getStatus == constant('testsetRun::RESULT_SUCCESS') %}
- {% set resultIcon = 'glyphicon glyphicon-ok green' %}
- {% elseif testset.getStatus == constant('testsetRun::RESULT_FAILURE') %}
- {% set resultIcon = 'glyphicon glyphicon-remove red' %}
- {% else %}
- {% set resultIcon = '' %}
- {% endif %}
- <td><span class="spaceHorizontal {{ resultIcon }}"></span>{{ testset.getStatus }}</td>
-
- {# Show failed #}
- {% set failed = testset.getTestsetResultCounts.failed %}
- {% set passed = testset.getTestsetResultCounts.passed %}
- {% set total = passed + failed %}
- <td class="leftBorder center">{{ failed }}<span class ="gray"> ({{ total }})</span></td>
- {# Show results as bars (scaled to BAR_AREA px) #}
- {% set passedBar = ((BAR_AREA/maxCount) * passed)|round(0, 'floor') %}
- {% if (passed > 0) and (passedBar == 0) %}
- {% set passedBar = 1 %}
- {% endif %}
- {% set failedBar = ((BAR_AREA/maxCount)*failed)|round(0, 'floor') %}
- {% if (failed > 0) and (failedBar == 0) %}
- {% set failedBar = 1 %}
+ {% if runsAvailable %}
+
+ {##### Latest Status #####}
+
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Latest Status</h4>
+ </div>
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th>project</th>
+ <th>latest result</th>
+ <th class="leftBorder center"><span class="spaceHorizontal glyphicon glyphicon-remove red"></span>failed <span class ="gray">(total)</span></th>
+ <th class="showInLargeDisplay"></th>
+ <th class="leftBorder center"><span class="spaceHorizontal glyphicon glyphicon-ok-sign green"></span>flaky <span class ="gray">(total)</span></th>
+ <th class="showInLargeDisplay"></th>
+ </tr>
+ </thead>
+ <tbody>
+ {# Calculate max result count for the bar #}
+ {% set maxCount = 1 %}
+ {% if (testset.getTestsetResultCounts.passed + testset.getTestsetResultCounts.failed) > maxCount %}
+ {% set maxCount = testset.getTestsetResultCounts.passed + testset.getTestsetResultCounts.failed %}
{% endif %}
- <td class="center showInLargeDisplay">
- <div>
- <div class="floatLeft redBackground" style="width: {{ failedBar }}px">{{ failed }}</div>
- <div class="floatLeft greenBackground" style="width: {{ passedBar }}px">{{ passed }}</div>
- </div>
- </td>
-
- {# Show flaky #}
- {% set flaky = testset.getTestsetFlakyCounts.flaky %}
- <td class="leftBorder center">{{ flaky }}<span class ="gray"> ({{ total }})</span></td>
- {# Show results as bars (scaled to BAR_AREA px) #}
- {% set flakyBar = ((BAR_AREA/maxCount)*flaky)|round(0, 'floor') %}
- {% if (flaky > 0) and (flakyBar == 0) %}
- {% set flakyBar = 1 %}
+ {% if testset.getTestsetFlakyCounts.flaky > maxCount %}
+ {% set maxCount = testset.getTestsetFlakyCounts.flaky %}
{% endif %}
- <td class="center showInLargeDisplay">
- {% if flaky > 0 %}
- <div>
- <div class="floatLeft redBackground" style="width: {{ flakyBar }}px">{{ flaky }}</div>
- </div>
+
+ {# Print summary #}
+ <tr>
+ {# Project name #}
+ <td>{{ testset.getProjectName }}</td>
+
+ {# Testset status according to the latest build results #}
+ {% if testset.getStatus == constant('TestsetRun::RESULT_SUCCESS') %}
+ {% set resultIcon = 'glyphicon glyphicon-ok green' %}
+ {% elseif testset.getStatus == constant('TestsetRun::RESULT_FAILURE') %}
+ {% set resultIcon = 'glyphicon glyphicon-remove red' %}
+ {% else %}
+ {% set resultIcon = '' %}
+ {% endif %}
+ <td><span class="spaceHorizontal {{ resultIcon }}"></span>{{ testset.getStatus }}</td>
+
+ {# Show failed #}
+ {% set failed = testset.getTestsetResultCounts.failed %}
+ {% set passed = testset.getTestsetResultCounts.passed %}
+ {% set total = passed + failed %}
+ <td class="leftBorder center">{{ failed }}<span class ="gray"> ({{ total }})</span></td>
+ {# Show results as bars (scaled to BAR_AREA px) #}
+ {% set passedBar = ((BAR_AREA/maxCount) * passed)|round(0, 'floor') %}
+ {% if (passed > 0) and (passedBar == 0) %}
+ {% set passedBar = 1 %}
+ {% endif %}
+ {% set failedBar = ((BAR_AREA/maxCount)*failed)|round(0, 'floor') %}
+ {% if (failed > 0) and (failedBar == 0) %}
+ {% set failedBar = 1 %}
{% endif %}
- </td>
- </tr>
+ <td class="center showInLargeDisplay">
+ <div>
+ <div class="floatLeft redBackground" style="width: {{ failedBar }}px"><small>{{ failed }}</small></div>
+ <div class="floatLeft greenBackground" style="width: {{ passedBar }}px"><small>{{ passed }}</small></div>
+ </div>
+ </td>
+
+ {# Show flaky #}
+ {% set flaky = testset.getTestsetFlakyCounts.flaky %}
+ <td class="leftBorder center">{{ flaky }}<span class ="gray"> ({{ total }})</span></td>
+ {# Show results as bars (scaled to BAR_AREA px) #}
+ {% set flakyBar = ((BAR_AREA/maxCount)*flaky)|round(0, 'floor') %}
+ {% if (flaky > 0) and (flakyBar == 0) %}
+ {% set flakyBar = 1 %}
+ {% endif %}
+ <td class="center showInLargeDisplay">
+ {% if flaky > 0 %}
+ <div>
+ <div class="floatLeft redBackground" style="width: {{ flakyBar }}px"><small>{{ flaky }}</small></div>
+ </div>
+ {% endif %}
+ </td>
+ </tr>
- </tbody>
- </table>
- </div> {# /table-responsive #}
- </div> {# /panel-body #}
- </div> {# /panel... #}
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
- {##### Results in Branches #####}
+ {##### Results in Branches #####}
- <div class="panel panel-primary">
- <div class="panel-heading">
- <h4 class="panel-title bold">Results in Branches</h4>
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Results in Branches</h4>
+ </div>
</div>
- </div>
-
- {# Get branches #}
- {% set branches = [] %}
- {% for run in projectBuilds %}
- {% if run.branch not in branches %}
- {% set branches = branches|merge([run.branch]) %}
- {% endif %}
- {% endfor %}
- {# Loop all the branches #}
- {% for branch in branches %}
-
- {# Get all build keys #}
- {% set buildKey = '' %}
- {% set buildKeys = [] %}
- {% set dates = [] %}
+ {# Get branches #}
+ {% set branches = [] %}
{% for run in projectBuilds %}
- {% if run.branch == branch %}
- {% if buildKey != run.buildKey %}
- {% set buildKey = run.buildKey %}
- {% set buildKeys = buildKeys|merge([run.buildKey]) %}
- {% set dates = dates|merge([run.timestamp]) %}
- {% endif %}
+ {% if run.branch not in branches %}
+ {% set branches = branches|merge([run.branch]) %}
{% endif %}
{% endfor %}
- {# Check if testset run for this branch #}
- {% set testsetBranch = 0 %}
- {% for run in testsetRuns if run.getBranchName == branch %}
- {% set testsetBranch = 1 %}
- {% endfor %}
-
- {# Show branch if testset run for it #}
- {% if testsetBranch %}
- <div class="panel panel-info">
- <div class="panel-heading">
- <h4 class="panel-title bold">{{ branch }}</h4>
- </div>
- <div class="panel-body">
- <div class="table-responsive">
- <table class="table table-striped">
- <thead>
- <tr>
- <th class="bold rightBorder">{{ testset.getName }}</th>
- {% for key, buildKey in buildKeys %}
- <th class="center">
- {% if buildKey|length > 6 %}
- <span class="clickOnTouch" data-toggle="tooltip" data-placement="top"
- title="{{ buildKey }}">{{ buildKey|slice(0, 4) }}...
- </span>
- {% else %}
- {{ buildKey }}
- {% endif %}
- <br>
- <span class="gray"><small>{{ dates[key]|date("m-d") }}</small></span>
- </th>
- {% endfor %}
- </tr>
- </thead>
- <tbody>
- {% set confPrev = '' %}
- {% set buildKeyIndexPrinted = -1 %}
- {% set buildKeyFound = 0 %}
- {% for run in testsetRuns if run.getBranchName == branch %}
-
- {# New row for each conf #}
- {% if confPrev != run.getConfName %}
- {# Close previous row #}
- {% if confPrev != '' %}
- {# Fill empty cells at the end of the row #}
- {% for key, buildKey in buildKeys %}
- {% if key > buildKeyIndexPrinted %}
- <td></td>
+ {# Loop all the branches #}
+ {% for branch in branches %}
+
+ {# Get all build keys #}
+ {% set buildKey = '' %}
+ {% set buildKeys = [] %}
+ {% set dates = [] %}
+ {% for run in projectBuilds %}
+ {% if run.branch == branch %}
+ {% if buildKey != run.buildKey %}
+ {% set buildKey = run.buildKey %}
+ {% set buildKeys = buildKeys|merge([run.buildKey]) %}
+ {% set dates = dates|merge([run.timestamp]) %}
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+
+ {# Check if testset run for this branch #}
+ {% set testsetBranch = 0 %}
+ {% for run in testsetRuns if run.getBranchName == branch %}
+ {% set testsetBranch = 1 %}
+ {% endfor %}
+
+ {# Show branch if testset run for it #}
+ {% if testsetBranch %}
+ <div class="panel panel-info">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">{{ branch }}</h4>
+ </div>
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th class="bold rightBorder">{{ testset.getName }}</th>
+ {% for key, buildKey in buildKeys %}
+ <th class="center">
+ {% if buildKey|length > 6 %}
+ <span class="clickOnTouch" data-toggle="tooltip" data-placement="top"
+ title="{{ buildKey }}">{{ buildKey|slice(0, 4) }}...
+ </span>
+ {% else %}
+ {{ buildKey }}
{% endif %}
- {% endfor %}
- </tr>
+ <br>
+ <span class="gray"><small>{{ dates[key]|date("m-d") }}</small></span>
+ </th>
+ {% endfor %}
+ </tr>
+ </thead>
+ <tbody>
+ {% set confPrev = '' %}
+ {% set buildKeyIndexPrinted = -1 %}
+ {% set buildKeyFound = 0 %}
+ {% for run in testsetRuns if run.getBranchName == branch %}
+
+ {# New row for each conf #}
+ {% if confPrev != run.getConfName %}
+ {# Close previous row #}
+ {% if confPrev != '' %}
+ {# Fill empty cells at the end of the row #}
+ {% for key, buildKey in buildKeys %}
+ {% if key > buildKeyIndexPrinted %}
+ <td></td>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% endif %}
+ <tr>
+ <td class="rightBorder"><small>{{ run.getConfName }}</small></td>
+ {% set buildKeyIndexPrinted = -1 %}
{% endif %}
- <tr>
- <td class="rightBorder"><small>{{ run.getConfName }}</small></td>
- {% set buildKeyIndexPrinted = -1 %}
- {% endif %}
- {# Result per build key #}
- {% set buildKeyFound = 0 %}
- {% for key, buildKey in buildKeys %}
- {# Print each column only once (checked based on column index key and buildKeyFound flag) #}
- {% if key > buildKeyIndexPrinted and not buildKeyFound %}
- {% if buildKey == run.getBuildKey %}
- {# Print result #}
- {% set flaky = '' %}
- {% if run.getResult == constant('testsetRun::RESULT_SUCCESS') %}
- {% if run.getRun == 1 %}
- {% set resultIcon = 'glyphicon glyphicon-ok green' %}
+ {# Result per build key #}
+ {% set buildKeyFound = 0 %}
+ {% for key, buildKey in buildKeys %}
+ {# Print each column only once (checked based on column index key and buildKeyFound flag) #}
+ {% if key > buildKeyIndexPrinted and not buildKeyFound %}
+ {% if buildKey == run.getBuildKey %}
+ {# Print result #}
+ {% set flaky = '' %}
+ {% if run.getResult == constant('TestsetRun::RESULT_SUCCESS') %}
+ {% if run.getRun == 1 %}
+ {% set resultIcon = 'glyphicon glyphicon-ok green' %}
+ {% else %}
+ {# Flaky #}
+ {% set resultIcon = 'glyphicon glyphicon-ok-sign green' %}
+ {% set flaky = ' (on run ' ~ run.getRun ~ ' as flaky)' %}
+ {% endif %}
+ {% elseif run.getResult == constant('TestsetRun::RESULT_FAILURE') %}
+ {% set resultIcon = 'glyphicon glyphicon-remove red' %}
{% else %}
- {# Flaky #}
- {% set resultIcon = 'glyphicon glyphicon-ok-sign green' %}
- {% set flaky = ' (on run ' ~ run.getRun ~ ' as flaky)' %}
+ {% set resultIcon = '' %}
{% endif %}
- {% elseif run.getResult == constant('testsetRun::RESULT_FAILURE') %}
- {% set resultIcon = 'glyphicon glyphicon-remove red' %}
- {% else %}
- {% set resultIcon = '' %}
- {% endif %}
- {% if (run.getDuration / 10) > 60 %}
- {% set durationFormatted = ' (00:' ~ (run.getDuration/10)|date("i:s") ~ ')' %}
+ {% if (run.getDuration / 10) > 60 %}
+ {% set durationFormatted = ' (00:' ~ (run.getDuration/10)|date("i:s") ~ ')' %}
+ {% else %}
+ {% set durationFormatted = '' %}
+ {% endif %}
+ <td class="center">
+ <span class="spaceHorizontal {{ resultIcon }} clickOnTouch"
+ data-toggle="tooltip" data-placement="top" data-html="true"
+ title="<table>
+ <tr><th>Build key: </th><td>{{ buildKey }}</td></tr>
+ <tr><th>Configuration: </th><td>{{ run.getConfName }}</td></tr>
+ <tr><th>Timestamp: </th><td>{{ run.getTimestamp }}</td></tr>
+ <tr><th>Result: </th><td>{{ run.getResult }} {{ flaky }}</td></tr>
+ <tr><th>Duration: </th><td>{{ run.getDuration / 10 }} s {{ durationFormatted }}</td></tr>
+ <tr><th>Run #: </th><td>{{ run.getRun }}</td></tr>
+ <tr><th>Insignificant: </th><td>{% if run.getInsignificant %}yes{% else %}no{% endif %}</td></tr>
+ </table>">
+ </span>
+ </td>
+ {% set buildKeyFound = 1 %}
{% else %}
- {% set durationFormatted = '' %}
+ {# Print empty cell #}
+ <td></td>
{% endif %}
- <td class="center">
- <span class="spaceHorizontal {{ resultIcon }} clickOnTouch"
- data-toggle="tooltip" data-placement="top" data-html="true"
- title="<table>
- <tr><th>Build key: </th><td>{{ buildKey }}</td></tr>
- <tr><th>Configuration: </th><td>{{ run.getConfName }}</td></tr>
- <tr><th>Timestamp: </th><td>{{ run.getTimestamp }}</td></tr>
- <tr><th>Result: </th><td>{{ run.getResult }} {{ flaky }}</td></tr>
- <tr><th>Duration: </th><td>{{ run.getDuration / 10 }} s {{ durationFormatted }}</td></tr>
- <tr><th>Run #: </th><td>{{ run.getRun }}</td></tr>
- <tr><th>Insignificant: </th><td>{% if run.getInsignificant %}yes{% else %}no{% endif %}</td></tr>
- </table>">
- </span>
- </td>
- {% set buildKeyFound = 1 %}
- {% else %}
- {# Print empty cell #}
- <td></td>
+ {% set buildKeyIndexPrinted = key %}
{% endif %}
- {% set buildKeyIndexPrinted = key %}
+ {% endfor %}
+ {% set confPrev = run.getConfName %}
+ {% endfor %}
+
+ {# Close last row (also fill empty cells at the end of the row) #}
+ {% for key, buildKey in buildKeys %}
+ {% if key > buildKeyIndexPrinted %}
+ <td></td>
{% endif %}
{% endfor %}
- {% set confPrev = run.getConfName %}
- {% endfor %}
+ </tr>
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
+ {% endif %} {# testsetBranch #}
+ {% endfor %}
- {# Close last row (also fill empty cells at the end of the row) #}
- {% for key, buildKey in buildKeys %}
- {% if key > buildKeyIndexPrinted %}
- <td></td>
- {% endif %}
- {% endfor %}
- </tr>
- </tbody>
- </table>
- </div> {# /table-responsive #}
- </div> {# /panel-body #}
- </div> {# /panel... #}
- {% endif %} {# testsetBranch #}
- {% endfor %}
+ {% else %} {# runsAvailable #}
+ <div class="alert alert-danger" role="alert">
+ No test result data available for testset {{ testset.getName }} in project {{ testset.getProjectName }}!
+ </div>
+ {% endif %}
</div> {# /col... #}
</div> {# /row #}
diff --git a/non-puppet/qtmetrics2/templates/testset_project.html b/non-puppet/qtmetrics2/templates/testset_project.html
new file mode 100644
index 0000000..a4cf0fb
--- /dev/null
+++ b/non-puppet/qtmetrics2/templates/testset_project.html
@@ -0,0 +1,346 @@
+{#
+#############################################################################
+##
+## Copyright (C) 2015 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Quality Assurance module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL21$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see http://www.qt.io/terms-conditions. For further
+## information use the contact form at http://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 or version 3 as published by the Free
+## Software Foundation and appearing in the file LICENSE.LGPLv21 and
+## LICENSE.LGPLv3 included in the packaging of this file. Please review the
+## following information to ensure the GNU Lesser General Public License
+## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## As a special exception, The Qt Company gives you certain additional
+## rights. These rights are described in The Qt Company LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+/**
+ * Testset project page
+ * @version 0.1
+ * @since 30-06-2015
+ * @author Juha Sippola
+ */
+
+#}
+
+{% include "header.html" %}
+
+{# Failed/passed bar area size in px #}
+{% set BAR_AREA = 60 %}
+
+<ol class="breadcrumb">
+ {% for link in breadcrumb %}
+ <li><a href="{{ link.link }}">{{ link.name }}</a></li>
+ {% endfor %}
+ <li class="active">{{ project }}</li>
+</ol>
+
+<div class="container-fluid">
+ <div class="row">
+
+ <div class="col-sm-12 col-md-12 main">
+
+ {# Check if any runs available #}
+ {% set runsAvailable = 0 %}
+ {% for run in confBuilds %}
+ {% set runsAvailable = 1 %}
+ {% endfor %}
+
+ {##### Title #####}
+
+ <h1 class="page-header">
+ {{ project }}
+ <button type="button" class="btn btn-xs btn-info" data-toggle="collapse" data-target="#info" aria-expanded="false" aria-controls="info">
+ <span class="glyphicon glyphicon-info-sign"></span>
+ </button>
+ <small>{{ refreshed }}</small>
+ </h1>
+
+ {##### Info well #####}
+
+ <div class="collapse" id="info">
+ <div class="well infoWell">
+ <span class="glyphicon glyphicon-info-sign"></span> <strong>Testset project</strong><br>
+ <ul>
+ <li><strong>Latest Status</strong> shows the status based on the results of {{ project }}
+ testsets in the latest <strong>{{ masterProject }} {{ masterState }}</strong> builds
+ in any configuration across all branches.</li>
+ <li><strong>Results in Branches</strong> shows the results of {{ project }} testsets by branch
+ and their configuration in <strong>{{ masterProject }} {{ masterState }}</strong> builds
+ ( <button type="button" class="btn btn-xs btn-success"><span class="badge">n</span></button> = all n testsets passed,
+ <button type="button" class="btn btn-xs btn-danger"><span class="badge">n</span></button> = n testsets failed);
+ details are available as tooltip on result icon.</li>
+ </ul>
+ </div>
+ </div>
+
+ {% if runsAvailable %}
+
+ {##### Latest Status #####}
+
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Latest Status</h4>
+ </div>
+
+ {# Get branches #}
+ {% set branches = [] %}
+ {% for run in latestTestsetRuns %}
+ {% if run.branch not in branches %}
+ {% set branches = branches|merge([run.branch]) %}
+ {% endif %}
+ {% endfor %}
+
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th class="rightBorder">testset project</th>
+ {% for branch in branches %}
+ <th class="center">{{ branch }}<br>
+ <small>failed <span class ="gray">(total)</span></small>
+ </th>
+ <th class="showInLargeDisplay"></th>
+ {% endfor %}
+ </tr>
+ </thead>
+ <tbody>
+ {# Calculate max failed result count for the bar #}
+ {% set maxCount = 1 %}
+ {% for run in latestTestsetRuns %}
+ {% if run.failed > maxCount %}
+ {% set maxCount = run.failed %}
+ {% endif %}
+ {% endfor %}
+
+ <tr>
+ {# Project name #}
+ <td class="rightBorder">{{ project }}</td>
+
+ {# Result (by branch) #}
+ {% for branch in branches %}
+ {% for run in latestTestsetRuns if project == run.project and branch == run.branch %}
+
+ {# Show results #}
+ {% set failed = run.failed %}
+ {% set passed = run.passed %}
+ {% set total = passed + failed %}
+ <td class="center">{{ failed }}<span class ="gray"> ({{ total }})</span></td>
+
+ {# Show results as bars (scaled to BAR_AREA px) #}
+ {% set failedBar = ((BAR_AREA/maxCount) * failed)|round(0, 'floor') %}
+ {% if (failed > 0) and (failedBar == 0) %}
+ {% set failedBar = 1 %}
+ {% endif %}
+ {% if failed == 0 %}
+ {% set failed = '' %}
+ {% endif %}
+ {% if (passed > 0) and (failed == 0) %}
+ {% set passedBar = BAR_AREA %}
+ {% else %}
+ {% set passed = '' %}
+ {% endif %}
+ <td class="center showInLargeDisplay">
+ <div>
+ <div class="floatLeft redBackground" style="width: {{ failedBar }}px">{{ failed }}</div>
+ <div class="floatLeft greenBackground" style="width: {{ passedBar }}px">{{ passed }}</div>
+ </div>
+ </td>
+ {% else %}
+ <td></td>
+ {% endfor %}
+ {% endfor %}
+ </tr>
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
+
+ {##### Results in Branches #####}
+
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Results in Branches</h4>
+ </div>
+ </div>
+
+ {# Get branches #}
+ {% set branches = [] %}
+ {% for run in projectBuilds %}
+ {% if run.branch not in branches %}
+ {% set branches = branches|merge([run.branch]) %}
+ {% endif %}
+ {% endfor %}
+
+ {# Loop all the branches #}
+ {% for branch in branches %}
+
+ {# Get all build keys #}
+ {% set buildKey = '' %}
+ {% set buildKeys = [] %}
+ {% set dates = [] %}
+ {% for run in projectBuilds %}
+ {% if run.branch == branch %}
+ {% if buildKey != run.buildKey %}
+ {% set buildKey = run.buildKey %}
+ {% set buildKeys = buildKeys|merge([run.buildKey]) %}
+ {% set dates = dates|merge([run.timestamp]) %}
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+
+ {# Check if testsets run for this branch #}
+ {% set testsetBranch = 0 %}
+ {% for run in confBuilds if run.branch == branch %}
+ {% set testsetBranch = 1 %}
+ {% endfor %}
+
+ {# Show branch if testsets run for it #}
+ {% if testsetBranch %}
+ <div class="panel panel-info">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">{{ branch }}</h4>
+ </div>
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th class="bold rightBorder">{{ project }}</th>
+ {% for key, buildKey in buildKeys %}
+ <th class="center">
+ {% if buildKey|length > 6 %}
+ <span class="clickOnTouch" data-toggle="tooltip" data-placement="top"
+ title="{{ buildKey }}">{{ buildKey|slice(0, 4) }}...
+ </span>
+ {% else %}
+ {{ buildKey }}
+ {% endif %}
+ <br>
+ <span class="gray"><small>{{ dates[key]|date("m-d") }}</small></span>
+ </th>
+ {% endfor %}
+ </tr>
+ </thead>
+ <tbody>
+ {% set confPrev = '' %}
+ {% set buildKeyIndexPrinted = -1 %}
+ {% set buildKeyFound = 0 %}
+ {% for run in confBuilds if run.branch == branch %}
+
+ {# New row for each conf #}
+ {% if confPrev != run.conf %}
+ {# Close previous row #}
+ {% if confPrev != '' %}
+ {# Fill empty cells at the end of the row #}
+ {% for key, buildKey in buildKeys %}
+ {% if key > buildKeyIndexPrinted %}
+ <td></td>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% endif %}
+ <tr>
+ <td class="rightBorder"><small>{{ run.conf }}</small></td>
+ {% set buildKeyIndexPrinted = -1 %}
+ {% endif %}
+
+ {# Result per build key #}
+ {% set buildKeyFound = 0 %}
+ {% for key, buildKey in buildKeys %}
+ {# Print each column only once (checked based on column index key and buildKeyFound flag) #}
+ {% if key > buildKeyIndexPrinted and not buildKeyFound %}
+ {% if buildKey == run.buildKey %}
+ {# Print results #}
+ <td class="center">
+ {% if (run.failed + run.ifailed) > 0 %}
+ <button type="button" class="btn btn-xs btn-danger clickOnTouch"
+ data-toggle="tooltip" data-placement="top" data-html="true"
+ title="<table>
+ <tr><th>Build key: </th><td>{{ buildKey }}</td></tr>
+ <tr><th>Configuration: </th><td>{{ run.conf }}</td></tr>
+ <tr><th>Testsets passed: </th><td>{{ run.passed }}</td></tr>
+ <tr><th>Testsets passed (insignificant): </th><td>{{ run.ipassed }}</td></tr>
+ <tr><th>Testsets failed: </th><td>{{ run.failed }}</td></tr>
+ <tr><th>Testsets failed (insignificant): </th><td>{{ run.ifailed }}</td></tr>
+ </table>">
+ <span class="badge">{{ run.failed + run.ifailed }}</span>
+ </button>
+ {% elseif (run.passed + run.ipassed) > 0 %}
+ <button type="button" class="btn btn-xs btn-success clickOnTouch"
+ data-toggle="tooltip" data-placement="top" data-html="true"
+ title="<table>
+ <tr><th>Build key: </th><td>{{ buildKey }}</td></tr>
+ <tr><th>Configuration: </th><td>{{ run.conf }}</td></tr>
+ <tr><th>Testsets passed: </th><td>{{ run.passed }}</td></tr>
+ <tr><th>Testsets passed (insignificant): </th><td>{{ run.ipassed }}</td></tr>
+ <tr><th>Testsets failed: </th><td>{{ run.failed }}</td></tr>
+ <tr><th>Testsets failed (insignificant): </th><td>{{ run.ifailed }}</td></tr>
+ </table>">
+ <span class="badge"><small>{{ run.passed + run.ipassed }}</small></span>
+ </button>
+ {% endif %}
+ </td>
+ {% set buildKeyFound = 1 %}
+ {% else %}
+ {# Print empty cell #}
+ <td></td>
+ {% endif %}
+ {% set buildKeyIndexPrinted = key %}
+ {% endif %}
+ {% endfor %}
+ {% set confPrev = run.conf %}
+ {% endfor %}
+
+ {# Close last row (also fill empty cells at the end of the row) #}
+ {% for key, buildKey in buildKeys %}
+ {% if key > buildKeyIndexPrinted %}
+ <td></td>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
+ {% endif %} {# testsetBranch #}
+ {% endfor %}
+
+ {% else %} {# runsAvailable #}
+ <div class="alert alert-danger" role="alert">
+ No test result data available for project {{ project }}!
+ </div>
+ {% endif %}
+
+ </div> {# /col... #}
+ </div> {# /row #}
+
+</div> {# /container-fluid #}
+
+{% include "footer.html" %}
+
+{# Local scripts for this page #}
+<script src="scripts/tooltip.js"></script>
+
+{% include "close.html" %}