jmeter-reports 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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