Skip to content

Instantly share code, notes, and snippets.

@teknologika
Last active September 26, 2018 01:44
Show Gist options
  • Save teknologika/12c1b60acad61360ef54 to your computer and use it in GitHub Desktop.
Save teknologika/12c1b60acad61360ef54 to your computer and use it in GitHub Desktop.
A Testing Status widget for dashing

Description

A Dashing widget to display the number of passing, ignored and failing tests from a test result file in the JUnit XML format.

Dependencies

The following dependencies are required. Please add them to your dashing gemfile.

gem 'nokogiri'

Run bundle install

You will also need to include Chart.min.js from http://www.chartjs.org.

Usage

1. Adjust Job Configuration

As it is quite common, a Junit xml source job is shown below. It requires the junit file locations to be added to the top of the job file, and the duration adjusted.

2. Adjust Dashboard Configuration

Add the following widget HTML snippet for each jql filter to your dashboard erb file.

<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
  <div data-id="unit_test_data" data-view ="Tests" data-title="Unit Tests" ></div>
</li>

Multiple widgets can be shown on a dashboard by repeating the above snippet and changing data-id along with additional, modified copy of the test_job.rb file.

Preview

License

The widget is provided unter the Apache License, Version 2.0. You may obtain a copy of the License at (http://www.apache.org/licenses/LICENSE-2.0)

require 'nokogiri'
# Any junit source file will need to be added to the sources list
sources = {
'system_test_data' => "http://localhost/system_tests.xml",
'unit_test_data' => "http://localhost/unit_tests.xml"
}
# Set up a hash to store the last passing count for each source
# Set everything to zero
last_passing = {}
sources.each do |source, url|
last_passing.store(source,0)
end
passing = 0
SCHEDULER.every '10s', :first_in => 0 do |job|
sources.each do |source, url|
# Reset the status to OK
status = "ok"
# Read the values from a JUnit XML file
begin
@doc = Nokogiri::HTML(open(url))
rescue
puts "\e[33mError reading Junit file: " + url + " \e[0m"
end
if @doc
duration = @doc.at_css("testsuite").attr("time").to_i
ignored = @doc.at_css("testsuite").attr("skipped").to_i
if ignored > 0
status = "danger"
end
failed_tests = @doc.at_css("testsuite").attr("failures").to_i
if failed_tests > 0
status = "warning"
end
total_tests = @doc.at_css("testsuite").attr("tests").to_i
passing = total_tests.to_i - failed_tests - ignored
end
# Note: not run is hardcodded to zero. Setting Not run greater than 0 will introcude a black gap into the chart
send_event(source, { passed: passing, last_passed: last_passing[source],ignored: ignored, failed: failed_tests, not_run:0, duration:duration, status:status})
last_passing[source] = passing
end
end
class Dashing.Tests extends Dashing.Widget
@accessor 'passing', ->
"#{parseInt(@get('passed'))} passing"
@accessor 'failing', ->
if @get('failed')
"#{parseInt(@get('failed'))}"
@accessor 'difference', ->
if @get('last_passed')
last_passed = parseInt(@get('last_passed'))
passed = parseInt(@get('passed'))
if last_passed != 0
diff = Math.abs(Math.round((passed - last_passed) / last_passed * 100))
"#{diff}%"
else
""
@accessor 'arrow', ->
if @get('last_passed')
if parseInt(@get('passed')) > parseInt(@get('last_passed')) then 'icon-arrow-up' else 'icon-arrow-down'
ready: ->
@ctx = $(@node).find('.chart-area')[0].getContext("2d");
@doughnutData = [
# Add the passing tests
value: parseInt(@get('passed'))
color: "#56BA3A"
highlight: "#56BA3A"
label: "Passing"
,
# Add the ignored tests
value: parseInt(@get('ignored'))
color: "#E6BB32"
highlight: "#E6BB32"
label: "Ignored"
,
# Add the failed tests
value: parseInt(@get('failed'))
color:"#EE4042"
highlight: "#EE4042"
label: "Failed"
,
# Add the not run if you want a gap
value: parseInt(@get('not_run'))
color: "#222222"
highlight: "#222222"
label: "Not Run"
]
@myDoughnut = new Chart(@ctx).Doughnut(@doughnutData,
responsive: true,
segmentShowStroke : false
)
onData: (data) ->
if @myDoughnut
@myDoughnut.segments[0].value = parseInt(@get('passed'))
@myDoughnut.segments[1].value = parseInt(@get('ignored'))
@myDoughnut.segments[2].value = parseInt(@get('failed'))
@myDoughnut.segments[3].value = parseInt(@get('not_run'))
@myDoughnut.update();
# Set the widget background colour needs to go red when tests fail
failed = parseInt(@get('failed'))
if failed = 0
$(@node).css('background-color', '##EE4042')
else
$(@node).css('background-color', '#222222')
if data.status
# clear existing "status-*" classes
$(@get('node')).attr 'class', (i,c) ->
c.replace /\bstatus-\S+/g, ''
# add new class
$(@get('node')).addClass "status-#{data.status}"
<h1 class="title" data-bind="title"></h1>
<div class="canvas-holder">
<canvas id="chart-area" class="chart-area"/>
</div>
<p class="change-rate">
<span data-bind="passing"></span>&nbsp;<span></span><i data-bind-class="arrow"></i>&nbsp;(<span data-bind="difference"></span>)
</p>
<p class="test-duration">Duration <span class="test-duration" data-bind="duration"></span> seconds</p>
<p class="updated-at" data-bind="updatedAtMessage"></p>
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color: #000;
$value-color: #fff;
$title-color: rgba(255, 255, 255, 0.7);
$moreinfo-color: rgba(255, 255, 255, 0.7);
$chart-width: 100%;
$chart-height: 100%;
// ----------------------------------------------------------------------------
// Widget-number styles
// ----------------------------------------------------------------------------
.widget-tests {
background-color: $background-color;
.title {
color: $title-color;
font-size: 2vw;
}
.value {
color: $value-color;
}
.change-rate {
font-weight: 500;
// padding-top:20px;
// padding-bottom:20px;
color: $value-color;
font-size: 1.5vw;
}
.more-info {
color: $moreinfo-color;
}
.updated-at {
color: rgba(0, 0, 0, 0.3);
font-size: 1vw;
}
.test-duration {
color: rgba(255, 255, 255, 0.7);
font-size: 1vw;
}
canvas#chart-area.chart-area
{
width: $chart-width !important;
height: $chart-height !important;
}
}
@larrycai
Copy link

new to Dashing, which folder is used to put Chart.min.js ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment