StepStats 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -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
- data/lib/stepstats.rb +3 -0
- metadata +65 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 54a8bf062647be15c2dcbdaa15c69dbeafac7db3
|
4
|
+
data.tar.gz: 6c0bab4ea16976b07c304438b64bc4c623590a92
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b7fe379502ac59d7105fc9784f93f061417f98129a305739d0395551e606fe566057de2005e8df9befc32669a618f13b94595a1ecd2561ad57304d275552dd41
|
7
|
+
data.tar.gz: f13724ace411a0e48ca5c1ecb63130c23b07d45bf5bb45a86dbc4b85aeffeb943c50f5a5dd6e0079aa33fb2205a73e7f8819d7c43c7bb4c1fe561e14c1376ba3
|
@@ -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! 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>
|
data/lib/stepstats.rb
ADDED
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: StepStats
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
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/stats.rb
|
35
|
+
- lib/step_stats/step.rb
|
36
|
+
- lib/step_stats/step_stats_formatter.rb
|
37
|
+
- lib/step_stats/table_partial.erb
|
38
|
+
- lib/step_stats/template.erb
|
39
|
+
- lib/stepstats.rb
|
40
|
+
homepage: https://github.com/sundus-y/StepStats
|
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: []
|