jmeter-reports 0.0.5 → 0.0.6

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.
data/Gemfile CHANGED
@@ -1,10 +1,10 @@
1
1
  source :rubygems
2
2
 
3
- gem 'rake'
4
3
  gem 'descriptive_statistics'
5
4
  gem 'formatador'
6
5
 
7
- group :test, :development do
6
+ group :test do
7
+ gem 'rake'
8
8
  gem 'minitest'
9
9
  gem 'minitest-colorize'
10
10
  gem 'pry'
@@ -12,10 +12,17 @@ GEM
12
12
  coderay (~> 1.0.5)
13
13
  method_source (~> 0.8)
14
14
  slop (~> 3.3.1)
15
- rake (10.0.2)
15
+ pry (0.9.10-java)
16
+ coderay (~> 1.0.5)
17
+ method_source (~> 0.8)
18
+ slop (~> 3.3.1)
19
+ spoon (~> 0.0)
20
+ rake (10.0.3)
16
21
  slop (3.3.3)
22
+ spoon (0.0.1)
17
23
 
18
24
  PLATFORMS
25
+ java
19
26
  ruby
20
27
 
21
28
  DEPENDENCIES
@@ -0,0 +1,51 @@
1
+ # JMeter Reports [![Build Status](https://travis-ci.org/marcoshack/jmeter-reports.png?branch=master)](https://travis-ci.org/marcoshack/jmeter-reports)
2
+
3
+ Command-line tools for JMeter report processing. Right now it supports only CSV summary reports processing to show:
4
+
5
+ * Test execution time
6
+ * Total and transaction throughputs
7
+ * Transaction samples/errors
8
+ * Min / Avg / Max / Standard Deviation
9
+ * 90 and 95 response time percentiles
10
+
11
+ # Install
12
+
13
+ Requires Ruby >= 1.9
14
+
15
+ gem install jmeter-reports
16
+
17
+ # Usage
18
+
19
+ jmeter-reports <path_to_summary_report_file.csv>
20
+
21
+ will show you something like this:
22
+
23
+ Start: 2012-12-14 16:22:53 -0200
24
+ End: 2012-12-14 16:28:33 -0200
25
+ Duration: 340 secs
26
+ Total requests: 10520
27
+ Average throughput: 30 RPS
28
+
29
+ +--------------------------+------+--------+---------+-----+------+-------+--------+------------+
30
+ | label | reqs | errors | err_pct | min | avg | max | sd | avg_thrput |
31
+ +--------------------------+------+--------+---------+-----+------+-------+--------+------------+
32
+ | GET session/new | 2651 | 18 | 0.6 | 49 | 742 | 10062 | 1576ms | 7.797 RPS |
33
+ +--------------------------+------+--------+---------+-----+------+-------+--------+------------+
34
+ | POST session | 2629 | 562 | 21.3 | 272 | 3104 | 10093 | 3882ms | 7.732 RPS |
35
+ +--------------------------+------+--------+---------+-----+------+-------+--------+------------+
36
+ | GET session/:id | 2620 | 0 | 0.0 | 21 | 227 | 8099 | 682ms | 7.705 RPS |
37
+ +--------------------------+------+--------+---------+-----+------+-------+--------+------------+
38
+ | Login | 2620 | 570 | 21.7 | 377 | 4185 | 25724 | 4401ms | 7.705 RPS |
39
+ +--------------------------+------+--------+---------+-----+------+-------+--------+------------+
40
+
41
+ you can also pass a list of summary report files to get an overview of each one. Let say you've a bunch of summary files named _summary\_report\_N.csv_:
42
+
43
+ jmeter-reports summary_report_*
44
+
45
+ +----------------------+---------------------------+---------------------------+---------+------------+
46
+ | filename | start | end | samples | avg_thrput |
47
+ +----------------------+---------------------------+---------------------------+---------+------------+
48
+ | summary_report_1.csv | 2012-12-11 10:47:32 -0200 | 2012-12-11 10:47:34 -0200 | 9 | 3 RPS |
49
+ +----------------------+---------------------------+---------------------------+---------+------------+
50
+ | summary_report_2.csv | 2012-12-11 10:47:32 -0200 | 2012-12-11 10:47:35 -0200 | 16 | 4 RPS |
51
+ +----------------------+---------------------------+---------------------------+---------+------------+
@@ -1,41 +1,43 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'formatador'
4
+ require 'descriptive_statistics'
5
+
3
6
  $:.push File.join(File.dirname(__FILE__), '..'), File.join(File.dirname(__FILE__), '..','lib')
7
+ require 'jmeter/reports'
4
8
 
5
- begin
6
- require 'bundler/setup'
7
- Bundler.require(:default)
8
- rescue LoadError
9
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
9
+ def version_message
10
+ "JMeter Reports version #{JmeterReports::VERSION}"
10
11
  end
11
12
 
12
- require 'jmeter/reports'
13
+ def usage_message
14
+ """#{version_message}
13
15
 
14
- if ARGV.empty?
15
- puts "Usage: #{File.basename(__FILE__)} <report_file>"
16
- exit 1
16
+ Usage:
17
+ #{File.basename(__FILE__)} <report_file> | show the summary report for the given file
18
+ #{File.basename(__FILE__)} <report_file_list> | show a overview list of all report files
19
+ #{File.basename(__FILE__)} --version | show jmeter-reports version
20
+ #{File.basename(__FILE__)} --help | show this help page
21
+ """
17
22
  end
18
23
 
19
- begin
20
- if ARGV.size > 1
21
- puts "filename,elapsed,requests,avg_throughput"
22
- ARGV.each do |filename|
23
- r = Jmeter::SummaryReport::Report.create(filename)
24
- puts "#{filename},#{r.elapsed},#{r.total_requests},#{r.avg_throughput}"
25
- end
24
+ def process_report(file_list)
25
+ if file_list.size > 1
26
+ JmeterReports::Views::AsciiSummaryList.new(file_list).render
26
27
  else
27
- report = Jmeter::SummaryReport::Report.create(ARGV.first)
28
- puts ""
29
- puts " Start: #{report.start_date}"
30
- puts " End: #{report.end_date}"
31
- puts " Duration: #{report.elapsed} secs"
32
- puts " Total requests: #{report.total_requests}"
33
- puts "Average throughput: #{report.avg_throughput} RPS"
34
- puts ""
35
- Formatador.display_table(report.table_data, [:label,:reqs,:errors,:err_pct,:min,:avg,:max,:sd,:avg_thrput])
36
- puts ""
28
+ JmeterReports::Views::AsciiSummary.new(JmeterReports::Summary.create(file_list.first)).render
29
+ end
30
+ end
31
+
32
+ if ARGV.empty? || ARGV[0] == '--help'
33
+ puts usage_message
34
+ elsif ARGV[0] == "--version"
35
+ puts version_message
36
+ else
37
+ begin
38
+ process_report(ARGV)
39
+ rescue Exception => e
40
+ puts e.message
41
+ exit 2
37
42
  end
38
- rescue Exception => e
39
- puts e.message
40
- exit 2
41
43
  end
@@ -5,7 +5,7 @@ require 'jmeter/reports'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "jmeter-reports"
8
- gem.version = Jmeter::Reports::VERSION
8
+ gem.version = JmeterReports::VERSION
9
9
  gem.authors = ["Marcos Hack"]
10
10
  gem.email = ["marcos.hack@gmail.com"]
11
11
  gem.description = %q{JMeter Reports}
@@ -19,10 +19,10 @@ Gem::Specification.new do |gem|
19
19
 
20
20
  gem.required_ruby_version = '>= 1.9'
21
21
 
22
- gem.add_runtime_dependency "bundler"
23
22
  gem.add_runtime_dependency "descriptive_statistics"
24
23
  gem.add_runtime_dependency "formatador"
25
-
24
+
25
+ gem.add_development_dependency "bundler"
26
26
  gem.add_development_dependency "rake"
27
27
  gem.add_development_dependency "minitest", "~> 3"
28
28
  gem.add_development_dependency "minitest-colorize"
@@ -1,4 +1,9 @@
1
- require 'jmeter/summary_report/report'
2
- require 'jmeter/summary_report/report_item'
3
- require 'jmeter/summary_report/result_line'
4
- require 'jmeter/reports/version'
1
+ require 'jmeter/reports/summary'
2
+ require 'jmeter/reports/summary_item'
3
+ require 'jmeter/reports/summary_line'
4
+ require 'jmeter/reports/views/ascii_summary'
5
+ require 'jmeter/reports/views/ascii_summary_list'
6
+
7
+ module JmeterReports
8
+ VERSION = "0.0.6"
9
+ end
@@ -0,0 +1,62 @@
1
+ module JmeterReports
2
+ class Summary
3
+ CSV_HEADER = "timeStamp,elapsed,label,responseCode,responseMessage,threadName,"+
4
+ "dataType,success,bytes,grpThreads,allThreads,URL,Latency\n"
5
+
6
+ def initialize
7
+ @items = {}
8
+ @req_count = 0
9
+ end
10
+
11
+ def self.create(summary_report_file_path)
12
+ report = Summary.new
13
+ csv_report = File.open(summary_report_file_path,'r')
14
+
15
+ unless csv_report.readline == CSV_HEADER
16
+ raise Exception.new("Invalid CSV report: #{summary_report_file_path}")
17
+ end
18
+
19
+ csv_report.each_line do |line|
20
+ next if line.start_with?("timeStamp,") # ignore header
21
+ report.add(SummaryLine.parse(line))
22
+ end
23
+ return report
24
+ end
25
+
26
+ def add(line)
27
+ @items[line.label] = SummaryItem.new(line.label) if @items[line.label].nil?
28
+ @items[line.label].add(line)
29
+ @req_count += 1
30
+ @start_ms = line.timestamp if @start_ms.nil? || line.timestamp < @start_ms
31
+ @end_ms = line.timestamp if @end_ms.nil? || line.timestamp > @end_ms
32
+ end
33
+
34
+ def elapsed_in_ms
35
+ @end_ms - @start_ms
36
+ end
37
+
38
+ def elapsed
39
+ (self.elapsed_in_ms / 1000.0).ceil
40
+ end
41
+
42
+ def avg_throughput
43
+ @req_count / self.elapsed
44
+ end
45
+
46
+ def items
47
+ @items.values
48
+ end
49
+
50
+ def total_requests
51
+ @req_count
52
+ end
53
+
54
+ def start_date
55
+ Time.at(@start_ms / 1000.0)
56
+ end
57
+
58
+ def end_date
59
+ Time.at(@end_ms / 1000.0)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,68 @@
1
+ require 'descriptive_statistics'
2
+
3
+ module JmeterReports
4
+ class SummaryItem
5
+ def initialize(label)
6
+ @label = label
7
+ @items = []
8
+ @error_count = 0
9
+ @req_count = 0
10
+ end
11
+
12
+ def add(line)
13
+ @error_count += 1 if line.error?
14
+ @items << line.elapsed
15
+ @req_count += 1
16
+ @start_ms = line.timestamp if @start_ms.nil? || line.timestamp < @start_ms
17
+ @end_ms = line.timestamp if @end_ms.nil? || line.timestamp > @end_ms
18
+ end
19
+
20
+ def elapsed_in_ms
21
+ @end_ms - @start_ms
22
+ end
23
+
24
+ def elapsed
25
+ (self.elapsed_in_ms / 1000.0).ceil
26
+ end
27
+
28
+ def avg_throughput
29
+ @req_count > 1 ? @req_count / self.elapsed.to_f : 0.0
30
+ end
31
+
32
+ def size
33
+ @items.size
34
+ end
35
+
36
+ def errors
37
+ @error_count
38
+ end
39
+
40
+ def error_rate
41
+ @error_count / self.size.to_f
42
+ end
43
+
44
+ def percentil(percentil)
45
+ @items.sort[((percentil / 100.0) * @items.size).ceil]
46
+ end
47
+
48
+ def min
49
+ @items.min
50
+ end
51
+
52
+ def avg
53
+ @items.reduce { |n,s| s += n } / @items.size
54
+ end
55
+
56
+ def max
57
+ @items.max
58
+ end
59
+
60
+ def sd
61
+ @items.standard_deviation.to_i
62
+ end
63
+
64
+ def label
65
+ @label
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,33 @@
1
+ # Representation of a summary report result line.
2
+ #
3
+ # Header:
4
+ # timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,
5
+ # success,bytes,grpThreads,allThreads,URL,Latency
6
+ #
7
+ # Line example:
8
+ # 1355164382383,97,Tela de Login,200,"Number of samples in transaction : 1,
9
+ # number of failing samples : 0",Thread Group 1-1,,true,5168,1,1,null,0
10
+ #
11
+
12
+ require 'csv'
13
+
14
+ module JmeterReports
15
+ class SummaryLine
16
+ attr_accessor :timestamp, :elapsed, :label, :error, :latency
17
+
18
+ def self.parse(line)
19
+ t,e,l,rc,rm,_,_,s,_,_,_,_,lt = CSV.parse_line(line)
20
+ res = JmeterReports::SummaryLine.new
21
+ res.timestamp = t.to_i
22
+ res.elapsed = e.to_i
23
+ res.label = l
24
+ res.error = (s == "false" ? true : false)
25
+ res.latency = lt.to_i
26
+ return res
27
+ end
28
+
29
+ def error?
30
+ self.error
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,45 @@
1
+ module JmeterReports
2
+ module Views
3
+ class AsciiSummary
4
+ HEADERS = [:label,:reqs,:errors,:err_pct,:min,:avg,:max,:sd,:avg_thrput,:pct_90,:pct_95]
5
+
6
+ def initialize(report)
7
+ @report = report
8
+ end
9
+
10
+ def report_data(color = true)
11
+ data = []
12
+ @report.items.each do |i|
13
+ data << {
14
+ :label => (color ? "[green]#{i.label}[/]" : i.label),
15
+ :reqs => i.size,
16
+ :errors => (i.errors > 0 && color ? "[red]#{i.errors}[/]" : i.errors),
17
+ :err_pct => (i.error_rate * 100).round(1),
18
+ :avg_thrput => "[yellow]#{i.avg_throughput.round(3)}[/]",
19
+ :min => i.min,
20
+ :avg => "[yellow]#{i.avg}[/]",
21
+ :max => i.max,
22
+ :sd => color ? "[yellow]#{i.sd}[/]" : i.sd,
23
+ :pct_90 => i.percentil(90),
24
+ :pct_95 => i.percentil(95)
25
+ }
26
+ end
27
+ return data
28
+ end
29
+
30
+ def render
31
+ puts ""
32
+ puts " Start: #{@report.start_date}"
33
+ puts " End: #{@report.end_date}"
34
+ puts " Duration: #{@report.elapsed} secs"
35
+ puts " Total requests: #{@report.total_requests}"
36
+ puts "Overall throughput: #{@report.avg_throughput} RPS"
37
+ puts ""
38
+ Formatador.display_compact_table(report_data, HEADERS)
39
+ puts ""
40
+ puts " Time values in milliseconds and throughput in Requests Per Second."
41
+ puts ""
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,30 @@
1
+ module JmeterReports
2
+ module Views
3
+ class AsciiSummaryList
4
+ HEADERS = [:filename,:start,:end,:samples,:avg_thrput]
5
+
6
+ def initialize(files)
7
+ @files = files
8
+ end
9
+
10
+ def report_data(color = true)
11
+ data = []
12
+ @files.each do |filename|
13
+ r = JmeterReports::Summary.create(filename)
14
+ data << {
15
+ :filename => (color ? "[yellow]#{File.basename(filename)}[/]" : File.basename(filename)),
16
+ :start => r.start_date,
17
+ :end => r.end_date,
18
+ :samples => (color ? "[blue]#{r.total_requests}[/]" : r.total_requests),
19
+ :avg_thrput => "#{r.avg_throughput} RPS"
20
+ }
21
+ end
22
+ return data
23
+ end
24
+
25
+ def render
26
+ Formatador.display_compact_table(report_data, HEADERS)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,success,bytes,grpThreads,allThreads,URL,Latency
2
+ 1355230052183,75,GET retrieve_gui,200,OK,Thread Group 1-1,text,true,5168,1,1,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery2820887356_2820887356&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=3887356&provedores=facebook%2Ctwitter%2Cgoogle,74
3
+ 1355230052256,72,GET retrieve_gui,200,OK,Thread Group 1-3,text,true,5168,3,3,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery2464809911_2464809911&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=8771784&provedores=facebook%2Ctwitter%2Cgoogle,70
4
+ 1355230052460,65,GET retrieve_gui,200,OK,Thread Group 1-5,text,true,5168,5,5,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery2880723472_2880723472&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=9723472&provedores=facebook%2Ctwitter%2Cgoogle,64
5
+ 1355230052560,65,GET retrieve_gui,200,OK,Thread Group 1-5,text,true,5168,5,5,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery2880723472_2880723472&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=9723472&provedores=facebook%2Ctwitter%2Cgoogle,64
6
+ 1355230053060,71,GET retrieve_gui,200,OK,Thread Group 1-6,text,true,5168,6,6,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery2808390679_2808390679&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=9390679&provedores=facebook%2Ctwitter%2Cgoogle,69
7
+ 1355230053262,66,GET retrieve_gui,200,OK,Thread Group 1-7,text,true,5168,7,7,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery2692773635_2692773635&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=1773635&provedores=facebook%2Ctwitter%2Cgoogle,65
8
+ 1355230053660,73,GET retrieve_gui,200,OK,Thread Group 1-8,text,true,5168,8,8,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery2625634952_2625634952&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=6634952&provedores=facebook%2Ctwitter%2Cgoogle,71
9
+ 1355230053760,73,GET retrieve_gui,200,OK,Thread Group 1-8,text,true,5168,8,8,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery2625634952_2625634952&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=6634952&provedores=facebook%2Ctwitter%2Cgoogle,71
10
+ 1355230054465,68,GET retrieve_gui,200,OK,Thread Group 1-9,text,true,5168,9,9,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery1205134350_1205134350&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=8134350&provedores=facebook%2Ctwitter%2Cgoogle,67
11
+ 1355230054867,434,POST execute,200,OK,Thread Group 1-5,text,true,1468,10,10,http://stage.id.abril.com.br/widgets/login/execute,434
12
+ 1355230054967,434,POST execute,200,OK,Thread Group 1-5,text,true,1468,10,10,http://stage.id.abril.com.br/widgets/login/execute,434
13
+ 1355230054987,434,POST execute,200,OK,Thread Group 1-5,text,true,1468,10,10,http://stage.id.abril.com.br/widgets/login/execute,434
14
+ 1355230055102,22,GET retrieve_success_gui,200,OK,Thread Group 1-5,text,true,2084,10,10,http://stage.id.abril.com.br/widgets/login/retrieve_success_gui?callback=AbrilIdJQuery2880723472_2880723472&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=9723472,27
15
+ 1355230055465,85,GET retrieve_gui,200,OK,Thread Group 1-9,text,true,5168,9,9,http://stage.id.abril.com.br/widgets/login/retrieve_gui?callback=AbrilIdJQuery1205134350_1205134350&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=8134350&provedores=facebook%2Ctwitter%2Cgoogle,67
16
+ 1355230055867,628,POST execute,200,OK,Thread Group 1-5,text,true,1468,10,10,http://stage.id.abril.com.br/widgets/login/execute,434
17
+ 1355230055902,98,GET retrieve_success_gui,200,OK,Thread Group 1-5,text,true,2084,10,10,http://stage.id.abril.com.br/widgets/login/retrieve_success_gui?callback=AbrilIdJQuery2880723472_2880723472&application_login=PLAYBOY&current_instance_id=aiwwidgets&current_box_id=abril-id-load_test-login&confirmation_url=http://example.com/&_=9723472,27
@@ -1,4 +1,10 @@
1
1
  require 'minitest/autorun'
2
2
  require 'minitest/colorize'
3
3
 
4
- Bundler.require(:default, :development, :test)
4
+ begin
5
+ require 'bundler/setup'
6
+ Bundler.require(:default, :development, :test)
7
+ rescue LoadError
8
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
9
+ end
10
+
@@ -0,0 +1,16 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+ require 'jmeter/reports/views/ascii_summary'
3
+
4
+ module JmeterReports
5
+ module Views
6
+ class TestAsciiSummary < MiniTest::Unit::TestCase
7
+ def setup
8
+ @report = ::JmeterReports::Summary.create(File.expand_path('fixtures/summary_report1.csv', File.dirname(__FILE__)))
9
+ end
10
+
11
+ def test_render
12
+ AsciiSummary.new(@report).render
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+ require 'jmeter/reports/views/ascii_summary_list'
3
+
4
+ module JmeterReports
5
+ module Views
6
+ class TestAsciiSummaryList < MiniTest::Unit::TestCase
7
+ def setup
8
+ @files = Dir.glob(File.expand_path('fixtures/*', File.dirname(__FILE__)))
9
+ end
10
+
11
+ def test_render
12
+ AsciiSummaryList.new(@files).render
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,12 +1,10 @@
1
1
  require File.expand_path('helper', File.dirname(__FILE__))
2
- require 'jmeter/reports/version'
2
+ require 'jmeter/reports'
3
3
 
4
- module Jmeter
5
- module Reports
6
- class TestVersion < MiniTest::Unit::TestCase
7
- def test_version
8
- assert Jmeter::Reports::VERSION != nil
9
- end
4
+ module JmeterReports
5
+ class TestVersion < MiniTest::Unit::TestCase
6
+ def test_version
7
+ assert JmeterReports::VERSION != nil
10
8
  end
11
9
  end
12
10
  end
@@ -0,0 +1,34 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+ require 'jmeter/reports'
3
+
4
+ module JmeterReports
5
+ class TestSummary < MiniTest::Unit::TestCase
6
+ def setup
7
+ @report = Summary.create(File.expand_path('fixtures/summary_report1.csv', File.dirname(__FILE__)))
8
+ end
9
+
10
+ def test_report_items
11
+ assert_equal 3, @report.items.size
12
+ end
13
+
14
+ def test_avg_throughput
15
+ assert_equal 3, @report.avg_throughput
16
+ end
17
+
18
+ def test_elapsed_in_ms
19
+ assert_equal 2719, @report.elapsed_in_ms
20
+ end
21
+
22
+ def test_elapsed
23
+ assert_equal 3, @report.elapsed
24
+ end
25
+
26
+ def test_start_date
27
+ assert_equal Time.new(2012,12,11,12,47,32,"+00:00").to_i, @report.start_date.utc.to_i, 'invalid start date'
28
+ end
29
+
30
+ def test_end_date
31
+ assert_equal Time.new(2012,12,11,12,47,34,"+00:00").to_i, @report.end_date.utc.to_i, 'invalid end date'
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path('helper', File.dirname(__FILE__))
2
+ require 'jmeter/reports/summary_line'
3
+
4
+ module JmeterReports
5
+ class TestSummaryLine < MiniTest::Unit::TestCase
6
+ def test_parse_simple_error_line
7
+ assert SummaryLine.parse('1355332336591,4850,POST execute,500,Internal Server Error,Thread Group 1-70,text,false,15535,75,75,http://stage.id.abril.com.br/widgets/login/execute,4847').error?
8
+ end
9
+
10
+ def test_parse_transaction_error_line
11
+ assert SummaryLine.parse('1355163053904,5933,Login,,"Number of samples in transaction : 2, number of failing samples : 1",Thread Group 1-15,,false,2836,20,20,null,0').error?
12
+ end
13
+ end
14
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jmeter-reports
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,10 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-14 00:00:00.000000000 Z
12
+ date: 2012-12-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: bundler
15
+ name: descriptive_statistics
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
@@ -28,7 +28,7 @@ dependencies:
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
30
  - !ruby/object:Gem::Dependency
31
- name: descriptive_statistics
31
+ name: formatador
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
@@ -44,14 +44,14 @@ dependencies:
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
46
  - !ruby/object:Gem::Dependency
47
- name: formatador
47
+ name: bundler
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
51
  - - ! '>='
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
- type: :runtime
54
+ type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
@@ -136,20 +136,24 @@ files:
136
136
  - Gemfile
137
137
  - Gemfile.lock
138
138
  - LICENSE
139
- - README.rdoc
139
+ - README.md
140
140
  - Rakefile
141
141
  - bin/jmeter-reports
142
142
  - jmeter-reports.gemspec
143
143
  - lib/jmeter/reports.rb
144
- - lib/jmeter/reports/version.rb
145
- - lib/jmeter/summary_report/report.rb
146
- - lib/jmeter/summary_report/report_item.rb
147
- - lib/jmeter/summary_report/result_line.rb
148
- - test/fixtures/summary_report.csv
144
+ - lib/jmeter/reports/summary.rb
145
+ - lib/jmeter/reports/summary_item.rb
146
+ - lib/jmeter/reports/summary_line.rb
147
+ - lib/jmeter/reports/views/ascii_summary.rb
148
+ - lib/jmeter/reports/views/ascii_summary_list.rb
149
+ - test/fixtures/summary_report1.csv
150
+ - test/fixtures/summary_report2.csv
149
151
  - test/helper.rb
152
+ - test/test_ascii_summary.rb
153
+ - test/test_ascii_summary_list.rb
150
154
  - test/test_jmeter_reports_version.rb
151
- - test/test_report.rb
152
- - test/test_result_line.rb
155
+ - test/test_summary.rb
156
+ - test/test_summary_line.rb
153
157
  homepage: https://github.com/marcoshack/jmeter-reports
154
158
  licenses: []
155
159
  post_install_message:
@@ -175,9 +179,12 @@ signing_key:
175
179
  specification_version: 3
176
180
  summary: Basic tools for JMeter reports processing.
177
181
  test_files:
178
- - test/fixtures/summary_report.csv
182
+ - test/fixtures/summary_report1.csv
183
+ - test/fixtures/summary_report2.csv
179
184
  - test/helper.rb
185
+ - test/test_ascii_summary.rb
186
+ - test/test_ascii_summary_list.rb
180
187
  - test/test_jmeter_reports_version.rb
181
- - test/test_report.rb
182
- - test/test_result_line.rb
188
+ - test/test_summary.rb
189
+ - test/test_summary_line.rb
183
190
  has_rdoc:
@@ -1,10 +0,0 @@
1
- == JMeter Reports {<img src="https://travis-ci.org/marcoshack/jmeter-reports.png?branch=master" alt="Build Status" />}[https://travis-ci.org/marcoshack/jmeter-reports]
2
-
3
- Basic tools for JMeter reports processing.
4
-
5
- Right now it supports only CSV summary reports processing to show:
6
-
7
- * Test execution time
8
- * Average request throughput
9
- * Number of requests/errors for each request and/or transaction
10
- * 90 and 95 response time percentiles
@@ -1,5 +0,0 @@
1
- module Jmeter
2
- module Reports
3
- VERSION = "0.0.5"
4
- end
5
- end
@@ -1,68 +0,0 @@
1
- module Jmeter
2
- module SummaryReport
3
- class Report
4
- CSV_HEADER = "timeStamp,elapsed,label,responseCode,responseMessage,threadName,"+
5
- "dataType,success,bytes,grpThreads,allThreads,URL,Latency\n"
6
-
7
- def initialize
8
- @items = {}
9
- @req_count = 0
10
- end
11
-
12
- def self.create(summary_report_file_path)
13
- report = Report.new
14
- csv_report = File.open(summary_report_file_path,'r')
15
-
16
- unless csv_report.readline == CSV_HEADER
17
- raise Exception.new("Invalid CSV report: #{summary_report_file_path}")
18
- end
19
-
20
- csv_report.each_line do |line|
21
- next if line.start_with?("timeStamp,") # ignore header
22
- report.add(ResultLine.parse(line))
23
- end
24
- return report
25
- end
26
-
27
- def add(line)
28
- @items[line.label] = ReportItem.new(line.label) if @items[line.label].nil?
29
- @items[line.label].add(line)
30
- @req_count += 1
31
- @start_ms = line.timestamp if @start_ms.nil? || line.timestamp < @start_ms
32
- @end_ms = line.timestamp if @end_ms.nil? || line.timestamp > @end_ms
33
- end
34
-
35
- def elapsed_in_ms
36
- @end_ms - @start_ms
37
- end
38
-
39
- def elapsed
40
- (self.elapsed_in_ms / 1000.0).ceil
41
- end
42
-
43
- def avg_throughput
44
- @req_count / self.elapsed
45
- end
46
-
47
- def items
48
- @items.values
49
- end
50
-
51
- def total_requests
52
- @req_count
53
- end
54
-
55
- def start_date
56
- Time.at(@start_ms / 1000.0)
57
- end
58
-
59
- def end_date
60
- Time.at(@end_ms / 1000.0)
61
- end
62
-
63
- def table_data
64
- @items.values.collect { |i| i.table_data }
65
- end
66
- end
67
- end
68
- end
@@ -1,68 +0,0 @@
1
- require 'descriptive_statistics'
2
-
3
- module Jmeter
4
- module SummaryReport
5
- class ReportItem
6
- def initialize(label)
7
- @label = label
8
- @items = []
9
- @error_count = 0
10
- @req_count = 0
11
- end
12
-
13
- def add(line)
14
- @error_count += 1 if line.error?
15
- @items << line.elapsed
16
- @req_count += 1
17
- @start_ms = line.timestamp if @start_ms.nil? || line.timestamp < @start_ms
18
- @end_ms = line.timestamp if @end_ms.nil? || line.timestamp > @end_ms
19
- end
20
-
21
- def elapsed_in_ms
22
- @end_ms - @start_ms
23
- end
24
-
25
- def elapsed
26
- (self.elapsed_in_ms / 1000.0).ceil
27
- end
28
-
29
- def avg_throughput
30
- @req_count / self.elapsed.to_f
31
- end
32
-
33
- def size
34
- @items.size
35
- end
36
-
37
- def errors
38
- @error_count
39
- end
40
-
41
- def error_rate
42
- @error_count / self.size.to_f
43
- end
44
-
45
- def table_data
46
- sorted_items = @items.sort
47
- {
48
- :label => @label,
49
- :reqs => self.size,
50
- :errors => self.errors,
51
- :err_pct => round(self.error_rate * 100, 1),
52
- :avg_thrput => "#{round(self.avg_throughput, 3)} RPS",
53
- :min => @items.min,
54
- :avg => @items.reduce { |n,s| s += n } / @items.size,
55
- :max => @items.max,
56
- :sd => "#{@items.standard_deviation.to_i}ms",
57
- :pct_90 => "#{sorted_items[(self.size * 0.90).round]}ms",
58
- :pct_95 => "#{sorted_items[(self.size * 0.95).round]}ms"
59
- }
60
- end
61
-
62
- private
63
- def round(float_number, dec)
64
- (float_number * 10**dec).to_i / (10**dec).to_f
65
- end
66
- end
67
- end
68
- end
@@ -1,35 +0,0 @@
1
- # Representation of a summary report result line.
2
- #
3
- # Header:
4
- # timeStamp,elapsed,label,responseCode,responseMessage,threadName,dataType,
5
- # success,bytes,grpThreads,allThreads,URL,Latency
6
- #
7
- # Line example:
8
- # 1355164382383,97,Tela de Login,200,"Number of samples in transaction : 1,
9
- # number of failing samples : 0",Thread Group 1-1,,true,5168,1,1,null,0
10
- #
11
-
12
- require 'csv'
13
-
14
- module Jmeter
15
- module SummaryReport
16
- class ResultLine
17
- attr_accessor :timestamp, :elapsed, :label, :error, :latency
18
-
19
- def self.parse(line)
20
- t,e,l,rc,rm,_,_,s,_,_,_,_,lt = CSV.parse_line(line)
21
- res = Jmeter::SummaryReport::ResultLine.new
22
- res.timestamp = t.to_i
23
- res.elapsed = e.to_i
24
- res.label = l
25
- res.error = (s == "false" ? true : false)
26
- res.latency = lt.to_i
27
- return res
28
- end
29
-
30
- def error?
31
- self.error
32
- end
33
- end
34
- end
35
- end
@@ -1,37 +0,0 @@
1
- require File.expand_path('helper', File.dirname(__FILE__))
2
- require 'jmeter/reports'
3
-
4
- module Jmeter
5
- module SummaryReport
6
- class TestReport < MiniTest::Unit::TestCase
7
- def setup
8
- fixture = File.expand_path('fixtures/summary_report.csv', File.dirname(__FILE__))
9
- @report = Report.create(fixture)
10
- end
11
-
12
- def test_report_items
13
- assert_equal 3, @report.items.size
14
- end
15
-
16
- def test_avg_throughput
17
- assert_equal 3, @report.avg_throughput
18
- end
19
-
20
- def test_elapsed_in_ms
21
- assert_equal 2719, @report.elapsed_in_ms
22
- end
23
-
24
- def test_elapsed
25
- assert_equal 3, @report.elapsed
26
- end
27
-
28
- def test_start_date
29
- assert_equal Time.new(2012,12,11,12,47,32,"+00:00").to_i, @report.start_date.utc.to_i, 'invalid start date'
30
- end
31
-
32
- def test_end_date
33
- assert_equal Time.new(2012,12,11,12,47,34,"+00:00").to_i, @report.end_date.utc.to_i, 'invalid end date'
34
- end
35
- end
36
- end
37
- end
@@ -1,16 +0,0 @@
1
- require File.expand_path('helper', File.dirname(__FILE__))
2
- require 'jmeter/summary_report/result_line'
3
-
4
- module Jmeter
5
- module SummaryReport
6
- class TestResultLine < MiniTest::Unit::TestCase
7
- def test_parse_simple_error_line
8
- assert ResultLine.parse('1355332336591,4850,POST execute,500,Internal Server Error,Thread Group 1-70,text,false,15535,75,75,http://stage.id.abril.com.br/widgets/login/execute,4847').error?
9
- end
10
-
11
- def test_parse_transaction_error_line
12
- assert ResultLine.parse('1355163053904,5933,Login,,"Number of samples in transaction : 2, number of failing samples : 1",Thread Group 1-15,,false,2836,20,20,null,0').error?
13
- end
14
- end
15
- end
16
- end