summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuha Sippola <juhasippola@outlook.com>2015-07-01 15:54:56 +0300
committerTony Sarajärvi <tony.sarajarvi@theqtcompany.com>2015-09-16 07:32:01 +0000
commit17114a51b5015b5af18818c30344bbe5365d7a6c (patch)
tree529f1fbdfea6c4279510bebf5f350e3033f0f673
parent5a2c85839bfb064c7d8faa79ee2d00bb51458e87 (diff)
Qt Metrics 2 (v0.6): Testset page
Implemented the Results in Branches section into testset page. Changed testset URL to include its project to identify testsets with same name clearly. Change-Id: I4ffd7ec6bbbc473af0d742e808568ff7d3b273da Reviewed-by: Tony Sarajärvi <tony.sarajarvi@theqtcompany.com>
-rw-r--r--non-puppet/qtmetrics2/index.php29
-rw-r--r--non-puppet/qtmetrics2/scripts/tooltip.js63
-rw-r--r--non-puppet/qtmetrics2/src/Database.php105
-rw-r--r--non-puppet/qtmetrics2/src/Factory.php84
-rw-r--r--non-puppet/qtmetrics2/src/TestsetRun.php38
-rw-r--r--non-puppet/qtmetrics2/src/test/DatabaseTest.php98
-rw-r--r--non-puppet/qtmetrics2/src/test/FactoryTest.php41
-rw-r--r--non-puppet/qtmetrics2/styles/qtmetrics.css26
-rw-r--r--non-puppet/qtmetrics2/templates/about.html6
-rw-r--r--non-puppet/qtmetrics2/templates/testset.html288
-rw-r--r--non-puppet/qtmetrics2/templates/testsets_flaky.html112
-rw-r--r--non-puppet/qtmetrics2/templates/testsets_top.html146
-rw-r--r--non-puppet/qtmetrics2/testset_search.php10
13 files changed, 811 insertions, 235 deletions
diff --git a/non-puppet/qtmetrics2/index.php b/non-puppet/qtmetrics2/index.php
index c17924b..746ffbe 100644
--- a/non-puppet/qtmetrics2/index.php
+++ b/non-puppet/qtmetrics2/index.php
@@ -34,8 +34,8 @@
/**
* Qt Metrics API
- * @version 0.4
- * @since 18-06-2015
+ * @version 0.5
+ * @since 25-06-2015
* @author Juha Sippola
*/
@@ -133,12 +133,13 @@ $app->get('/test/flaky', function() use($app)
});
/**
- * UI route: /testset/:testset (GET)
+ * UI route: /testset/:testset/:project (GET)
*/
-$app->get('/testset/:testset', function($testset) use($app)
+$app->get('/testset/:testset/:project', function($testset, $project) use($app)
{
$testset = strip_tags($testset);
+ $project = strip_tags($project);
$ini = Factory::conf();
$breadcrumb = array(
array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root'))
@@ -150,10 +151,21 @@ $app->get('/testset/:testset', function($testset) use($app)
'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
'lastDaysFailures' => $ini['top_failures_last_days'],
'lastDaysFlaky' => $ini['flaky_testsets_last_days'],
+ 'sinceDateFailures' => Factory::getSinceDate(intval($ini['top_failures_last_days']) - 1),
+ 'sinceDateFlaky' => Factory::getSinceDate(intval($ini['flaky_testsets_last_days']) - 1),
'masterProject' => $ini['master_build_project'],
'masterState' => $ini['master_build_state'],
- 'testsets' => Factory::createTestset(
+ 'projectBuilds' => Factory::db()->getProjectBuildsByBranch(
+ $ini['master_build_project'],
+ $ini['master_build_state']),
+ 'testset' => Factory::createTestset(
+ $testset,
+ $project,
+ $ini['master_build_project'],
+ $ini['master_build_state']), // managed as object
+ 'testsetRuns' => Factory::createTestsetRuns(
$testset,
+ $project,
$ini['master_build_project'],
$ini['master_build_state']) // managed as objects
));
@@ -164,7 +176,7 @@ $app->get('/testset/:testset', function($testset) use($app)
));
$app->response()->status(404);
}
-});
+})->name('testsetProject');
$app->run();
@@ -180,7 +192,10 @@ if (isset($_POST["testsetInputSubmit"])) {
exit();
}
if (isset($_POST["testsetInputValue"])) {
- header('Location: ' . Slim\Slim::getInstance()->urlFor('root') . 'testset/' . htmlspecialchars($_POST['testsetInputValue']));
+ $string = explode(' (in ', htmlspecialchars($_POST['testsetInputValue'])); // the separator must match with that used in testset_search.php
+ $testset = $string[0];
+ $project = str_replace(')', '', $string[1]);
+ header('Location: ' . Slim\Slim::getInstance()->urlFor('root') . 'testset/' . $testset . '/' . $project);
exit();
}
}
diff --git a/non-puppet/qtmetrics2/scripts/tooltip.js b/non-puppet/qtmetrics2/scripts/tooltip.js
new file mode 100644
index 0000000..78dcfb9
--- /dev/null
+++ b/non-puppet/qtmetrics2/scripts/tooltip.js
@@ -0,0 +1,63 @@
+/*
+#############################################################################
+##
+## 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$
+##
+#############################################################################
+
+/**
+ * Initialize Bootstrap tooltips
+ * @version 0.1
+ * @since 26-06-2015
+ * @author Juha Sippola
+ */
+
+$(function () {
+
+ // Set tooltip activation to click on touch devices (and hover on others)
+ var is_touch_device = ("ontouchstart" in window) || window.DocumentTouch && document instanceof DocumentTouch;
+ $(".clickOnTouch").tooltip({
+ trigger: is_touch_device ? "click" : "hover"
+ });
+
+ // Bootstrap tooltip
+ $('[data-toggle="tooltip"]').tooltip();
+
+ // Hide clicked tooltip
+ $('body').on('click', function (e) {
+ $('[data-toggle="tooltip"]').each(function () {
+ //the 'is' for element that triggered the tooltip
+ if (!$(this).is(e.target) && $(this).has(e.target).length === 0) {
+ $(this).tooltip('hide');
+ }
+ });
+ });
+
+});
diff --git a/non-puppet/qtmetrics2/src/Database.php b/non-puppet/qtmetrics2/src/Database.php
index 9f9999c..efc87c3 100644
--- a/non-puppet/qtmetrics2/src/Database.php
+++ b/non-puppet/qtmetrics2/src/Database.php
@@ -34,8 +34,8 @@
/**
* Database class
- * @version 0.3
- * @since 16-06-2015
+ * @version 0.4
+ * @since 22-06-2015
* @author Juha Sippola
*/
@@ -114,16 +114,20 @@ class Database {
{
$result = array();
$query = $this->db->prepare("
- SELECT DISTINCT name
+ SELECT testset.name AS testset, project.name AS project
FROM testset
- WHERE name LIKE ?
- ORDER BY name;
+ INNER JOIN project ON testset.project_id = project.id
+ WHERE testset.name LIKE ?
+ ORDER BY testset.name;
");
$query->execute(array(
'%' . $filter . '%'
));
while($row = $query->fetch(PDO::FETCH_ASSOC)) {
- $result[] = array('name' => $row['name']);
+ $result[] = array(
+ 'name' => $row['testset'],
+ 'project' => $row['project']
+ );
}
return $result;
}
@@ -499,6 +503,95 @@ class Database {
}
/**
+ * Get project build keys and timestamps by branch
+ * @param string $runProject
+ * @param string $runState
+ * @return array (string branch, string build_key, string timestamp)
+ */
+ public function getProjectBuildsByBranch($runProject, $runState)
+ {
+ $result = array();
+ $query = $this->db->prepare("
+ SELECT
+ branch.name AS branch,
+ project_run.build_key,
+ project_run.timestamp
+ FROM project_run
+ 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, project_run.timestamp DESC;
+ ");
+ $query->execute(array(
+ $runProject,
+ $runState
+ ));
+ while($row = $query->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = array(
+ 'branch' => $row['branch'],
+ 'buildKey' => $row['build_key'],
+ 'timestamp' => $row['timestamp']
+ );
+ }
+ 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)
+ */
+ public function getTestsetResultsByBranchConf($testset, $testsetProject, $runProject, $runState)
+ {
+ $result = array();
+ $query = $this->db->prepare("
+ SELECT
+ branch.name AS branch,
+ conf.name AS conf,
+ project_run.build_key,
+ testset_run.result,
+ project_run.timestamp,
+ testset_run.duration,
+ testset_run.run
+ 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
+ testset.name = ? AND
+ project.name = ? AND
+ 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.name, project_run.timestamp DESC;
+ ");
+ $query->execute(array(
+ $testset,
+ $testsetProject,
+ $runProject,
+ $runState
+ ));
+ while($row = $query->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = array(
+ 'branch' => $row['branch'],
+ 'conf' => $row['conf'],
+ 'buildKey' => $row['build_key'],
+ 'result' => $row['result'],
+ 'timestamp' => $row['timestamp'],
+ 'duration' => $row['duration'],
+ 'run' => $row['run']
+ );
+ }
+ 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 ce1751e..0870f8c 100644
--- a/non-puppet/qtmetrics2/src/Factory.php
+++ b/non-puppet/qtmetrics2/src/Factory.php
@@ -34,8 +34,8 @@
/**
* Factory class
- * @version 0.2
- * @since 12-06-2015
+ * @version 0.3
+ * @since 23-06-2015
* @author Juha Sippola
*/
@@ -166,7 +166,7 @@ class Factory {
$objects = array();
$ini = self::conf();
// Failure result list (from specified builds only)
- if ($listType == self::LIST_FAILURES) {
+ if ($listType === self::LIST_FAILURES) {
$days = intval($ini['top_failures_last_days']) - 1;
$since = self::getSinceDate($days);
$limit = intval($ini['top_failures_n']);
@@ -179,7 +179,7 @@ class Factory {
}
}
// Flaky list (all builds)
- if ($listType == self::LIST_FLAKY) {
+ if ($listType === self::LIST_FLAKY) {
$days = intval($ini['flaky_testsets_last_days']) - 1;
$since = self::getSinceDate($days);
$limit = intval($ini['flaky_testsets_n']);
@@ -194,39 +194,65 @@ class Factory {
}
/**
- * Create Testset object(s) for those in database
- * If several testsets with same name in different projects, all are created
+ * Create Testset object for that in database
* Counts are limited by date (since) and length, failure result counts for specified builds only
* @param string $name
+ * @param string $testsetProject
* @param string $runProject
* @param string $runState
* @return array Testset object(s)
*/
- public static function createTestset($name, $runProject, $runState)
+ public static function createTestset($name, $testsetProject, $runProject, $runState)
{
- $objects = array();
$ini = self::conf();
- // Get testset(s)
- $dbTestset = self::db()->getTestsetProject($name);
- foreach($dbTestset as $testset) {
- $obj = new Testset($testset['name'], $testset['project']);
- $obj->setStatus($runProject, $runState);
- // Failure result counts (from specified builds only)
- $days = intval($ini['top_failures_last_days']) - 1;
- $since = self::getSinceDate($days);
- $dbTestsetDetails = self::db()->getTestsetResultCounts($name, $runProject, $runState, $since);
- foreach($dbTestsetDetails as $detail) {
- if ($testset['project'] == $detail['project'])
- $obj->setTestsetResultCounts($detail['passed'], $detail['failed']);
- }
- // Flaky counts (all builds)
- $days = intval($ini['flaky_testsets_last_days']) - 1;
- $since = self::getSinceDate($days);
- $dbTestsetDetails = self::db()->getTestsetFlakyCounts($name, $since);
- foreach($dbTestsetDetails as $detail) {
- if ($testset['project'] == $detail['project'])
- $obj->setTestsetFlakyCounts($detail['flaky'], $detail['total']);
- }
+ $obj = new Testset($name, $testsetProject);
+ $obj->setStatus($runProject, $runState);
+ // Failure result counts (from specified builds only)
+ $days = intval($ini['top_failures_last_days']) - 1;
+ $since = self::getSinceDate($days);
+ $dbTestsetDetails = self::db()->getTestsetResultCounts($name, $runProject, $runState, $since);
+ foreach($dbTestsetDetails as $detail) {
+ if ($detail['project'] === $testsetProject)
+ $obj->setTestsetResultCounts($detail['passed'], $detail['failed']);
+ }
+ // Flaky counts (all builds)
+ $days = intval($ini['flaky_testsets_last_days']) - 1;
+ $since = self::getSinceDate($days);
+ $dbTestsetDetails = self::db()->getTestsetFlakyCounts($name, $since);
+ foreach($dbTestsetDetails as $detail) {
+ if ($detail['project'] === $testsetProject)
+ $obj->setTestsetFlakyCounts($detail['flaky'], $detail['total']);
+ }
+ return $obj;
+ }
+
+ /**
+ * Create TestsetRun objects for those in database
+ * @param string $testset
+ * @param string $testsetProject
+ * @param string $runProject
+ * @param string $runState
+ * @return array TestsetRun objects
+ */
+ public static function createTestsetRuns($testset, $testsetProject, $runProject, $runState)
+ {
+ $objects = array();
+ $dbEntries = self::db()->getTestsetResultsByBranchConf($testset, $testsetProject, $runProject, $runState);
+ foreach($dbEntries as $entry) {
+ $obj = new TestsetRun(
+ $testset,
+ $testsetProject,
+ $runProject,
+ $entry['branch'],
+ $runState,
+ $entry['buildKey'],
+ $entry['conf'],
+ $entry['run'],
+ TestsetRun::stripResult($entry['result']),
+ TestsetRun::isInsignificant($entry['result']),
+ $entry['timestamp'],
+ $entry['duration']
+ );
$objects[] = $obj;
}
return $objects;
diff --git a/non-puppet/qtmetrics2/src/TestsetRun.php b/non-puppet/qtmetrics2/src/TestsetRun.php
index 9f5f198..f733712 100644
--- a/non-puppet/qtmetrics2/src/TestsetRun.php
+++ b/non-puppet/qtmetrics2/src/TestsetRun.php
@@ -34,8 +34,8 @@
/**
* TestsetRun class
- * @version 0.2
- * @since 12-06-2015
+ * @version 0.3
+ * @since 23-06-2015
* @author Juha Sippola
*/
@@ -56,13 +56,19 @@ class TestsetRun extends ProjectRun {
private $name;
/**
+ * Testset project name.
+ * @var string
+ */
+ private $testsetProjectName;
+
+ /**
* Configuration name.
* @var string
*/
private $confName;
/**
- * Run number (a failed test is repeated once).
+ * Run number (a failed test is repeated).
* @var int
*/
private $run;
@@ -77,6 +83,7 @@ class TestsetRun extends ProjectRun {
* TestsetRun constructor.
* TestsetRun include the result in the project configuration build
* @param string $testsetName
+ * @param string $testsetProjectName
* @param string $projectName
* @param string $branchName
* @param string $stateName
@@ -86,11 +93,12 @@ class TestsetRun extends ProjectRun {
* @param string $result (plain result without any possible flags)
* @param bool $insignificant (true = insignificant)
* @param int $timestamp
- * @param int $duration
+ * @param int $duration (in deciseconds)
*/
- public function __construct($name, $projectName, $branchName, $stateName, $buildKey, $confName, $run, $result, $insignificant, $timestamp, $duration) {
+ public function __construct($name, $testsetProjectName, $projectName, $branchName, $stateName, $buildKey, $confName, $run, $result, $insignificant, $timestamp, $duration) {
parent::__construct($projectName, $branchName, $stateName, $buildKey, $result, $timestamp, $duration);
$this->name = $name;
+ $this->$testsetProjectName = $testsetProjectName;
$this->confName = $confName;
$this->run = $run;
$this->insignificant = $insignificant;
@@ -106,6 +114,24 @@ class TestsetRun extends ProjectRun {
}
/**
+ * Get configuration name.
+ * @return string
+ */
+ public function getConfName()
+ {
+ return $this->confName;
+ }
+
+ /**
+ * Get run number.
+ * @return int
+ */
+ public function getRun()
+ {
+ return $this->run;
+ }
+
+ /**
* Get insignificance flag.
* @return bool (true = insignificant)
*/
@@ -134,7 +160,7 @@ class TestsetRun extends ProjectRun {
public static function isInsignificant($resultString)
{
$flag = false;
- if (strpos($resultString, 'i') == 0) // begins with 'i'
+ if (strpos($resultString, 'i') === 0) // begins with 'i'
$flag = true;
return $flag;
}
diff --git a/non-puppet/qtmetrics2/src/test/DatabaseTest.php b/non-puppet/qtmetrics2/src/test/DatabaseTest.php
index 98b854c..afb6671 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.3
- * @since 15-06-2015
+ * @version 0.4
+ * @since 23-06-2015
* @author Juha Sippola
*/
@@ -125,6 +125,10 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
$db = Factory::db();
$result = $db->getTestsetsFiltered($filter);
$this->assertGreaterThanOrEqual($exp_match_count_min, count($result));
+ foreach($result as $row) {
+ $this->assertArrayHasKey('name', $row);
+ $this->assertArrayHasKey('project', $row);
+ }
}
public function testGetTestsetsFilteredData()
{
@@ -180,9 +184,9 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
foreach($result as $row) {
$this->assertArrayHasKey('os', $row);
$this->assertArrayHasKey('os_version', $row);
- if ($row['os'] == $exp_os)
+ if ($row['os'] === $exp_os)
$osCount++;
- if ($row['os_version'] == $exp_os_version)
+ if ($row['os_version'] === $exp_os_version)
$versionCount++;
}
$this->assertGreaterThanOrEqual($exp_count_min, $osCount);
@@ -208,7 +212,7 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
$result = $db->getLatestProjectBranchBuildKeys($project, $state);
$this->assertNotEmpty($result);
foreach($result as $row) {
- if ($row['name'] == $exp_branch) {
+ if ($row['name'] === $exp_branch) {
$this->assertArrayHasKey('name', $row);
$this->assertArrayHasKey('key', $row);
$this->assertEquals($exp_build_key, $row['key']);
@@ -456,6 +460,90 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test getProjectBuildsByBranch
+ * @dataProvider testGetProjectBuildsByBranchData
+ */
+ public function testGetProjectBuildsByBranch($runProject, $runState, $exp_branch, $exp_key, $has_data)
+ {
+ $branches = array();
+ $keys = array();
+ $db = Factory::db();
+ $result = $db->getProjectBuildsByBranch($runProject, $runState);
+ foreach($result as $row) {
+ $this->assertArrayHasKey('branch', $row);
+ $this->assertArrayHasKey('buildKey', $row);
+ $this->assertArrayHasKey('timestamp', $row);
+ $branches[] = $row['branch'];
+ $keys[] = $row['buildKey'];
+ }
+ if ($has_data) {
+ $this->assertNotEmpty($result);
+ $this->assertContains($exp_branch, $branches);
+ $this->assertContains($exp_key, $keys);
+ } else {
+ $this->assertEmpty($result);
+ }
+ }
+ public function testGetProjectBuildsByBranchData()
+ {
+ return array(
+ array('Qt5', 'state', 'dev', '1023', 1),
+ array('Qt5', 'state', 'stable', '1348', 1),
+ array('Qt5', 'state', 'stable', '1348', 1),
+ array('Qt5', 'state', 'stable', '1348', 1),
+ array('Qt5', 'state', 'dev', 'BuildKeyInStringFormat12345', 1),
+ array('Qt5', 'invalid', '', '', 0)
+ );
+ }
+
+ /**
+ * Test getTestsetResultsByBranchConf
+ * @dataProvider testGetTestsetResultsByBranchConfData
+ */
+ public function testGetTestsetResultsByBranchConf($testset, $testsetProject, $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->getTestsetResultsByBranchConf($testset, $testsetProject, $runProject, $runState);
+ foreach($result as $row) {
+ $this->assertArrayHasKey('branch', $row);
+ $this->assertArrayHasKey('conf', $row);
+ $this->assertArrayHasKey('buildKey', $row);
+ $this->assertArrayHasKey('result', $row);
+ $this->assertArrayHasKey('timestamp', $row);
+ $this->assertArrayHasKey('duration', $row);
+ $this->assertArrayHasKey('run', $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 testGetTestsetResultsByBranchConfData()
+ {
+ return array(
+ array('tst_qftp', 'Qt5', 'Qt5', 'state', '', '', '', '', 0),
+ array('tst_qftp', 'QtBase', 'Qt5', 'state', 'dev', 'linux-g++_developer-build_qtnamespace_qtlibinfix_Ubuntu_11.10_x64', '1023', 'ifailed', 1),
+ array('tst_qftp', 'QtBase', 'Qt5', 'state', 'stable', 'win32-msvc2010_developer-build_angle_Windows_7', '1348', 'ipassed', 1),
+ array('tst_qfont', 'QtBase', 'Qt5', 'state', 'stable', 'macx-clang_developer-build_OSX_10.8', '1348', 'failed', 1),
+ array('tst_qfont', 'QtBase', 'Qt5', 'state', 'stable', 'win32-msvc2010_developer-build_angle_Windows_7', '1348', 'passed', 1),
+ array('tst_qfont', 'QtBase', 'Qt5', 'state', 'dev', 'linux-g++-32_developer-build_Ubuntu_10.04_x86', 'BuildKeyInStringFormat12345', 'failed', 1)
+ );
+ }
+
+ /**
* Test getDbRefreshed
*/
public function testGetDbRefreshed()
diff --git a/non-puppet/qtmetrics2/src/test/FactoryTest.php b/non-puppet/qtmetrics2/src/test/FactoryTest.php
index 7bde27d..5f1028a 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.2
- * @since 12-06-2015
+ * @version 0.3
+ * @since 23-06-2015
* @author Juha Sippola
*/
@@ -111,11 +111,11 @@ class FactoryTest extends PHPUnit_Framework_TestCase
public function testGetTestsetsFilteredData()
{
return array(
- array('', 3), // test data includes three testsets
- array('f', 3), // all
- array('ft', 2), // tst_qftp and tst_networkselftest
- array('ftp', 1), // tst_qftp
- array('tst_qftp', 1),
+ array('', 4), // test data includes four testsets
+ array('f', 4), // all
+ array('ft', 3), // tst_qftp (twice) and tst_networkselftest
+ array('ftp', 2), // tst_qftp (twice)
+ array('tst_qftp', 2),
array('tst_qfont', 1),
array('tst_qfon', 1),
array('tst_qfontt', 0),
@@ -133,7 +133,7 @@ class FactoryTest extends PHPUnit_Framework_TestCase
$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
+ if ($project->getName() === $runProject) { // check only the projects with project_run data
$this->assertNotEmpty($project->getStatus());
}
}
@@ -192,12 +192,12 @@ class FactoryTest extends PHPUnit_Framework_TestCase
* Test createTestset
* @dataProvider testCreateTestsetData
*/
- public function testCreateTestset($testset, $project, $runProject, $runState)
+ public function testCreateTestset($name, $project, $runProject, $runState)
{
- $testsets = Factory::createTestset($testset, $runProject, $runState);
+ $testsets = Factory::createTestset($name, $project, $runProject, $runState);
foreach($testsets as $testset) {
$this->assertTrue($testset instanceof Testset);
- if ($testset->getProjectName() == $project) {
+ if ($testset->getProjectName() === $project) {
$status = $testset->getStatus();
$this->assertNotEmpty($status);
$result = $testset->getTestsetResultCounts();
@@ -220,6 +220,25 @@ class FactoryTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test createTestsetRuns
+ * @dataProvider testCreateTestsetRunsData
+ */
+ public function testCreateTestsetRuns($name, $projectName, $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);
+ foreach($runs as $run) {
+ $this->assertTrue($run instanceof TestsetRun);
+ }
+ }
+ public function testCreateTestsetRunsData()
+ {
+ return array(
+ array('tst_qftp', 'qtbase', 'Qt5', 'stable', 'state', '1348', 'win64-msvc2012_developer-build_qtnamespace_Windows_8', 5, 'failed', true, '28.5.2013 0:54', 8130),
+ array('tst_qfont', 'qtbase', 'Qt5', 'dev', 'state', 'BuildKeyInStringFormat12345', 'linux-g++-32_developer-build_Ubuntu_10.04_x86', 1, 'failed', false, '28.5.2013 0:54', 8130)
+ );
+ }
+
+ /**
* Test getSinceDate
* @dataProvider testGetSinceDateData
*/
diff --git a/non-puppet/qtmetrics2/styles/qtmetrics.css b/non-puppet/qtmetrics2/styles/qtmetrics.css
index 8c01db0..0d47cc8 100644
--- a/non-puppet/qtmetrics2/styles/qtmetrics.css
+++ b/non-puppet/qtmetrics2/styles/qtmetrics.css
@@ -35,8 +35,8 @@
/**
* Qt Metrics style sheet
- * @version 0.1
- * @since 04-06-2015
+ * @version 0.2
+ * @since 22-06-2015
* @author Juha Sippola
*/
@@ -53,7 +53,7 @@
* Load home page image (from www.qt.io) with text color adjustments in tablets and bigger devices only (typically using faster connection)
*/
-@media screen and (min-width: 720px) {
+@media screen and (min-width: 768px) {
.jumbotron {
background-image: url("https://d3hp9ud7yvwzy0.cloudfront.net/wp-content/uploads/2014/06/Qt-in-nutshell-hero2.jpg");
background-size: cover;
@@ -77,7 +77,7 @@
* Include UI elements and behavior in tablets and bigger devices only (typically using faster connection)
*/
-@media screen and (max-width: 720px) {
+@media screen and (max-width: 768px) {
.showInLargeDisplay {
display: none;
}
@@ -92,6 +92,16 @@
}
/*
+ * Make the tooltip align left, respect new lines and prevent text from wrapping
+ */
+.tooltip-inner {
+ text-align: left;
+ white-space: pre;
+ max-width: none;
+ background-color: #12293E;
+}
+
+/*
* Make space horizontally outside an element
*/
@@ -131,6 +141,10 @@
border-left: 2px solid lightgrey;
}
+.rightBorder {
+ border-right: 2px solid lightgrey;
+}
+
.center {
text-align: center
}
@@ -170,3 +184,7 @@
.textSmall {
font-size: small;
}
+
+.bold {
+ font-weight: bold;
+}
diff --git a/non-puppet/qtmetrics2/templates/about.html b/non-puppet/qtmetrics2/templates/about.html
index c893598..1ba66fc 100644
--- a/non-puppet/qtmetrics2/templates/about.html
+++ b/non-puppet/qtmetrics2/templates/about.html
@@ -34,8 +34,8 @@
/**
* About window content
- * @version 0.5
- * @since 18-06-2015
+ * @version 0.6
+ * @since 26-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.5 (18-Jun-2015)</small></p>
+<p><small>Version 0.6 (26-Jun-2015)</small></p>
diff --git a/non-puppet/qtmetrics2/templates/testset.html b/non-puppet/qtmetrics2/templates/testset.html
index c69e859..59f98e4 100644
--- a/non-puppet/qtmetrics2/templates/testset.html
+++ b/non-puppet/qtmetrics2/templates/testset.html
@@ -34,8 +34,8 @@
/**
* Testset page
- * @version 0.3
- * @since 18-06-2015
+ * @version 0.4
+ * @since 26-06-2015
* @author Juha Sippola
*/
@@ -43,23 +43,26 @@
{% include "header.html" %}
-{# testsets as Testset objects
+{# Failed/passed bar area size in px #}
+{% set BAR_AREA = 120 %}
+
+{# testset as Testset object
/**
* @var Testset[] testsets
*/
#}
-{# Get the testset name #}
-{% set testsetName = '' %}
-{% for testset in testsets %}
- {% set testsetName = testset.getName %}
-{% endfor %}
+{# testsetRuns as TestsetRun objects
+/**
+ * @var TestsetRun[] testsetRuns
+ */
+#}
<ol class="breadcrumb">
{% for link in breadcrumb %}
<li><a href="{{ link.link }}">{{ link.name }}</a></li>
{% endfor %}
- <li class="active">{{ testsetName }}</li>
+ <li class="active">{{ testset.getName }}</li>
</ol>
<div class="container-fluid">
@@ -67,14 +70,18 @@
<div class="col-sm-12 col-md-12 main">
+ {##### Title #####}
+
<h1 class="page-header">
- {{ testsetName }}
+ {{ testset.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>Testset</strong><br>
@@ -83,35 +90,54 @@
<strong>{{ masterProject }} {{ masterState }}</strong> builds across all branches
(shows failed if failed in one or in several).</li>
<li><strong>failed</strong> count shows the number of <strong>{{ masterProject }} {{ masterState }}</strong>
- builds where {{ testsetName }} failed during the last {{ lastDaysFailures }} days.</li>
+ builds where {{ testset.getName }} failed during the last {{ lastDaysFailures }} days
+ (since {{ sinceDateFailures }}).</li>
<li><strong>flaky</strong> count shows the number of <strong>all</strong> builds where
- {{ testsetName }} failed on the first run but, when rerun, it passed
- (during the last {{ lastDaysFlaky }} days).</li>
+ {{ testset.getName }} failed on the first run but, when rerun, it passed
+ (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>
</ul>
</div>
</div>
- <div class="panel-body">
- <div class="table-responsive">
- <table class="table table-striped">
- <thead>
- <tr>
- <th>testset</th>
- <th class="showInLargeDisplay">project</th>
- <th>latest result</th>
- <th class="leftBorder center">failed <span class ="gray">(total)</span></th>
- <th class="leftBorder center">flaky <span class ="gray">(total)</span></th>
- </tr>
- </thead>
- <tbody>
- {# Print testset(s) #}
- {% for testset in testsets %}
+ {##### 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>
- {# Testset name #}
- <td>{{ testset.getName }}</td>
+ <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 class="showInLargeDisplay">{{ testset.getProjectName }}</td>
+ <td>{{ testset.getProjectName }}</td>
{# Testset status according to the latest build results #}
{% if testset.getStatus == constant('testsetRun::RESULT_SUCCESS') %}
@@ -128,30 +154,208 @@
{% 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 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 %}
+ {% endif %}
+ <td class="center showInLargeDisplay">
+ {% if flaky > 0 %}
+ <div>
+ <div class="floatLeft redBackground" style="width: {{ flakyBar }}px">{{ flaky }}</div>
+ </div>
+ {% endif %}
+ </td>
</tr>
- {% endfor %}
- </tbody>
- </table>
- </div> {# /table-responsive #}
- </div> {# /panel-body #}
+ </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 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>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% 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' %}
+ {% 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 %}
+ {% set resultIcon = '' %}
+ {% endif %}
+ {% 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 %}
+ {# Print empty cell #}
+ <td></td>
+ {% endif %}
+ {% set buildKeyIndexPrinted = key %}
+ {% endif %}
+ {% 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 %}
+ </tr>
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
+ {% endif %} {# testsetBranch #}
+ {% endfor %}
</div> {# /col... #}
</div> {# /row #}
-</div> {# /container-fluid #}
-<br>
-<div class="alert alert-danger" role="alert">
- <strong>Under construction!</strong>
-</div>
+</div> {# /container-fluid #}
{% include "footer.html" %}
{# Local scripts for this page #}
-{# (none) #}
+<script src="scripts/tooltip.js"></script>
{% include "close.html" %}
diff --git a/non-puppet/qtmetrics2/templates/testsets_flaky.html b/non-puppet/qtmetrics2/templates/testsets_flaky.html
index 9baa9f2..018881f 100644
--- a/non-puppet/qtmetrics2/templates/testsets_flaky.html
+++ b/non-puppet/qtmetrics2/templates/testsets_flaky.html
@@ -34,8 +34,8 @@
/**
* Flaky testsets page
- * @version 0.2
- * @since 18-06-2015
+ * @version 0.3
+ * @since 24-06-2015
* @author Juha Sippola
*/
@@ -64,6 +64,8 @@
<div class="col-sm-12 col-md-12 main">
+ {##### Title #####}
+
<h1 class="page-header">
Top {{ topN }} Flaky Testsets
<button type="button" class="btn btn-xs btn-info" data-toggle="collapse" data-target="#info" aria-expanded="false" aria-controls="info">
@@ -71,7 +73,8 @@
</button>
<small>{{ refreshed }}</small>
</h1>
- <h3 class="sub-header">Last {{ lastDays }} days <small>(since {{ sinceDate }})</small></h3>
+
+ {##### Info well #####}
<div class="collapse" id="info">
<div class="well infoWell">
@@ -84,56 +87,63 @@
</div>
</div>
- <div class="panel-body">
- <div class="table-responsive">
- <table class="table table-striped">
- <thead>
- <tr>
- <th>testset</th>
- <th>project</th>
- <th class="leftBorder center">flaky <span class ="gray">(total)</span></th>
- <th class="showInLargeDisplay">flaky</th>
- </tr>
- </thead>
- <tbody>
- {# Calculate max result count for the bar #}
- {% set maxCount = 1 %}
- {% for testset in testsets %}
- {% if testset.getTestsetFlakyCounts.flaky > maxCount %}
- {% set maxCount = testset.getTestsetFlakyCounts.flaky %}
- {% endif %}
- {% endfor %}
-
- {# Print testsets #}
- {% for testset in testsets %}
- <tr>
- {# Testset name #}
- <td><a href="{{ testsetRoute }}/{{ testset.getName }}">{{ testset.getName }}</a></td>
-
- {# Project name #}
- <td>{{ testset.getProjectName }}</td>
-
- {# Show results as numbers #}
- {% set flaky = testset.getTestsetFlakyCounts.flaky %}
- {% set total = testset.getTestsetFlakyCounts.total %}
- <td class="leftBorder center">{{ flaky }}<span class ="gray"> ({{ total }})</span></td>
+ {##### Flaky list #####}
- {# 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">
- <div>
- <div class="floatLeft redBackground" style="width: {{ flakyBar }}px">&nbsp;</div>
- </div>
- </td>
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Last {{ lastDays }} days <small>(since {{ sinceDate }})</small></h4>
+ </div>
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th>testset</th>
+ <th>project</th>
+ <th class="leftBorder center">flaky <span class ="gray">(total)</span></th>
+ <th class="showInLargeDisplay">flaky</th>
</tr>
- {% endfor %}
- </tbody>
- </table>
- </div> {# /table-responsive #}
- </div> {# /panel-body #}
+ </thead>
+ <tbody>
+ {# Calculate max result count for the bar #}
+ {% set maxCount = 1 %}
+ {% for testset in testsets %}
+ {% if testset.getTestsetFlakyCounts.flaky > maxCount %}
+ {% set maxCount = testset.getTestsetFlakyCounts.flaky %}
+ {% endif %}
+ {% endfor %}
+
+ {# Print testsets #}
+ {% for testset in testsets %}
+ <tr>
+ {# Testset name #}
+ <td><a href="{{ testsetRoute }}/{{ testset.getName }}/{{ testset.getProjectName }}">{{ testset.getName }}</a></td>
+
+ {# Project name #}
+ <td>{{ testset.getProjectName }}</td>
+
+ {# Show results as numbers #}
+ {% set flaky = testset.getTestsetFlakyCounts.flaky %}
+ {% set total = testset.getTestsetFlakyCounts.total %}
+ <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">
+ <div>
+ <div class="floatLeft redBackground" style="width: {{ flakyBar }}px">&nbsp;</div>
+ </div>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
</div> {# /col... #}
</div> {# /row #}
diff --git a/non-puppet/qtmetrics2/templates/testsets_top.html b/non-puppet/qtmetrics2/templates/testsets_top.html
index aa2d864..a9abec5 100644
--- a/non-puppet/qtmetrics2/templates/testsets_top.html
+++ b/non-puppet/qtmetrics2/templates/testsets_top.html
@@ -34,8 +34,8 @@
/**
* Top failures (testsets) page
- * @version 0.3
- * @since 18-06-2015
+ * @version 0.4
+ * @since 24-06-2015
* @author Juha Sippola
*/
@@ -64,6 +64,8 @@
<div class="col-sm-12 col-md-12 main">
+ {##### Title #####}
+
<h1 class="page-header">
Top {{ topN }} Failures
<button type="button" class="btn btn-xs btn-info" data-toggle="collapse" data-target="#info" aria-expanded="false" aria-controls="info">
@@ -71,7 +73,8 @@
</button>
<small>{{ refreshed }}</small>
</h1>
- <h3 class="sub-header">Last {{ lastDays }} days <small>(since {{ sinceDate }})</small></h3>
+
+ {##### Info well #####}
<div class="collapse" id="info">
<div class="well infoWell">
@@ -86,73 +89,80 @@
</div>
</div>
- <div class="panel-body">
- <div class="table-responsive">
- <table class="table table-striped">
- <thead>
- <tr>
- <th>testset</th>
- <th class="showInLargeDisplay">project</th>
- <th>latest result</th>
- <th class="leftBorder center">failed <span class ="gray">(total)</span></th>
- <th class="showInLargeDisplay">failed + passed</th>
- </tr>
- </thead>
- <tbody>
- {# Calculate max result count for the bar #}
- {% set maxCount = 1 %}
- {% for testset in testsets %}
- {% if (testset.getTestsetResultCounts.passed + testset.getTestsetResultCounts.failed) > maxCount %}
- {% set maxCount = testset.getTestsetResultCounts.passed + testset.getTestsetResultCounts.failed %}
- {% endif %}
- {% endfor %}
-
- {# Print testsets #}
- {% for testset in testsets %}
+ {##### Top list #####}
+
+ <div class="panel panel-primary">
+ <div class="panel-heading">
+ <h4 class="panel-title bold">Last {{ lastDays }} days <small>(since {{ sinceDate }})</small></h4>
+ </div>
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped">
+ <thead>
<tr>
- {# Testset name #}
- <td><a href="{{ testsetRoute }}/{{ testset.getName }}">{{ testset.getName }}</a></td>
-
- {# Project name #}
- <td class="showInLargeDisplay">{{ 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 results as numbers #}
- {% 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 class="center showInLargeDisplay">
- <div>
- <div class="floatLeft redBackground" style="width: {{ failedBar }}px">&nbsp;</div>
- <div class="floatLeft greenBackground" style="width: {{ passedBar }}px">&nbsp;</div>
- </div>
- </td>
+ <th>testset</th>
+ <th class="showInLargeDisplay">project</th>
+ <th>latest result</th>
+ <th class="leftBorder center">failed <span class ="gray">(total)</span></th>
+ <th class="showInLargeDisplay">failed + passed</th>
</tr>
- {% endfor %}
- </tbody>
- </table>
- </div> {# /table-responsive #}
- </div> {# /panel-body #}
+ </thead>
+ <tbody>
+ {# Calculate max result count for the bar #}
+ {% set maxCount = 1 %}
+ {% for testset in testsets %}
+ {% if (testset.getTestsetResultCounts.passed + testset.getTestsetResultCounts.failed) > maxCount %}
+ {% set maxCount = testset.getTestsetResultCounts.passed + testset.getTestsetResultCounts.failed %}
+ {% endif %}
+ {% endfor %}
+
+ {# Print testsets #}
+ {% for testset in testsets %}
+ <tr>
+ {# Testset name #}
+ <td><a href="{{ testsetRoute }}/{{ testset.getName }}/{{ testset.getProjectName }}">{{ testset.getName }}</a></td>
+
+ {# Project name #}
+ <td class="showInLargeDisplay">{{ 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 results as numbers #}
+ {% 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 class="center showInLargeDisplay">
+ <div>
+ <div class="floatLeft redBackground" style="width: {{ failedBar }}px">&nbsp;</div>
+ <div class="floatLeft greenBackground" style="width: {{ passedBar }}px">&nbsp;</div>
+ </div>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div> {# /table-responsive #}
+ </div> {# /panel-body #}
+ </div> {# /panel... #}
</div> {# /col... #}
</div> {# /row #}
diff --git a/non-puppet/qtmetrics2/testset_search.php b/non-puppet/qtmetrics2/testset_search.php
index d280564..0758ad1 100644
--- a/non-puppet/qtmetrics2/testset_search.php
+++ b/non-puppet/qtmetrics2/testset_search.php
@@ -34,8 +34,8 @@
/**
* Testset autocomplete search
- * @version 0.1
- * @since 04-06-2015
+ * @version 0.2
+ * @since 25-06-2015
* @author Juha Sippola
*/
@@ -48,8 +48,12 @@ if (isset($_GET['term'])) {
$rows = Factory::getTestsetsFiltered($_GET['term']);
foreach ($rows as $row) {
foreach ($row as $key => $value) {
- $list[] = $value;
+ if ($key === 'name')
+ $name = $value;
+ else
+ $project = $value;
}
+ $list[] = $name . ' (in ' . $project . ')'; // the separator must match with that used in index.php
}
// Return list as json string
echo json_encode($list);