step-stats 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/step-stats.rb +3 -0
- data/lib/step_stats/stats.rb +54 -0
- data/lib/step_stats/step.rb +61 -0
- data/lib/step_stats/step_stats_formatter.rb +33 -0
- data/lib/step_stats/table_partial.erb +32 -0
- data/lib/step_stats/template.erb +141 -0
- metadata +65 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a88024d8c94f650f2d8c148fae871aa264c116f8
|
4
|
+
data.tar.gz: 4baee00e3b90efdbc040161c9a8027de31c30caf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4d8c7c95c70efe349294c2d80dcc5439ac8a50ec640ba359a4f05fe4f102a92e3b65486e55289b839246b1cc4ebad0fdc2ba8dc18a818141a1798c85a151d95a
|
7
|
+
data.tar.gz: f98e44c0ae794ee4d2bcba9b9955f981dd339ba5433481c6bd10f5a18aa9a47135b10fd08fc0ec86bb868f1ea75883d98405abc17149019ef53e49d4047dcaba
|
data/lib/step-stats.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module StepStats
|
2
|
+
class Stats
|
3
|
+
attr_accessor :stats
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
@stats = {}
|
7
|
+
@step_counter = "STEP-000"
|
8
|
+
@steps = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_stat step_definition, duration, status, location
|
12
|
+
step_number = get_step_number step_definition.regexp_source
|
13
|
+
if @stats[step_number].nil?
|
14
|
+
@stats[step_number] = Step.new(step_definition.regexp_source, step_definition.file_colon_line)
|
15
|
+
end
|
16
|
+
step_entry = {duration: duration, status: status, location: location}
|
17
|
+
@stats[step_number].add step_entry
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_step_number step_regx
|
21
|
+
@steps[step_regx] = @step_counter.next!.dup if @steps[step_regx].nil?
|
22
|
+
@steps[step_regx]
|
23
|
+
end
|
24
|
+
|
25
|
+
def percent step,rounding='ceil'
|
26
|
+
((step.total/total_time)*100).send(rounding)
|
27
|
+
end
|
28
|
+
|
29
|
+
def stats
|
30
|
+
@stats.values.sort_by{|step| step.avg * step.count}.reverse
|
31
|
+
end
|
32
|
+
|
33
|
+
def top30count
|
34
|
+
@stats.values.sort_by{|step| step.count}.reverse[0..top30]
|
35
|
+
end
|
36
|
+
|
37
|
+
def top30time
|
38
|
+
@stats.values.sort_by{|step| step.avg}.reverse[0..top30]
|
39
|
+
end
|
40
|
+
|
41
|
+
def top30
|
42
|
+
(@stats.values.count*0.3).ceil
|
43
|
+
end
|
44
|
+
|
45
|
+
def total_time
|
46
|
+
@stats.values.inject(0){|accum,step| accum+step.total}.to_f
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_chart_data
|
50
|
+
@stats.values.each.map{|s|[s.name,s.total,s.location]}.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module StepStats
|
2
|
+
class Step
|
3
|
+
attr_accessor :name,:definition,:location
|
4
|
+
|
5
|
+
def initialize(step_def_name, step_def_location)
|
6
|
+
@name = step_def_name
|
7
|
+
@location = step_def_location
|
8
|
+
# An Array of hashs with duration, status and location
|
9
|
+
# step_info = {duration: 5.21692, status: :pass, location: 'feature/...feature:219'}
|
10
|
+
@step_entries = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def durations
|
14
|
+
@durations || @step_entries.map{|step| step[:duration]}
|
15
|
+
end
|
16
|
+
|
17
|
+
def add step_entry
|
18
|
+
@step_entries << step_entry
|
19
|
+
end
|
20
|
+
|
21
|
+
def min
|
22
|
+
durations.min.to_f.round(3)
|
23
|
+
end
|
24
|
+
|
25
|
+
def max
|
26
|
+
durations.max.to_f.round(3)
|
27
|
+
end
|
28
|
+
|
29
|
+
def avg
|
30
|
+
(total / count.to_f).round(3)
|
31
|
+
end
|
32
|
+
|
33
|
+
def total
|
34
|
+
durations.sum
|
35
|
+
end
|
36
|
+
|
37
|
+
def count
|
38
|
+
durations.count
|
39
|
+
end
|
40
|
+
|
41
|
+
def stddev
|
42
|
+
return 0.to_f if count == 1
|
43
|
+
total = durations.inject(0){|accum, i| accum +(i-avg)**2 }
|
44
|
+
variance = total/(count - 1).to_f
|
45
|
+
Math.sqrt(variance).round(3)
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_chart_data
|
49
|
+
@step_entries.map(&:values).each_with_index.map do |s, index|
|
50
|
+
step_entry = [(index + 1).to_s,s[0]]
|
51
|
+
if s[1] == :passed
|
52
|
+
step_entry << "green"
|
53
|
+
else
|
54
|
+
step_entry << "red"
|
55
|
+
end
|
56
|
+
step_entry << "Location: #{s[2]} \n Time: #{s[0]} seconds"
|
57
|
+
step_entry
|
58
|
+
end.to_s
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'cucumber/formatter/pretty'
|
3
|
+
|
4
|
+
module StepStats
|
5
|
+
class Formatter < Cucumber::Formatter::Pretty
|
6
|
+
def initialize(step_mother, io, options)
|
7
|
+
@sss = Stats.new
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def before_step(step)
|
12
|
+
@start_time = Time.now
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line)
|
17
|
+
@duration = Time.now - @start_time
|
18
|
+
@sss.add_stat(step_match.step_definition,@duration,status,file_colon_line) if @duration > 0
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def after_features(*args)
|
23
|
+
@path = File.dirname(__FILE__)
|
24
|
+
template = File.read(@path+"/template.erb")
|
25
|
+
@data = @sss.stats
|
26
|
+
result = ERB.new(template, 0, "", "@html").result(binding)
|
27
|
+
stats_html_file = File.new('tmp/step_stats.html','w')
|
28
|
+
stats_html_file.write(result)
|
29
|
+
stats_html_file.close
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<table id="all-table" class="data-table table table-hover">
|
2
|
+
<thead>
|
3
|
+
<td>Step</td>
|
4
|
+
<td>Definition</td>
|
5
|
+
<td>Avg</td>
|
6
|
+
<td>SD</td>
|
7
|
+
<td>Max</td>
|
8
|
+
<td>Min</td>
|
9
|
+
<td>Count</td>
|
10
|
+
</thead>
|
11
|
+
<% @data.each_with_index do |stat,index| %>
|
12
|
+
<tr data-durations="<%= ERB::Util.h(stat.to_chart_data) %>">
|
13
|
+
<td>
|
14
|
+
<span><%= index+1 %></span>
|
15
|
+
<span class="percentage">
|
16
|
+
<%= @sss.percent(stat,'floor') %>%
|
17
|
+
</span>
|
18
|
+
</td>
|
19
|
+
<td title="<%= stat.location %>" style="background: -webkit-linear-gradient(left, #DC4141 <%= @sss.percent(stat) %>%, white <%= @sss.percent(stat) %>%);"><%= stat.name %></td>
|
20
|
+
<td><%= stat.avg %></td>
|
21
|
+
<td><%= stat.stddev %></td>
|
22
|
+
<td><%= stat.max %></td>
|
23
|
+
<td><%= stat.min %></td>
|
24
|
+
<td><%= stat.count %></td>
|
25
|
+
</tr>
|
26
|
+
<tr>
|
27
|
+
<td colspan="7">
|
28
|
+
<div id="chart-<%= index+1 %>" class="details_chart">Details</div>
|
29
|
+
</td>
|
30
|
+
</tr>
|
31
|
+
<% end %>
|
32
|
+
</table>
|
@@ -0,0 +1,141 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Cucumber Steps Stats</title>
|
4
|
+
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
|
5
|
+
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
6
|
+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
7
|
+
<script type="text/javascript"
|
8
|
+
src="https://www.google.com/jsapi?autoload={
|
9
|
+
'modules':[{
|
10
|
+
'name':'visualization',
|
11
|
+
'version':'1',
|
12
|
+
'packages':['corechart']
|
13
|
+
}]
|
14
|
+
}"></script>
|
15
|
+
<style>
|
16
|
+
nav#top-menu{border-color: #2F2F2F!important;}
|
17
|
+
body{padding-top: 50px;}
|
18
|
+
ul.side-bar{height: 100%;}
|
19
|
+
.tabs-left > div.side-bar {position:fixed; height: 100%;}
|
20
|
+
.tabs-left > div.tab-content {margin-left: 200px;}
|
21
|
+
.tabs-left > div > .nav-tabs > li{float: none;}
|
22
|
+
.tabs-left > div > .nav-tabs > li > a{min-width: 74px;margin-right: 0;margin-bottom: 3px;}
|
23
|
+
.tabs-left > div > .nav-tabs {background-color: #222;float: left;margin-right: 19px;border-right: 1px solid #ddd;}
|
24
|
+
.tabs-left > div > .nav-tabs > li > a {margin-right: -1px;-webkit-border-radius: 4px 0 0 4px;-moz-border-radius: 4px 0 0 4px;border-radius: 4px 0 0 4px;color:#9d9d9d}
|
25
|
+
.tabs-left > div > .nav-tabs > li > a:hover,
|
26
|
+
.tabs-left > div > .nav-tabs > li > a:focus {border-color: #eeeeee #5f635d #eeeeee #eeeeee;}
|
27
|
+
.tabs-left > div > .nav-tabs .active > a,
|
28
|
+
.tabs-left > div > .nav-tabs .active > a:hover,
|
29
|
+
.tabs-left > div > .nav-tabs .active > a:focus {border-color: #ddd transparent #ddd #ddd;*border-right-color: #ffffff;}
|
30
|
+
.tabs-left > div > .tab-pane {float: left;width: 99%;}
|
31
|
+
span.percentage{float: right;}
|
32
|
+
div.details_chart{height: 400px;}
|
33
|
+
div.tps_chart{height: 800px;}
|
34
|
+
</style>
|
35
|
+
</head>
|
36
|
+
<body>
|
37
|
+
<nav id="top-menu" class="navbar navbar-inverse navbar-fixed-top">
|
38
|
+
<div class="container-fluid">
|
39
|
+
<div class="navbar-header">
|
40
|
+
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
41
|
+
<span class="sr-only">Toggle navigation</span>
|
42
|
+
<span class="icon-bar"></span>
|
43
|
+
<span class="icon-bar"></span>
|
44
|
+
<span class="icon-bar"></span>
|
45
|
+
</button>
|
46
|
+
<a class="navbar-brand" href="#"><%= Rails.application.class.parent_name %> - Cucumber Steps Stats</a>
|
47
|
+
</div>
|
48
|
+
<div id="navbar" class="navbar-collapse collapse">
|
49
|
+
<ul class="nav navbar-nav navbar-right">
|
50
|
+
<li><a href="#dashboard">Dashboard</a></li>
|
51
|
+
</ul>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
</nav>
|
55
|
+
<div class="tabbable tabs-left">
|
56
|
+
<!-- Nav tabs -->
|
57
|
+
<div class="side-bar">
|
58
|
+
<ul class="nav nav-tabs side-bar" role="tablist">
|
59
|
+
<li role="presentation" class="active"><a href="#all" aria-controls="all" role="tab" data-toggle="tab">All Steps</a></li>
|
60
|
+
<li role="presentation"><a href="#top30time" aria-controls="top30time" role="tab" data-toggle="tab">Top 30% Steps by Time</a></li>
|
61
|
+
<li role="presentation"><a href="#top30count" aria-controls="top30count" role="tab" data-toggle="tab">Top 30% Steps by Count</a></li>
|
62
|
+
<li role="presentation"><a href="#timeperstep" aria-controls="timeperstep" role="tab" data-toggle="tab">Time Spent per Step</a></li>
|
63
|
+
</ul>
|
64
|
+
</div>
|
65
|
+
<!-- Tab panes -->
|
66
|
+
<div class="tab-content table-responsive">
|
67
|
+
<div role="tabpanel" class="tab-pane active" id="all">
|
68
|
+
<%= ERB.new(File.read(@path+"/table_partial.erb")).result(binding) %>
|
69
|
+
</div>
|
70
|
+
<div role="tabpanel" class="tab-pane" id="top30time">
|
71
|
+
<% @data = @sss.top30time %>
|
72
|
+
<%= ERB.new(File.read(@path+"/table_partial.erb")).result(binding) %>
|
73
|
+
</div>
|
74
|
+
<div role="tabpanel" class="tab-pane" id="top30count">
|
75
|
+
<% @data = @sss.top30count %>
|
76
|
+
<%= ERB.new(File.read(@path+"/table_partial.erb")).result(binding) %>
|
77
|
+
</div>
|
78
|
+
<div role="tabpanel" class="tab-pane" id="timeperstep">
|
79
|
+
<span data-results="<%= ERB::Util.h(@sss.to_chart_data) %>"></span>
|
80
|
+
<div class="tps_chart"></div>
|
81
|
+
</div>
|
82
|
+
</div>
|
83
|
+
</div>
|
84
|
+
<script>
|
85
|
+
$(document).ready(function(){
|
86
|
+
$.each($(".data-table"),function(i,table){$(table).find("tr:odd").addClass("master");});
|
87
|
+
$.each($(".data-table"),function(i,table){
|
88
|
+
$(table).find("tr:not(.master)").hide();
|
89
|
+
$(table).find("tr:first-child").show();
|
90
|
+
$(table).find("tr.master").click(function(){
|
91
|
+
var chart_data = eval($(this).data("durations"));
|
92
|
+
$(this).next("tr").toggle();
|
93
|
+
drawDetailsChart(this, chart_data);
|
94
|
+
});
|
95
|
+
});
|
96
|
+
$("a[href='#timeperstep']").click(function(){
|
97
|
+
drawTimePerStepChart();
|
98
|
+
});
|
99
|
+
});
|
100
|
+
function drawDetailsChart(elem,raw_data) {
|
101
|
+
var dataTable= new google.visualization.DataTable();
|
102
|
+
dataTable.addColumn('string', 'Count');
|
103
|
+
dataTable.addColumn('number', 'Duration in Seconds');
|
104
|
+
dataTable.addColumn({type: 'string', role: 'style' });
|
105
|
+
dataTable.addColumn({type: 'string', role: 'tooltip'});
|
106
|
+
|
107
|
+
dataTable.addRows(raw_data);
|
108
|
+
|
109
|
+
var options = {
|
110
|
+
title: 'Timming of all the calls for the above step.',
|
111
|
+
vAxis: {viewWindow: {min:0} },
|
112
|
+
legend: { position: 'bottom' }
|
113
|
+
};
|
114
|
+
|
115
|
+
var chart = new google.visualization.ColumnChart($(elem).next().find('.details_chart')[0]);
|
116
|
+
chart.draw(dataTable, options);
|
117
|
+
}
|
118
|
+
function drawTimePerStepChart() {
|
119
|
+
var chart_data = eval($('div#timeperstep').find('span').data("results"));
|
120
|
+
|
121
|
+
var dataTable= new google.visualization.DataTable();
|
122
|
+
dataTable.addColumn('string', 'Name');
|
123
|
+
dataTable.addColumn('number', 'Duration in Seconds');
|
124
|
+
dataTable.addColumn({type: 'string', role: 'tooltip'});
|
125
|
+
|
126
|
+
dataTable.addRows(chart_data);
|
127
|
+
|
128
|
+
var options = {
|
129
|
+
title: 'Which Step took most of the time ?',
|
130
|
+
is3D: true
|
131
|
+
};
|
132
|
+
|
133
|
+
var chart = new google.visualization.PieChart($('div#timeperstep').find('.tps_chart')[0]);
|
134
|
+
setTimeout(function(){
|
135
|
+
chart.draw(dataTable, options);
|
136
|
+
},1);
|
137
|
+
|
138
|
+
}
|
139
|
+
</script>
|
140
|
+
</body>
|
141
|
+
</html>
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: step-stats
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sundus Yousuf
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cucumber
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Cucumber formatter that generates stats on all steps that are used during
|
28
|
+
testing.
|
29
|
+
email: sundus2y@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- lib/step-stats.rb
|
35
|
+
- lib/step_stats/stats.rb
|
36
|
+
- lib/step_stats/step.rb
|
37
|
+
- lib/step_stats/step_stats_formatter.rb
|
38
|
+
- lib/step_stats/table_partial.erb
|
39
|
+
- lib/step_stats/template.erb
|
40
|
+
homepage: https://github.com/sundus-y/step-stats
|
41
|
+
licenses:
|
42
|
+
- MIT
|
43
|
+
metadata: {}
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
requirements: []
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 2.4.3
|
61
|
+
signing_key:
|
62
|
+
specification_version: 4
|
63
|
+
summary: Cucumber formatter that generates stats on all steps that are used during
|
64
|
+
testing.
|
65
|
+
test_files: []
|