StepStats 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ require 'step_stats/step'
2
+ require 'step_stats/stats'
3
+ require 'step_stats/step_stats_formatter'
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: []