diff options
author | Juha Sippola <juhasippola@outlook.com> | 2015-09-25 14:14:22 +0300 |
---|---|---|
committer | Tony Sarajärvi <tony.sarajarvi@theqtcompany.com> | 2015-09-29 08:59:34 +0000 |
commit | 146f150d772b0f5950d322094ad140a5feba527f (patch) | |
tree | 6bc1252ffde10722dc9be95acdeb148f42c65df0 /non-puppet/qtmetrics2 | |
parent | 2317417e27fbfbe319d5f5cc43d71528f6f1619d (diff) |
Qt Metrics 2 (v0.35): Top testset/testfunction duration
New pages to list top testset durations and testfunction
durations (for one testset) since a specific date including
the runs that take longer than a specific limit.
The testset duration list can be opened from the button
on home page, and the testfunction list from a button
on the testset page.
Change-Id: I19d2fe1a8cc06f68cb78c7672148687b0fdff681
Reviewed-by: Tony Sarajärvi <tony.sarajarvi@theqtcompany.com>
Diffstat (limited to 'non-puppet/qtmetrics2')
-rw-r--r-- | non-puppet/qtmetrics2/index.php | 112 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/scripts/ajax.js | 31 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/src/Database.php | 214 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/src/Factory.php | 97 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/src/TestsetRun.php | 19 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/src/test/DatabaseTest.php | 136 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/src/test/FactoryTest.php | 60 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/templates/about.html | 4 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/templates/conf.html | 13 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/templates/home.html | 7 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/templates/testfunction.html | 7 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/templates/testfunctions_duration.html | 108 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/templates/testset.html | 16 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/templates/testset_testfunctions.html | 8 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/templates/testsets_duration.html | 110 | ||||
-rw-r--r-- | non-puppet/qtmetrics2/templates/testsets_duration_data.html | 183 |
16 files changed, 1073 insertions, 52 deletions
diff --git a/non-puppet/qtmetrics2/index.php b/non-puppet/qtmetrics2/index.php index 4156976..a3a9e26 100644 --- a/non-puppet/qtmetrics2/index.php +++ b/non-puppet/qtmetrics2/index.php @@ -34,7 +34,7 @@ /** * Qt Metrics API - * @since 23-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -73,6 +73,7 @@ $app->get('/', function() use($app) 'topRoute' => Slim\Slim::getInstance()->urlFor('top'), 'flakyRoute' => Slim\Slim::getInstance()->urlFor('flaky'), 'topTestfunctionsRoute' => Slim\Slim::getInstance()->urlFor('toptestfunctions'), + 'durationTestsetsRoute' => Slim\Slim::getInstance()->urlFor('durationTestsets'), 'bpassedTestfunctionsRoute' => Slim\Slim::getInstance()->urlFor('bpassed'), 'masterProject' => $ini['master_build_project'], 'masterState' => $ini['master_build_state'], @@ -650,6 +651,113 @@ $app->get('/data/test/bpassed/testrows/:testset/:project', function($testset, $p }); /** + * UI route: /test/duration/testsets (GET) + */ + +$app->get('/test/duration/testsets', function() use($app) +{ + $ini = Factory::conf(); + $dbStatus = Factory::db()->getDbRefreshStatus(); + $days = intval($ini['top_duration_last_days']) - 1; + $since = Factory::getSinceDate($days); + $breadcrumb = array( + array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root')) + ); + $app->render('testsets_duration.html', array( + 'root' => Slim\Slim::getInstance()->urlFor('root'), + 'dbStatus' => $dbStatus, + 'refreshed' => $dbStatus['refreshed'] . ' (GMT)', + 'breadcrumb' => $breadcrumb, + 'lastDays' => $ini['top_duration_last_days'], + 'sinceDate' => $since, + 'durationLimitSec' => $ini['testset_top_duration_limit_sec'], + 'masterProject' => $ini['master_build_project'], + 'masterState' => $ini['master_build_state'] + )); +})->name('durationTestsets'); + +$app->get('/data/test/duration/testsets', function() use($app) +{ + $ini = Factory::conf(); + $days = intval($ini['top_duration_last_days']) - 1; + $since = Factory::getSinceDate($days); + $app->render('testsets_duration_data.html', array( + 'testsetRoute' => Slim\Slim::getInstance()->urlFor('root') . 'testset', + 'lastDays' => $ini['top_duration_last_days'], + 'sinceDate' => $since, + 'durationLimitSec' => $ini['testset_top_duration_limit_sec'], + 'list' => 'testsets', + 'testset' => '', + 'project' => '', + 'runs' => Factory::createTestsetRunsMaxDuration( + $ini['master_build_project'], + $ini['master_build_state']) // managed as objects + )); +}); + +/** + * UI route: /test/duration/testfunctions/:testset/:project (GET) + */ + +$app->get('/test/duration/testfunctions/:testset/:project', function($testset, $project) use($app) +{ + $ini = Factory::conf(); + $dbStatus = Factory::db()->getDbRefreshStatus(); + if (Factory::checkTestset($testset)) { + $days = intval($ini['top_duration_last_days']) - 1; + $since = Factory::getSinceDate($days); + $testsetRoute = str_replace('/:testset/:project', '', Slim\Slim::getInstance()->urlFor('testset')); + $breadcrumb = array( + array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root')), + array('name' => $testset, 'link' => $testsetRoute . '/' . $testset . '/' . $project) + ); + $app->render('testfunctions_duration.html', array( + 'root' => Slim\Slim::getInstance()->urlFor('root'), + 'dbStatus' => $dbStatus, + 'refreshed' => $dbStatus['refreshed'] . ' (GMT)', + 'breadcrumb' => $breadcrumb, + 'lastDays' => $ini['top_duration_last_days'], + 'sinceDate' => $since, + 'durationLimitSec' => $ini['testfunction_top_duration_limit_sec'], + 'testset' => $testset, + 'project' => $project, + 'masterProject' => $ini['master_build_project'], + 'masterState' => $ini['master_build_state'] + )); + } else { + $app->render('empty.html', array( + 'root' => Slim\Slim::getInstance()->urlFor('root'), + 'dbStatus' => $dbStatus, + 'message' => '404 Not Found' + )); + $app->response()->status(404); + } +})->name('durationTestfunctions'); + +$app->get('/data/test/duration/testfunctions/:testset/:project', function($testset, $project) use($app) +{ + $ini = Factory::conf(); + $days = intval($ini['top_duration_last_days']) - 1; + $since = Factory::getSinceDate($days); + $testsetTestfunctionsRoute = str_replace('/:testset/:project/:conf', '', Slim\Slim::getInstance()->urlFor('testset_testfunctions')); + $app->render('testsets_duration_data.html', array( + 'testsetRoute' => Slim\Slim::getInstance()->urlFor('root') . 'testset', + 'testsetTestfunctionsRoute' => $testsetTestfunctionsRoute, + 'lastDays' => $ini['top_duration_last_days'], + 'sinceDate' => $since, + 'durationLimitSec' => $ini['testfunction_top_duration_limit_sec'], + 'list' => 'testfunctions', + 'testset' => $testset, + 'project' => $project, + 'runs' => Factory::createTestfunctionRunsMaxDuration( + $testset, + $project, + $ini['master_build_project'], + $ini['master_build_state']) // managed as objects + )); +}); + +/** * UI route: /testset/:testset/:project (GET) */ @@ -667,6 +775,7 @@ $app->get('/testset/:testset/:project', function($testset, $project) use($app) $testsetProjectRoute = str_replace('/:project', '', Slim\Slim::getInstance()->urlFor('testsetproject')); $bpassedTestsetRoute = str_replace('/:testset/:project', '', Slim\Slim::getInstance()->urlFor('bpassedtestset')); $bpassedtestsetTestrowsRoute = str_replace('/:testset/:project', '', Slim\Slim::getInstance()->urlFor('bpassedtestsetTestrows')); + $durationTestfunctionsRoute = str_replace('/:testset/:project', '', Slim\Slim::getInstance()->urlFor('durationTestfunctions')); $app->render('testset.html', array( 'root' => Slim\Slim::getInstance()->urlFor('root'), 'dbStatus' => $dbStatus, @@ -676,6 +785,7 @@ $app->get('/testset/:testset/:project', function($testset, $project) use($app) 'testsetProjectRoute' => $testsetProjectRoute, 'bpassedTestsetRoute' => $bpassedTestsetRoute, 'bpassedtestsetTestrowsRoute' => $bpassedtestsetTestrowsRoute, + 'durationTestfunctionsRoute' => $durationTestfunctionsRoute, 'lastDaysFailures' => $ini['top_failures_last_days'], 'lastDaysFlaky' => $ini['flaky_testsets_last_days'], 'sinceDateFailures' => Factory::getSinceDate(intval($ini['top_failures_last_days']) - 1), diff --git a/non-puppet/qtmetrics2/scripts/ajax.js b/non-puppet/qtmetrics2/scripts/ajax.js index 294194b..f63695e 100644 --- a/non-puppet/qtmetrics2/scripts/ajax.js +++ b/non-puppet/qtmetrics2/scripts/ajax.js @@ -34,7 +34,7 @@ /** * Ajax route calls - * @since 23-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -152,4 +152,33 @@ $(function () { }); } + // Top testset duration + if ($.inArray('testsets_duration', divs) > -1) { + $.ajax({ + url: "data/test/duration/testsets", + dataType: "html", + cache: true + }) + .done(function( html ) { + console.log(this.url + " done"); + $('#testsets_duration').html(html); + }); + } + + // Top testfunction duration + if ($.inArray('testfunctions_duration', divs) > -1) { + testset = $('#testset').html(); + project = $('#project').html(); + url = "data/test/duration/testfunctions/" + testset + "/" + project; + $.ajax({ + url: url, + dataType: "html", + cache: true + }) + .done(function( html ) { + console.log(this.url + " done"); + $('#testfunctions_duration').html(html); + }); + } + }); diff --git a/non-puppet/qtmetrics2/src/Database.php b/non-puppet/qtmetrics2/src/Database.php index a3b7f1b..beabfff 100644 --- a/non-puppet/qtmetrics2/src/Database.php +++ b/non-puppet/qtmetrics2/src/Database.php @@ -34,7 +34,7 @@ /** * Database class - * @since 23-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -133,9 +133,33 @@ class Database { } /** + * Get list of testsets. + * @return array (int id, string name, string project) + */ + public function getTestsets() + { + $result = array(); + $query = $this->db->prepare(" + SELECT testset.id AS id, testset.name AS testset, project.name AS project + FROM testset + INNER JOIN project ON testset.project_id = project.id + ORDER BY testset.name; + "); + $query->execute(array()); + while($row = $query->fetch(PDO::FETCH_ASSOC)) { + $result[] = array( + 'id' => $row['id'], + 'name' => $row['testset'], + 'project' => $row['project'] + ); + } + return $result; + } + + /** * Get list of testsets matching the filter string. * @param string $filter - * @return array (string name) + * @return array (string name, string project) */ public function getTestsetsFiltered($filter) { @@ -188,6 +212,38 @@ class Database { } /** + * Get list of testfunctions for a testset + * @param string $testset + * @param string $project + * @return array (int id, int testsetId, string name) + */ + public function getTestfunctionsTestset($testset, $project) + { + $result = array(); + $query = $this->db->prepare(" + SELECT testfunction.id AS id, testfunction.testset_id AS testset_id, testfunction.name AS testset + FROM testfunction + WHERE testfunction.testset_id = + (SELECT testset.id + FROM testset INNER JOIN project ON testset.project_id = project.id + WHERE testset.name = ? AND project.name = ?) + ORDER BY testfunction.name; + "); + $query->execute(array( + $testset, + $project + )); + while($row = $query->fetch(PDO::FETCH_ASSOC)) { + $result[] = array( + 'id' => $row['id'], + 'testsetId' => $row['testset_id'], + 'name' => $row['testset'] + ); + } + return $result; + } + + /** * Get list of target platform os's * @return array (string os) */ @@ -757,6 +813,132 @@ class Database { } /** + * Get the longest testset run duration in specified builds since specified date + * @param string $runProject + * @param string $runState + * @param string $date + * @param string $durationLimitSec + * @return array (string testset, string project, string branch, string conf, string buildKey, string timestamp, string result, int duration) + */ + public function getTestsetMaxDuration($testsetId, $runProject, $runState, $date, $durationLimitSec) + { + $result = array(); + $query = $this->db->prepare(" + SELECT + testset.name AS testset, + project.name AS project, + branch.name AS branch, + conf.name AS conf, + project_run.build_key, + project_run.timestamp, + testset_run.result, + testset_run.duration + 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 + INNER JOIN state ON project_run.state_id = state.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.timestamp >= ? AND + testset_run.testset_id = ? AND + testset_run.duration >= ? + ORDER BY testset_run.duration DESC + LIMIT 1; + "); + $durationLimitDsec = $durationLimitSec * 10; // duration is in deciseconds in the database + $query->bindParam(1, $runProject); + $query->bindParam(2, $runState); + $query->bindParam(3, $date); + $query->bindParam(4, $testsetId, PDO::PARAM_INT); // int data type must be separately set + $query->bindParam(5, $durationLimitDsec, PDO::PARAM_INT); + $query->execute(); + while($row = $query->fetch(PDO::FETCH_ASSOC)) { + $result[] = array( + 'testset' => $row['testset'], + 'project' => $row['project'], + 'branch' => $row['branch'], + 'conf' => $row['conf'], + 'buildKey' => $row['build_key'], + 'timestamp' => $row['timestamp'], + 'result' => $row['result'], + 'duration' => round($row['duration']/10, 1) // convert deciseconds to seconds + ); + } + return $result; + } + + /** + * Get the longest testfunction run duration in specified builds since specified date + * @param string $runProject + * @param string $runState + * @param string $date + * @param string $durationLimitSec + * @return array (string testfunction, string testset, string project, string branch, string conf, string buildKey, string timestamp, string result, int duration) + */ + public function getTestfunctionMaxDuration($testfunctionId, $testsetId, $runProject, $runState, $date, $durationLimitSec) + { + $result = array(); + $query = $this->db->prepare(" + SELECT + testfunction.name AS testfunction, + testset.name AS testset, + project.name AS project, + branch.name AS branch, + conf.name AS conf, + project_run.build_key, + project_run.timestamp, + testfunction_run.result, + testfunction_run.duration + FROM testfunction_run + INNER JOIN testfunction ON testfunction_run.testfunction_id = testfunction.id + INNER JOIN testset_run ON testfunction_run.testset_run_id = testset_run.id + 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 + INNER JOIN state ON project_run.state_id = state.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.timestamp >= ? AND + testset_run.testset_id = ? AND + testfunction_run.testfunction_id = ? AND + testfunction_run.duration >= ? + ORDER BY testfunction_run.duration DESC + LIMIT 1; + "); + $durationLimitDsec = $durationLimitSec * 10; // duration is in deciseconds in the database + $query->bindParam(1, $runProject); + $query->bindParam(2, $runState); + $query->bindParam(3, $date); + $query->bindParam(4, $testsetId, PDO::PARAM_INT); // int data type must be separately set + $query->bindParam(5, $testfunctionId, PDO::PARAM_INT); // int data type must be separately set + $query->bindParam(6, $durationLimitDsec, PDO::PARAM_INT); + $query->execute(); + while($row = $query->fetch(PDO::FETCH_ASSOC)) { + $result[] = array( + 'testfunction' => $row['testfunction'], + 'testset' => $row['testset'], + 'project' => $row['project'], + 'branch' => $row['branch'], + 'conf' => $row['conf'], + 'buildKey' => $row['build_key'], + 'timestamp' => $row['timestamp'], + 'result' => $row['result'], + 'duration' => round($row['duration']/10, 1) // convert deciseconds to seconds + ); + } + return $result; + } + + /** * Get counts of all passed, failed and skipped runs by testfunction in specified builds since specified date (list length limited) * Only the testfunctions that have failed since the specified date are listed * @param string $runProject @@ -1002,7 +1184,7 @@ class Database { * Get project run data by branch * @param string $runProject * @param string $runState - * @return array (string branch, string build_key, string timestamp) + * @return array (string branch, string buildKey, string timestamp) */ public function getProjectBuildsByBranch($runProject, $runState) { @@ -1038,7 +1220,7 @@ 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) + * @return array (string branch, string conf, string buildKey, bool forcesuccess, bool insignificant, string result, string timestamp, string duration) */ public function getConfBuildsByBranch($runProject, $runState) { @@ -1087,7 +1269,7 @@ class Database { * @param string $runProject * @param string $runState * @param string $targetOs - * @return array (string branch, string conf, string build_key, bool forcesuccess, bool insignificant, string result, string timestamp, string duration) + * @return array (string branch, string conf, string buildKey, bool forcesuccess, bool insignificant, string result, string timestamp, string duration) */ public function getConfOsBuildsByBranch($runProject, $runState, $targetOs) { @@ -1138,7 +1320,7 @@ class Database { * @param string $runProject * @param string $runState * @param string $conf - * @return array (string branch, string conf, string build_key, bool forcesuccess, bool insignificant, string result, string timestamp, string duration) + * @return array (string branch, string conf, string buildKey, bool forcesuccess, bool insignificant, string result, string timestamp, string duration) */ public function getConfBuildByBranch($runProject, $runState, $conf) { @@ -1190,7 +1372,7 @@ class Database { * @param string $testsetProject * @param string $runProject * @param string $runState - * @return array (string branch, string conf, string build_key, string result, string timestamp, string duration, int run) + * @return array (string branch, string conf, string buildKey, string result, string timestamp, string duration, int run) */ public function getTestsetResultsByBranchConf($testset, $testsetProject, $runProject, $runState) { @@ -1232,7 +1414,7 @@ class Database { 'buildKey' => $row['build_key'], 'result' => $row['result'], 'timestamp' => $row['timestamp'], - 'duration' => $row['duration'], + 'duration' => round($row['duration']/10, 1), // convert deciseconds to seconds 'run' => $row['run'] ); } @@ -1244,7 +1426,7 @@ class Database { * @param string $testsetProject * @param string $runProject * @param string $runState - * @return array (string branch, string conf, string build_key, int passed, int ipassed, int failed, int ifailed) + * @return array (string branch, string conf, string buildKey, int passed, int ipassed, int failed, int ifailed) */ public function getTestsetProjectResultsByBranchConf($testsetProject, $runProject, $runState) { @@ -1298,7 +1480,7 @@ class Database { * @param string $conf * @param string $runProject * @param string $runState - * @return array (string branch, string build_key, string testset, string project, string result, string timestamp, string duration, int run) + * @return array (string branch, string buildKey, string testset, string project, string result, string timestamp, string duration, int run) */ public function getTestsetConfResultsByBranch($conf, $runProject, $runState) { @@ -1341,7 +1523,7 @@ class Database { 'project' => $row['project'], 'result' => $row['result'], 'timestamp' => $row['timestamp'], - 'duration' => $row['duration'], + 'duration' => round($row['duration']/10, 1), // convert deciseconds to seconds 'run' => $row['run'] ); } @@ -1355,7 +1537,7 @@ class Database { * @param string $testsetProject * @param string $runProject * @param string $runState - * @return array (string branch, string build_key, string testset, string project, string result, string timestamp, string duration, int run) + * @return array (string branch, string buildKey, string testset, string project, string result, string timestamp, string duration, int run) */ public function getTestsetConfProjectResultsByBranch($conf, $testsetProject, $runProject, $runState) { @@ -1400,7 +1582,7 @@ class Database { 'project' => $row['project'], 'result' => $row['result'], 'timestamp' => $row['timestamp'], - 'duration' => $row['duration'], + 'duration' => round($row['duration']/10, 1), // convert deciseconds to seconds 'run' => $row['run'] ); } @@ -1415,7 +1597,7 @@ class Database { * @param string $conf * @param string $runProject * @param string $runState - * @return array (string branch, string build_key, string testfunction, string result, string timestamp, string duration) + * @return array (string branch, string buildKey, string testfunction, string result, string timestamp, string duration) */ public function getTestfunctionConfResultsByBranch($testset, $testsetProject, $conf, $runProject, $runState) { @@ -1461,7 +1643,7 @@ class Database { 'testfunction' => $row['testfunction'], 'result' => $row['result'], 'timestamp' => $row['timestamp'], - 'duration' => $row['duration'] + 'duration' => round($row['duration']/10, 1) // convert deciseconds to seconds ); } return $result; @@ -1476,7 +1658,7 @@ class Database { * @param string $conf * @param string $runProject * @param string $runState - * @return array (string branch, string build_key, string testrow, string result, string timestamp) + * @return array (string branch, string buildKey, string testrow, string result, string timestamp) */ public function getTestrowConfResultsByBranch($testfunction, $testset, $testsetProject, $conf, $runProject, $runState) { diff --git a/non-puppet/qtmetrics2/src/Factory.php b/non-puppet/qtmetrics2/src/Factory.php index 7bce306..fedf90b 100644 --- a/non-puppet/qtmetrics2/src/Factory.php +++ b/non-puppet/qtmetrics2/src/Factory.php @@ -34,7 +34,7 @@ /** * Factory class - * @since 23-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -477,6 +477,101 @@ class Factory { } /** + * Create TestsetRun objects with the longest duration for each testset + * Object list is sorted descending by duration + * @param string $runProject + * @param string $runState + * @return array TestsetRun objects + */ + public static function createTestsetRunsMaxDuration($runProject, $runState) + { + $objects = array(); + $ini = self::conf(); + $days = intval($ini['top_duration_last_days']) - 1; + $since = self::getSinceDate($days); + $durationLimitSec = intval($ini['testset_top_duration_limit_sec']); + $testsets = self::db()->getTestsets(); + foreach($testsets as $testset) { + $dbEntries = self::db()->getTestsetMaxDuration($testset['id'], $runProject, $runState, $since, $durationLimitSec); + foreach($dbEntries as $entry) { + $obj = new TestsetRun( + $entry['testset'], + $entry['project'], + $runProject, + $entry['branch'], + $runState, + $entry['buildKey'], + $entry['conf'], + 0, + TestsetRun::stripResult($entry['result']), + TestsetRun::isInsignificant($entry['result']), + $entry['timestamp'], + $entry['duration'] + ); + $objects[] = $obj; + } + } + // Sort descending by duration + usort($objects, function($a, $b) + { + if ($a->getDuration() === $b->getDuration()) + return 0; + else + return ($a->getDuration() > $b->getDuration() ? -1 : 1); + }); + return $objects; + } + + /** + * Create TestfunctionRun objects with the longest duration for each testfunction + * Object list is sorted descending by duration + * @param string $testset + * @param string $testsetProject + * @param string $runProject + * @param string $runState + * @return array TestfunctionRun objects + */ + public static function createTestfunctionRunsMaxDuration($testset, $project, $runProject, $runState) + { + $objects = array(); + $ini = self::conf(); + $days = intval($ini['top_duration_last_days']) - 1; + $since = self::getSinceDate($days); + $durationLimitSec = intval($ini['testfunction_top_duration_limit_sec']); + $testfunctions = self::db()->getTestfunctionsTestset($testset, $project); + foreach($testfunctions as $testfunction) { + $dbEntries = self::db()->getTestfunctionMaxDuration($testfunction['id'], $testfunction['testsetId'], $runProject, $runState, $since, $durationLimitSec); + foreach($dbEntries as $entry) { + $obj = new TestfunctionRun( + $entry['testfunction'], + $entry['testset'], + $entry['project'], + $runProject, + $entry['branch'], + $runState, + $entry['buildKey'], + $entry['conf'], + TestfunctionRun::stripResult($entry['result']), + TestfunctionRun::isBlacklisted($entry['result']), + TestfunctionRun::hasChildren($entry['result']), + $entry['timestamp'], + $entry['duration'] + ); + $objects[] = $obj; + } + } + // Sort descending by duration + usort($objects, function($a, $b) + { + if ($a->getDuration() === $b->getDuration()) + return 0; + else + return ($a->getDuration() > $b->getDuration() ? -1 : 1); + }); + return $objects; + } + + /** * Create TestfunctionRun objects in a configuration for those in database * @param string $testset * @param string $testsetProject diff --git a/non-puppet/qtmetrics2/src/TestsetRun.php b/non-puppet/qtmetrics2/src/TestsetRun.php index 1203276..696014b 100644 --- a/non-puppet/qtmetrics2/src/TestsetRun.php +++ b/non-puppet/qtmetrics2/src/TestsetRun.php @@ -34,7 +34,7 @@ /** * TestsetRun class - * @since 17-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -49,6 +49,11 @@ class TestsetRun extends ProjectRun { const RESULT_FAILURE = "failed"; /** + * If the tesset name is long, a shorter version of the name can be requested + */ + const SHORT_NAME_LENGTH = 25; + + /** * Testset name. * @var string */ @@ -112,6 +117,18 @@ class TestsetRun extends ProjectRun { } /** + * Get short name. + * @return string + */ + public function getShortName() + { + if (strlen($this->name) > self::SHORT_NAME_LENGTH) + return substr($this->name, 0, self::SHORT_NAME_LENGTH - 10) . '...' . substr($this->name, -7); + else + return $this->name; + } + + /** * Get name of the testset project. * @return string */ diff --git a/non-puppet/qtmetrics2/src/test/DatabaseTest.php b/non-puppet/qtmetrics2/src/test/DatabaseTest.php index 942cf38..8605365 100644 --- a/non-puppet/qtmetrics2/src/test/DatabaseTest.php +++ b/non-puppet/qtmetrics2/src/test/DatabaseTest.php @@ -38,7 +38,7 @@ 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 - * @since 23-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -144,6 +144,31 @@ class DatabaseTest extends PHPUnit_Framework_TestCase } /** + * Test getTestsets + * @dataProvider testGetTestsetsData + */ + public function testGetTestsets($exp_testset) + { + $items = array(); + $db = Factory::db(); + $result = $db->getTestsets(); + $this->assertNotEmpty($result); + foreach($result as $row) { + $this->assertArrayHasKey('id', $row); + $this->assertArrayHasKey('name', $row); + $this->assertArrayHasKey('project', $row); + $items[] = $row['name']; + } + $this->assertContains($exp_testset, $items); + } + public function testGetTestsetsData() + { + return array( + array('tst_qftp') + ); + } + + /** * Test getTestsetsFiltered * @dataProvider testGetTestsetsFilteredData */ @@ -198,6 +223,33 @@ class DatabaseTest extends PHPUnit_Framework_TestCase } /** + * Test getTestfunctionsTestset + * @dataProvider testGetTestfunctionsTestsetData + */ + public function testGetTestfunctionsTestset($testset, $project, $exp_testfunction) + { + $items = array(); + $db = Factory::db(); + $result = $db->getTestfunctionsTestset($testset, $project); + $this->assertNotEmpty($result); + foreach($result as $row) { + $this->assertArrayHasKey('id', $row); + $this->assertArrayHasKey('testsetId', $row); + $this->assertArrayHasKey('name', $row); + $items[] = $row['name']; + } + $this->assertContains($exp_testfunction, $items); + } + public function testGetTestfunctionsTestsetData() + { + return array( + array('tst_networkselftest', 'qtbase', 'cleanupTestCase'), + array('tst_qfont', 'qtbase', 'defaultFamily'), + array('tst_qftp', 'qtbase', 'binaryAscii') + ); + } + + /** * Test getTargetPlatformOs * @dataProvider testGetTargetPlatformOsData */ @@ -600,6 +652,88 @@ class DatabaseTest extends PHPUnit_Framework_TestCase } /** + * Test getTestsetMaxDuration + * @dataProvider testGetTestsetMaxDurationData + */ + public function testGetTestsetMaxDuration($testsetId, $runProject, $runState, $date, $durationLimitSec, $exp_testset, $exp_durationSec, $has_data) + { + $testsets = array(); + $db = Factory::db(); + $result = $db->getTestsetMaxDuration($testsetId, $runProject, $runState, $date, $durationLimitSec); + foreach($result as $row) { + $this->assertArrayHasKey('testset', $row); + $this->assertArrayHasKey('project', $row); + $this->assertArrayHasKey('branch', $row); + $this->assertArrayHasKey('conf', $row); + $this->assertArrayHasKey('buildKey', $row); + $this->assertArrayHasKey('timestamp', $row); + $this->assertArrayHasKey('result', $row); + $this->assertArrayHasKey('duration', $row); + $testsets[] = $row['testset']; + } + if ($has_data) { + $this->assertNotEmpty($result); + $this->assertContains($exp_testset, $testsets); + $this->assertEquals(1, count($testsets)); + $this->assertEquals($exp_durationSec, $row['duration']); + } else { + $this->assertEmpty($result); + } + } + public function testGetTestsetMaxDurationData() + { + return array( + array(3, 'Qt5', 'state', '2013-05-01', 90, 'tst_qftp', 813, 1), // duration is in seconds in the interface + array(3, 'Qt5', 'state', '2013-05-28', 90, 'tst_qftp', 813, 1), + array(3, 'Qt5', 'state', '2013-05-28', 900, 'tst_qftp', 0, 0), + array(3, 'Qt5', 'state', '2013-05-29', 90, 'tst_qftp', 0, 0), + array(999, 'Qt5', 'state', '2013-05-29', 90, 'invalid', 0, 0) + ); + } + + /** + * Test getTestfunctionMaxDuration + * @dataProvider testGetTestfunctionMaxDurationData + */ + public function testGetTestfunctionMaxDuration($testfunctionId, $testsetId, $runProject, $runState, $date, $durationLimitSec, $exp_testfunction, $exp_durationSec, $has_data) + { + $testfunctions = array(); + $db = Factory::db(); + $result = $db->getTestfunctionMaxDuration($testfunctionId, $testsetId, $runProject, $runState, $date, $durationLimitSec); + foreach($result as $row) { + $this->assertArrayHasKey('testfunction', $row); + $this->assertArrayHasKey('testset', $row); + $this->assertArrayHasKey('project', $row); + $this->assertArrayHasKey('branch', $row); + $this->assertArrayHasKey('conf', $row); + $this->assertArrayHasKey('buildKey', $row); + $this->assertArrayHasKey('timestamp', $row); + $this->assertArrayHasKey('result', $row); + $this->assertArrayHasKey('duration', $row); + $testfunctions[] = $row['testfunction']; + } + if ($has_data) { + $this->assertNotEmpty($result); + $this->assertContains($exp_testfunction, $testfunctions); + $this->assertEquals(1, count($testfunctions)); + $this->assertEquals($exp_durationSec, $row['duration']); + } else { + $this->assertEmpty($result); + } + } + public function testGetTestfunctionMaxDurationData() + { + return array( + array(39, 3, 'Qt5', 'state', '2013-05-01', 5, 'binaryAscii', 31.1, 1), // duration is in seconds in the interface + array(39, 3, 'Qt5', 'state', '2013-05-28', 5, 'binaryAscii', 0, 0), + array(39, 3, 'Qt5', 'state', '2013-05-01', 900, 'binaryAscii', 0, 0), + array(31, 2, 'Qt5', 'state', '2013-05-01', 5, 'resetFont', 6.1, 1), + array(18, 1, 'Qt5', 'state', '2013-05-01', 0.2, 'socks5Proxy', 0.2, 1), + array(999, 999, 'Qt5', 'state', '2013-05-29', 5, 'invalid', 0, 0) + ); + } + + /** * Test getTestfunctionsResultCounts * @dataProvider testGetTestfunctionsResultCountsData */ diff --git a/non-puppet/qtmetrics2/src/test/FactoryTest.php b/non-puppet/qtmetrics2/src/test/FactoryTest.php index 72271b2..9940d4a 100644 --- a/non-puppet/qtmetrics2/src/test/FactoryTest.php +++ b/non-puppet/qtmetrics2/src/test/FactoryTest.php @@ -37,7 +37,7 @@ require_once(__DIR__.'/../Factory.php'); /** * Factory unit test class * @example To run (in qtmetrics root directory): php <path-to-phpunit>/phpunit.phar ./src/test - * @since 23-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -479,6 +479,64 @@ class FactoryTest extends PHPUnit_Framework_TestCase } /** + * Test createTestsetRunsMaxDuration + * @dataProvider testCreateTestsetRunsMaxDurationData + */ + public function testCreateTestsetRunsMaxDuration($runProject, $runState, $exp_testset, $exp_build_key, $exp_duration, $max_imaginary_duration) + { + $runs = Factory::createTestsetRunsMaxDuration($runProject, $runState); + $this->assertNotEmpty($runs); + $prevDuration = $max_imaginary_duration; + foreach($runs as $run) { + $this->assertTrue($run instanceof TestsetRun); + $this->assertLessThanOrEqual($prevDuration, $run->getDuration()); + $prevDuration = $run->getDuration(); + if ($run->getName() === $exp_testset) { + $this->assertEquals($exp_build_key, $run->getBuildKey()); + $this->assertEquals($exp_duration, $run->getDuration()); + } + } + } + public function testCreateTestsetRunsMaxDurationData() + { + return array( + array('Qt5', 'state', 'tst_qftp', '1348', 813, 999), + array('Qt5', 'state', 'tst_qfont', 'BuildKeyInStringFormat12345', 814, 999), + array('Qt5', 'state', 'tst_networkselftest', '1348', 729, 999), + array('Qt5', 'state', 'invalid', '', 0, 999) + ); + } + + /** + * Test createTestfunctionRunsMaxDuration + * @dataProvider testCreateTestfunctionRunsMaxDurationData + */ + public function testCreateTestfunctionRunsMaxDuration($testset, $testsetProject, $runProject, $runState, $exp_testfunction, $exp_build_key, $exp_duration, $max_imaginary_duration) + { + $runs = Factory::createTestfunctionRunsMaxDuration($testset, $testsetProject, $runProject, $runState); + $this->assertNotEmpty($runs); + $prevDuration = $max_imaginary_duration; + foreach($runs as $run) { + $this->assertTrue($run instanceof TestfunctionRun); + $this->assertLessThanOrEqual($prevDuration, $run->getDuration()); + $prevDuration = $run->getDuration(); + if ($run->getName() === $exp_testfunction) { + $this->assertEquals($exp_build_key, $run->getBuildKey()); + $this->assertEquals($exp_duration, $run->getDuration()); + } + } + } + public function testCreateTestfunctionRunsMaxDurationData() + { + return array( + array('tst_qftp', 'qtbase', 'Qt5', 'state', 'binaryAscii', '1023', 31.1, 999), + array('tst_qfont', 'qtbase', 'Qt5', 'state', 'resetFont', '1346', 6.1, 999), + array('tst_networkselftest', 'qtbase', 'Qt5', 'state', 'socks5Proxy', '1348', 0.2, 999), + array('tst_networkselftest', 'qtbase', 'Qt5', 'state', 'invalid', '', 0, 999) + ); + } + + /** * Test createTestfunctionRunsInConf * @dataProvider testCreateTestfunctionRunsInConfData */ diff --git a/non-puppet/qtmetrics2/templates/about.html b/non-puppet/qtmetrics2/templates/about.html index 044d95a..715df9b 100644 --- a/non-puppet/qtmetrics2/templates/about.html +++ b/non-puppet/qtmetrics2/templates/about.html @@ -34,7 +34,7 @@ /** * About window content - * @since 23-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -52,4 +52,4 @@ and the global Qt developer community are the target audience. For detailed desc <p>See the <strong><a href="https://wiki.qt.io/Qt_Metrics_2_Backlog" target="_blank">backlog</a></strong> for development items currently identified or in progress.</p> -<p><small>Version 0.34 (23-Sep-2015)</small></p> +<p><small>Version 0.35 (24-Sep-2015)</small></p> diff --git a/non-puppet/qtmetrics2/templates/conf.html b/non-puppet/qtmetrics2/templates/conf.html index f5dab3a..16015e8 100644 --- a/non-puppet/qtmetrics2/templates/conf.html +++ b/non-puppet/qtmetrics2/templates/conf.html @@ -34,7 +34,7 @@ /** * Configuration page - * @since 17-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -368,11 +368,6 @@ title="insignificant">i</span> {% else %} {% set resultIcon = '' %} {% endif %} -{% if (run.getDuration / 10) > 60 %} -{% set durationFormatted = ' (00:' ~ (run.getDuration/10)|date("i:s") ~ ')' %} -{% else %} -{% set durationFormatted = '' %} -{% endif %} {# Print result #} <td class="center"> <span class="spaceHorizontal {{ resultIcon }} clickOnTouch" data-toggle="tooltip" data-placement="top" data-html="true" @@ -558,8 +553,8 @@ title="<table> {% else %} {% set resultIcon = '' %} {% endif %} -{% if (run.getDuration / 10) > 60 %} -{% set durationFormatted = ' (00:' ~ (run.getDuration/10)|date("i:s") ~ ')' %} +{% if run.getDuration > 60 %} +{% set durationFormatted = ' (00:' ~ (run.getDuration|round)|date("i:s") ~ ')' %} {% else %} {% set durationFormatted = '' %} {% endif %} @@ -570,7 +565,7 @@ title="<table> <tr><th>Testset: </th><td>{{ run.getName }}</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>Duration: </th><td>{{ run.getDuration }} 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 %} diff --git a/non-puppet/qtmetrics2/templates/home.html b/non-puppet/qtmetrics2/templates/home.html index 185e257..da90858 100644 --- a/non-puppet/qtmetrics2/templates/home.html +++ b/non-puppet/qtmetrics2/templates/home.html @@ -34,7 +34,7 @@ /** * Home page - * @since 21-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -127,14 +127,15 @@ </form> </div> <br> -<p>See top failure/flaky lists:</p> +<p>See top lists:</p> <div> <a class="btn btn-primary btn-xs" href="{{ topRoute }}" role="button">testsets</a> <a class="btn btn-primary btn-xs" href="{{ flakyRoute }}" role="button">flaky</a> <a class="btn btn-primary btn-xs" href="{{ topTestfunctionsRoute }}" role="button">test functions</a> +<a class="btn btn-primary btn-xs" href="{{ durationTestsetsRoute }}" role="button">duration</a> </div> <br> -<p>See blacklisted tests where tagging could be removed:</p> +<p>See blacklisted but passed tests:</p> <div> <a class="btn btn-primary btn-xs" href="{{ bpassedTestfunctionsRoute }}" role="button">test functions</a> </div> diff --git a/non-puppet/qtmetrics2/templates/testfunction.html b/non-puppet/qtmetrics2/templates/testfunction.html index 14d285b..1338d02 100644 --- a/non-puppet/qtmetrics2/templates/testfunction.html +++ b/non-puppet/qtmetrics2/templates/testfunction.html @@ -34,7 +34,7 @@ /** * Test function page (list of test rows) - * @since 23-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -247,11 +247,6 @@ {% else %} {% set resultIcon = '' %} {% endif %} -{% if (run.getDuration / 10) > 60 %} -{% set durationFormatted = ' (00:' ~ ((run.getDuration/10)|round)|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> diff --git a/non-puppet/qtmetrics2/templates/testfunctions_duration.html b/non-puppet/qtmetrics2/templates/testfunctions_duration.html new file mode 100644 index 0000000..c09f7cd --- /dev/null +++ b/non-puppet/qtmetrics2/templates/testfunctions_duration.html @@ -0,0 +1,108 @@ +{# +############################################################################# +## +## 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$ +## +############################################################################# + +/** + * Top duration (testsets) page + * @since 24-09-2015 + * @author Juha Sippola + */ + +#} + +{% include "header.html" %} + +<ol class="breadcrumb"> +{% for link in breadcrumb %} +<li><a href="{{ link.link }}">{{ link.name }}</a></li> +{% endfor %} +<li class="active">top test function duration</li> +</ol> + +<div class="container-fluid"> +<div class="row"> + +<div class="col-sm-12 col-md-12 main"> + +{##### Title #####} + +<h1 class="page-header"> +<span id="testset">{{ testset }}</span> +<span id="project" class="hidden">{{ project }}</span> +Top Test Function Duration +<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>Top Test Function Duration</strong><br> +<ul> +<li>Lists test functions for the testset {{ testset }} by their duration in +<strong>{{ masterProject }} {{ masterState }}</strong> builds during the last {{ lastDays }} days. +The list includes only the test function runs that took over {{ durationLimitSec }} seconds.</li> +<li>Each test function is listed here only once showing the test run that took the longest time. +All test function runs in different configurations across all branches can be seen on the linked +testset page, where the differences between configurations and branches can be studied as well.</li> +</ul> +</div> +</div> + +{##### List #####} + +<div id="testfunctions_duration"> +<div class="panel panel-primary"> +<div class="panel-heading"> +<h4 class="panel-title bold">Last {{ lastDays }} days <small>(since {{ sinceDate }}, duration over {{ durationLimitSec }}s)</small></h4> +</div> +</div> +<div class="progress data_loading"> +<div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"> +</div> +</div> +</div> {# testfunctions_duration #} + +</div> {# .col... #} +</div> {# .row #} +</div> {# .container-fluid #} + +{% include "footer.html" %} + +{# Local scripts for this page #} +<script src="scripts/ajax.js"></script> + +{% include "close.html" %} diff --git a/non-puppet/qtmetrics2/templates/testset.html b/non-puppet/qtmetrics2/templates/testset.html index 9fd4900..3cb54e6 100644 --- a/non-puppet/qtmetrics2/templates/testset.html +++ b/non-puppet/qtmetrics2/templates/testset.html @@ -34,7 +34,7 @@ /** * Testset page (list of configurations) - * @since 23-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -124,11 +124,15 @@ and their configuration on <strong>{{ masterProject }} {{ masterState }}</strong <div> <div class="btn-group"> {% set link = bpassedTestsetRoute ~ '/' ~ testset.getName|url_encode ~ '/' ~ testset.getProjectName|url_encode %} -<a class="btn btn-primary btn-xs" href="{{ link }}" role="button">blacklisted passes for<br>test functions</a> +<a class="btn btn-primary btn-xs" href="{{ link }}" role="button"><span class="badge">test functions</span><br>blacklisted passes</a> </div> <div class="btn-group"> {% set link = bpassedtestsetTestrowsRoute ~ '/' ~ testset.getName|url_encode ~ '/' ~ testset.getProjectName|url_encode %} -<a class="btn btn-primary btn-xs" href="{{ link }}" role="button">blacklisted passes for<br>test rows</a> +<a class="btn btn-primary btn-xs" href="{{ link }}" role="button"><span class="badge">test rows</span><br>blacklisted passes</a> +</div> +<div class="btn-group"> +{% set link = durationTestfunctionsRoute ~ '/' ~ testset.getName|url_encode ~ '/' ~ testset.getProjectName|url_encode %} +<a class="btn btn-primary btn-xs" href="{{ link }}" role="button"><span class="badge">test functions</span><br>duration</a> </div> </div> <hr> @@ -341,8 +345,8 @@ and their configuration on <strong>{{ masterProject }} {{ masterState }}</strong {% else %} {% set resultIcon = '' %} {% endif %} -{% if (run.getDuration / 10) > 60 %} -{% set durationFormatted = ' (00:' ~ (run.getDuration/10)|date("i:s") ~ ')' %} +{% if run.getDuration > 60 %} +{% set durationFormatted = ' (00:' ~ (run.getDuration|round)|date("i:s") ~ ')' %} {% else %} {% set durationFormatted = '' %} {% endif %} @@ -353,7 +357,7 @@ title="<table> <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>Duration: </th><td>{{ run.getDuration }} 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> diff --git a/non-puppet/qtmetrics2/templates/testset_testfunctions.html b/non-puppet/qtmetrics2/templates/testset_testfunctions.html index d2ee081..d5c2d44 100644 --- a/non-puppet/qtmetrics2/templates/testset_testfunctions.html +++ b/non-puppet/qtmetrics2/templates/testset_testfunctions.html @@ -34,7 +34,7 @@ /** * Testset page (list of test functions) - * @since 21-09-2015 + * @since 24-09-2015 * @author Juha Sippola */ @@ -261,8 +261,8 @@ {% else %} {% set resultIcon = '' %} {% endif %} -{% if (run.getDuration / 10) > 60 %} -{% set durationFormatted = ' (00:' ~ ((run.getDuration/10)|round)|date("i:s") ~ ')' %} +{% if run.getDuration > 60 %} +{% set durationFormatted = ' (00:' ~ (run.getDuration|round)|date("i:s") ~ ')' %} {% else %} {% set durationFormatted = '' %} {% endif %} @@ -278,7 +278,7 @@ title="<table> <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 }} {{ testrowResult }}</td></tr> -<tr><th>Duration: </th><td>{{ run.getDuration / 10 }} s {{ durationFormatted }}</td></tr> +<tr><th>Duration: </th><td>{{ run.getDuration }} s {{ durationFormatted }}</td></tr> <tr><th>Blacklisted: </th><td>{% if run.getBlacklisted %}yes{% else %}no{% endif %}</td></tr></table>"> </span></td> {% set buildKeyFound = 1 %} diff --git a/non-puppet/qtmetrics2/templates/testsets_duration.html b/non-puppet/qtmetrics2/templates/testsets_duration.html new file mode 100644 index 0000000..8fd953a --- /dev/null +++ b/non-puppet/qtmetrics2/templates/testsets_duration.html @@ -0,0 +1,110 @@ +{# +############################################################################# +## +## 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$ +## +############################################################################# + +/** + * Top duration (testsets) page + * @since 24-09-2015 + * @author Juha Sippola + */ + +#} + +{% include "header.html" %} + +<ol class="breadcrumb"> +{% for link in breadcrumb %} +<li><a href="{{ link.link }}">{{ link.name }}</a></li> +{% endfor %} +<li class="active">top testset duration</li> +</ol> + +<div class="container-fluid"> +<div class="row"> + +<div class="col-sm-12 col-md-12 main"> + +{##### Title #####} + +<h1 class="page-header"> +Top Testset Duration +<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>Top Testset Duration</strong><br> +<ul> +<li>Lists testsets by their duration in <strong>{{ masterProject }} {{ masterState }}</strong> +builds during the last {{ lastDays }} days. The list includes only the testset runs that took +over {{ durationLimitSec }} seconds.</li> +<li>Each testset is listed here only once showing the test run that took the longest time. +All testset runs in different configurations across all branches can be seen on the linked +testset page in order to check the differences between configurations and branches, as well +as to show the test function duration list.</li> +</ul> +</div> +</div> + +{##### List #####} + +<div id="testsets_duration"> +<div class="panel panel-primary"> +<div class="panel-heading"> +<h4 class="panel-title bold">Last {{ lastDays }} days <small>(since {{ sinceDate }}, duration over {{ durationLimitSec }}s)</small></h4> +</div> +</div> +<div class="progress data_loading"> +<div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"> +</div> +</div> +<div class="alert alert-warning" role="alert"> +<span class="glyphicon glyphicon-time"></span> <strong>Please wait:</strong> Extracting the data will be ready in less than a minute! +</div> +</div> {# testsets_duration #} + +</div> {# .col... #} +</div> {# .row #} +</div> {# .container-fluid #} + +{% include "footer.html" %} + +{# Local scripts for this page #} +<script src="scripts/ajax.js"></script> + +{% include "close.html" %} diff --git a/non-puppet/qtmetrics2/templates/testsets_duration_data.html b/non-puppet/qtmetrics2/templates/testsets_duration_data.html new file mode 100644 index 0000000..59497d9 --- /dev/null +++ b/non-puppet/qtmetrics2/templates/testsets_duration_data.html @@ -0,0 +1,183 @@ +{# +############################################################################# +## +## 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$ +## +############################################################################# + +/** + * Top duration (testsets and testfunctions) data + * @since 24-09-2015 + * @author Juha Sippola + */ + +#} + +{# Failed/passed bar area size in px #} +{% set BAR_AREA = 120 %} + +{# runs as TestsetRun objects +/** + * @var TestsetRun[] runs + */ +#} +{# runs as TestfunctionRun objects +/** + * @var TestfunctionRun[] runs + */ +#} + +{##### List #####} + +{# Calculate max duration for the bar #} +{% set runCount = 0 %} +{% set maxDuration = 1 %} +{% for run in runs %} +{% set runCount = runCount + 1 %} +{% if run.getDuration > maxDuration %} +{% set maxDuration = run.getDuration %} +{% endif %} +{% endfor %} + +<div class="panel panel-primary"> +<div class="panel-heading"> +<h4 class="panel-title bold">Last {{ lastDays }} days <small>(since {{ sinceDate }}, duration over {{ durationLimitSec }}s)</small></h4> +</div> + +{% if runCount > 0 %} + +<div class="panel-body"> +<div class="table-responsive"> +<table class="table table-striped"> +<thead> +<tr> +{% if list == 'testsets' %} +<th>testset</th> +{% else %} +<th>test function</th> +{% endif %} +<th class="leftBorder center">duration</th> +<th class="showInLargeDisplay"></th> +<th class="leftBorder">build information</th> +</tr> +</thead> +<tbody> + +{# Print testsets #} +{% for run in runs %} +<tr> +{# Testset and project name#} +{% if list == 'testsets' %} +{% set link = testsetRoute ~ '/' ~ run.getName|url_encode ~ '/' ~ run.getTestsetProjectName|url_encode %} +<td><a href="{{ link }}"> +{% if run.getName|length > constant('TestsetRun::SHORT_NAME_LENGTH') %} +<span class="clickOnTouch" data-toggle="tooltip" data-placement="top" title="{{ run.getName }}">{{ run.getShortName }}</span> +{% else %} +{{ run.getShortName }} +{% endif %} +</a><br>in {{ run.getTestsetProjectName }}</td> + +{# Testfunction name #} +{% else %} +<td> +{% if run.getName|length > constant('TestsetRun::SHORT_NAME_LENGTH') %} +<span class="clickOnTouch" data-toggle="tooltip" data-placement="top" title="{{ run.getName }}">{{ run.getShortName }}</span> +{% else %} +{{ run.getShortName }} +{% endif %} +</td> +{% endif %} + +{# Duration #} +{% if run.getDuration > 60 %} +{% set durationFormatted = ' (00:' ~ (run.getDuration|round)|date("i:s") ~ ')' %} +{% else %} +{% set durationFormatted = '' %} +{% endif %} +<td class="leftBorder center">{{ run.getDuration }}s<br>{{ durationFormatted }}</td> + +{# Show results as bars (scaled to BAR_AREA px) #} +{% set bar = ((BAR_AREA/maxDuration) * run.getDuration)|round(0, 'floor') %} +{% if (run.getDuration > 0) and (bar == 0) %} +{% set bar = 1 %} +{% endif %} +<td class="center showInLargeDisplay"> +<div> +<div class="floatLeft blueBackground" style="width: {{ bar }}px"> </div> +</div> +</td> +{# Build info #} +{% if run.getResult == constant('testsetRun::RESULT_SUCCESS') %} +{% set resultIcon = 'glyphicon glyphicon-ok green' %} +{% elseif run.getResult == constant('testsetRun::RESULT_FAILURE') %} +{% set resultIcon = 'glyphicon glyphicon-remove red' %} +{% elseif run.getResult == constant('TestfunctionRun::RESULT_SUCCESS') %} +{% set resultIcon = 'glyphicon glyphicon-ok green' %} +{% elseif run.getResult == constant('TestfunctionRun::RESULT_FAILURE') %} +{% set resultIcon = 'glyphicon glyphicon-remove red' %} +{% elseif run.getResult == constant('TestfunctionRun::RESULT_FAILURE_EXPECTED') %} +{% set resultIcon = 'glyphicon glyphicon-remove-sign green' %} +{% elseif run.getResult == constant('TestfunctionRun::RESULT_SUCCESS_UNEXPECTED') %} +{% set resultIcon = 'glyphicon glyphicon-ok-sign red' %} +{% elseif run.getResult == constant('TestfunctionRun::RESULT_SKIP') %} +{% set resultIcon = 'glyphicon glyphicon-ban-circle gray' %} +{% else %} +{% set resultIcon = '' %} +{% endif %} +{% if list == 'testsets' %} +{% set resultTitle = 'testset result: ' ~ run.getResult %} +{% else %} +{% set resultTitle = 'test function result: ' ~ run.getResult %} +{% endif %} +<td class="leftBorder"><small> +<span class="clickOnTouch" data-toggle="tooltip" data-placement="top" title="{{ resultTitle }}"><span class="{{ resultIcon }}"></span></span> +<a href="{{ run.getBuildLink }}" target="_blank"><span class="spaceHorizontal glyphicon glyphicon-folder-open"></span></a> +{{ run.getBranchName }} build on {{ run.getTimestamp }} +<br>{{ run.getConfName }}</small></td> +</tr> +{% endfor %}{# run #} +</tbody> +</table> +</div> {# .table-responsive #} +</div> {# .panel-body #} + +{% endif %}{# runCount #} +</div> {# .panel... #} + +{% if runCount == 0 %} +<div class="alert alert-info" role="alert"> +{% if list == 'testsets' %} +There are not any testsets with duration less than {{ durationLimitSec }}s since {{ sinceDate }}! +{% else %} +The testset {{ testset }} ({{ project }}) either does not have any {{ list }}, +or the duration of all {{ list }} since {{ sinceDate }} is less than {{ durationLimitSec }}s! +{% endif %} +</div> +{% endif %}{# runCount #} |