diff --git a/tcms/settings/common.py b/tcms/settings/common.py index a263fa3449..17037fc8a1 100644 --- a/tcms/settings/common.py +++ b/tcms/settings/common.py @@ -107,6 +107,7 @@ (_('Breakdown'), reverse_lazy('testing-breakdown')), (_('Status matrix'), reverse_lazy('testing-status-matrix')), (_('Execution trends'), reverse_lazy('testing-execution-trends')), + (_('TestCase health'), reverse_lazy('test-case-health')), ]), ('More coming soon', 'http://kiwitcms.org/blog/kiwi-tcms-team/2019/03/03/legacy-reports-become-telemetry/'), diff --git a/tcms/telemetry/static/telemetry/js/testing/test-case-health.js b/tcms/telemetry/static/telemetry/js/testing/test-case-health.js new file mode 100644 index 0000000000..84840f3fe6 --- /dev/null +++ b/tcms/telemetry/static/telemetry/js/testing/test-case-health.js @@ -0,0 +1,94 @@ +$(document).ready(() => { + loadInitialProduct(); + loadInitialTestPlans(); + + document.getElementById('id_product').onchange = () => { + update_version_select_from_product(); + update_build_select_from_product(true); + updateTestPlanSelectFromProduct(drawPage); + }; + + document.getElementById('id_version').onchange = drawPage; + document.getElementById('id_build').onchange = drawPage; + document.getElementById('id_test_plan').onchange = drawPage; + + $('#id_after').on('dp.change', drawPage); + $('#id_before').on('dp.change', drawPage); + + drawPage(); +}) + +function drawPage() { + const query = {}; + + const productId = $('#id_product').val(); + if (productId) { + query['case__plan__product'] = productId; + } + + const versionId = $('#id_version').val(); + if (versionId) { + query['case__plan__product_version'] = versionId; + } + + const buildId = $('#id_build').val(); + if (buildId) { + query['build_id'] = buildId; + } + + const testPlanId = $('#id_test_plan').val(); + if (testPlanId) { + query['case__plan__plan_id'] = testPlanId; + } + + const dateBefore = $('#id_before'); + if (dateBefore.val()) { + query['close_date__lte'] = dateBefore.data('DateTimePicker').date().format('YYYY-MM-DD 23:59:59'); + } + + const dateAfter = $('#id_after'); + if (dateAfter.val()) { + query['close_date__gte'] = dateAfter.data('DateTimePicker').date().format('YYYY-MM-DD 00:00:00'); + } + + jsonRPC("Testing.test_case_health", query, data => { + drawTable('#test-case-health-table', data); + }) +} + +function drawTable(selector, data) { + $(`${selector} > tbody`).remove() + + $(selector).DataTable({ + data: data, + columns: [ + { + data: null, + render: renderTestCaseColumn + }, + { + data: null, + render: renderFailedExecutionsColumn + }, + { + data: null, + render: renderPercentColumn + }, + ], + paging: false, + ordering: false, + dom: "t" + }); +} + +function renderTestCaseColumn(data) { + return `TC-${data.case_id}: ${data.case_summary}`; +} + +function renderFailedExecutionsColumn(data) { + return `${data.count.fail} of ${data.count.all}`; +} + +function renderPercentColumn(data) { + return Number.parseFloat(data.count.fail / data.count.all * 100).toFixed(1); +} diff --git a/tcms/telemetry/templates/telemetry/testing/test-case-health.html b/tcms/telemetry/templates/telemetry/testing/test-case-health.html new file mode 100644 index 0000000000..399e3afb56 --- /dev/null +++ b/tcms/telemetry/templates/telemetry/testing/test-case-health.html @@ -0,0 +1,100 @@ +{% extends "base.html" %} +{% load i18n %} +{% load static %} + +{% block title %}{% trans "TestCase Health" %}{% endblock %} + +{% block contents %} +
+ +
+
+ +
+ +
+ + +
+ +
+ + +
+ +
+
+ +
+ +
+ +
+ + +
+
+ + + + +
+ + {% include "datetimepicker_script.html" with selector="#id_after" %} +
+ + +
+
+ + + + +
+ + {% include "datetimepicker_script.html" with selector="#id_before" %} +
+
+
+ + + + + + + + + + + + +
{% trans "Most frequently failing test cases" %}
{% trans "Test Case" %} {% trans "Failed executions" %} {% trans "% of failed executions" %}
+
+ + + + + + + + + + + +{% endblock %} diff --git a/tcms/telemetry/urls.py b/tcms/telemetry/urls.py index d134760ae6..ebd6bb2eaf 100644 --- a/tcms/telemetry/urls.py +++ b/tcms/telemetry/urls.py @@ -8,4 +8,6 @@ name='testing-status-matrix'), url(r'^testing/execution-trends/$', views.TestingExecutionTrendsView.as_view(), name='testing-execution-trends'), + url(r'^testing/test-case-health/$', views.TestingTestCaseHealth.as_view(), + name='test-case-health'), ] diff --git a/tcms/telemetry/views.py b/tcms/telemetry/views.py index 4c303dd1ea..5766bd4299 100644 --- a/tcms/telemetry/views.py +++ b/tcms/telemetry/views.py @@ -16,3 +16,8 @@ class TestingStatusMatrixView(TemplateView): class TestingExecutionTrendsView(TemplateView): template_name = 'telemetry/testing/execution-trends.html' + + +class TestingTestCaseHealth(TemplateView): + + template_name = 'telemetry/testing/test-case-health.html'