rspec_log_formatter 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MGJmODJlZTJkMzNjOGY5OWRjNDRjNmIxYzUyMTM0ZWEyY2MxN2U0Ng==
4
+ NDA1NzQxMjZmZjU0ZWU3ZjkzZTRmMzIzNTYzM2Q1NTRiZTJiYTVkOA==
5
5
  data.tar.gz: !binary |-
6
- YzQ3MDllYzM1MmQ5NmJjNzJkYmVlMjE0ZjkxY2U1ZmFiZjg1ZDYxMw==
6
+ NjhiY2JiNzgyMGEyZGFlOTIyZjk4NTZjZmU5NzFkODA3NjBlNGIwOQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MzBjMWQ3NGZjMzZmODM1M2VhY2ZmYjA3MGE0NjQzYTg5Zjg1YjEwNTA3YjIy
10
- ZDhmMDZlNDBmYTc5Y2ZjZjc1Njg3MjMwYzQ1ZjRlNmJhOTFmZTI5NzQwZDlj
11
- MDA0OGQ5ODJjNmQxZWU1NDZlOTJkM2Q4NTU2YzFlNGJiMmQ0ZGQ=
9
+ NDE3M2RlZGExODYyNjc2ZGZmOGE4YjgxYzMxZDYzYTRlZWQwMGNjOGNiZGY5
10
+ MTlmOGIzYjE5ZDUyMWU0MjFjMjBhNjlkZjc0M2IzNzk3MWQ1MWVlYWQ0NTM0
11
+ ZmI3YzRlNjlhODcwZmZjYTQ2NGQxODU5ZTZhOWY2YWNiNjIwYjU=
12
12
  data.tar.gz: !binary |-
13
- Mzc5NWQ5MzEyZmFiMDE0ODZjODEyZTkxYWQ4MWQ3ZDRjYmUzNDI5ODY3YjVm
14
- NTY2ZTg1ZjJkZWY1YjczMGQyMWE3OTE4M2Q4YjJjMDA4YTdjNTM0Nzg3YjRk
15
- MjdhMjgzZjM4Y2JkY2MwNjE2OWFiYzQwNWIwM2M2YzAyNjE4MTQ=
13
+ YTEwMTFlYzFjMTllODQ0NmQxZDU4Mjc1MDI4NzBhOTc2NGU4OWM1NDBhZmNk
14
+ YTNiYmY0MmYzZjdlMjMyYjc5YTgxNGE1YTk0YWZjOThiOTBmZDJlNmRkYjk1
15
+ ZTQ0NDEwNjNiZmU2OGRlZjY4MDNhMGYxMjAxNzU2ZmVhZjliNTY=
@@ -6,14 +6,7 @@ module RspecLogFormatter
6
6
  def analyze(filepath, options = {})
7
7
  window = options[:last_builds]
8
8
 
9
- build_numbers = []
10
- results = File.open(filepath).each_line.map do |line|
11
- result = Result.new(*CSV.parse_line(line, col_sep: "\t").first(7))
12
- build_numbers << result.build_number
13
- result
14
- end
15
- build_numbers.uniq!.sort!
16
-
9
+ build_numbers, results = result_numbers(filepath, options = {})
17
10
 
18
11
  scores = []
19
12
  results.group_by(&:description).each do |description, results|
@@ -33,6 +26,48 @@ module RspecLogFormatter
33
26
 
34
27
  scores.sort.map(&:as_hash)
35
28
  end
29
+
30
+ def truncate(filepath, opts = {})
31
+ builds = opts.fetch(:keep_builds)
32
+ build_numbers, results = result_numbers(filepath, options = {})
33
+ sio = StringIO.new
34
+
35
+ File.open(filepath, 'r').each_line do |line|
36
+ result = parse_line(line)
37
+ next unless build_numbers.last(builds).include? result.build_number
38
+ sio.puts line
39
+ end
40
+
41
+ sio.rewind
42
+ File.open(filepath, 'w') do |f|
43
+ f.write sio.read
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def parse_line(line)
50
+ Result.new(*CSV.parse_line(line, col_sep: "\t").first(7))
51
+ end
52
+
53
+ def each_result(filepath, &block)
54
+ File.open(filepath, 'r').each_line do |line|
55
+ result = parse_line(line)
56
+ block.call(result)
57
+ end
58
+ end
59
+
60
+ def result_numbers(filepath, options = {})
61
+ build_numbers = []
62
+ results = []
63
+ each_result(filepath) do |result|
64
+ build_numbers << result.build_number
65
+ results << result
66
+ end
67
+ [build_numbers.uniq.sort, results]
68
+ end
69
+
36
70
  end
71
+
37
72
  end
38
73
  end
@@ -6,8 +6,15 @@ module RspecLogFormatter
6
6
  end
7
7
 
8
8
  def to_s
9
- results = @results.first(10)
10
- header = "Top #{results.count} flakiest examples\n"
9
+ results = @results.reject do |result|
10
+ result[:percent] == 0.0
11
+ end.first(10)
12
+
13
+ header = if results.empty?
14
+ "None of the specs were flaky"
15
+ else
16
+ "Top #{results.size} flakiest examples\n"
17
+ end
11
18
  header + results.each_with_index.map do |result, i|
12
19
  title = " #{i+1}) #{result[:description]} -- #{result[:percent]}%"
13
20
  failure_messages = result[:failure_messages].map { |fm| " * #{fm}" }.join("\n")
@@ -0,0 +1,20 @@
1
+ require "csv"
2
+ require "rspec/core/formatters/base_formatter"
3
+
4
+ module RspecLogFormatter
5
+ class AnalyzerFormatter < RSpec::Core::Formatters::BaseFormatter
6
+ FILENAME = "rspec.history"
7
+
8
+ def initialize(*args)
9
+ super
10
+ end
11
+
12
+
13
+ def dump_summary(_,_,_,_)
14
+ output.puts RspecLogFormatter::Analysis::PrettyPrinter.new(
15
+ RspecLogFormatter::Analysis::Analyzer.new.analyze(FILENAME)
16
+ )
17
+ end
18
+
19
+ end
20
+ end
@@ -5,23 +5,17 @@ module RspecLogFormatter
5
5
  class Formatter < RSpec::Core::Formatters::BaseFormatter
6
6
  FILENAME = "rspec.history"
7
7
 
8
- class Config
9
- def clock=(clock)
10
- @clock = clock
8
+ class Maker
9
+ def new(_output)
10
+ RspecLogFormatter::Formatter.new(clock, opts)
11
11
  end
12
- def clock
13
- @clock ||= Time
14
- @clock
15
- end
16
- end
17
- CONFIG = Config.new
18
-
19
- def initialize(*args)
20
- super
21
12
  end
13
+ Factory = Maker.new
22
14
 
23
- def self.analyze(filepath)
24
- Analysis::Analyzer.new.analyze(filepath)
15
+ def initialize(clock=nil, opts={})
16
+ @clock = clock || Time
17
+ @build_number = opts[:build_number] || ENV["BUILD_NUMBER"]
18
+ @keep_builds = opts[:keep_builds]
25
19
  end
26
20
 
27
21
  def example_started(example)
@@ -36,11 +30,14 @@ module RspecLogFormatter
36
30
  record("failed", example, clock.now, clock.now - @clock_start, example.exception)
37
31
  end
38
32
 
33
+ def dump_summary(_,_,_,_)
34
+ return unless @keep_builds
35
+ RspecLogFormatter::Analysis::Analyzer.new.truncate(FILENAME, keep_builds: @keep_builds)
36
+ end
37
+
39
38
  private
40
39
 
41
- def clock
42
- CONFIG.clock
43
- end
40
+ attr_reader :clock
44
41
 
45
42
  def record(outcome, example, time, duration, exception=nil)
46
43
  if exception
@@ -53,7 +50,7 @@ module RspecLogFormatter
53
50
  end
54
51
 
55
52
  example_data = [
56
- ENV["BUILD_NUMBER"],
53
+ @build_number,
57
54
  time,
58
55
  outcome,
59
56
  example.full_description.to_s.gsub(/\r|\n|\t/, " "),
@@ -1,3 +1,3 @@
1
1
  module RspecLogFormatter
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require "spec_helper"
2
+ require 'tempfile'
2
3
 
3
4
  describe RspecLogFormatter::Analysis::Analyzer do
4
5
  it "sorts the parsed results by failure percentage" do
@@ -24,6 +25,19 @@ describe RspecLogFormatter::Analysis::Analyzer do
24
25
  }
25
26
  end
26
27
 
28
+
29
+ it "can truncate the log file" do
30
+ filepath = File.expand_path("../../../../fixtures/test_was_flaky_then_fixed.history", __FILE__)
31
+ temp = Tempfile.new('fixture')
32
+ FileUtils.copy(filepath, temp.path)
33
+ described_class.new.truncate(temp.path, keep_builds: 3)
34
+ File.open(temp.path, 'r').read.should == <<HEREDOC
35
+ 5 2014-01-21 16:08:25 -0800 passed desc ./spec/m1k1_spec.rb
36
+ 6 2014-01-21 16:08:25 -0800 passed desc ./spec/m1k1_spec.rb
37
+ 7 2014-01-21 16:08:25 -0800 passed desc ./spec/m1k1_spec.rb
38
+ HEREDOC
39
+ end
40
+
27
41
  it "can analyze only a window of builds" do
28
42
  filepath = File.expand_path("../../../../fixtures/test_was_flaky_then_fixed.history", __FILE__)
29
43
  subject.analyze(filepath, last_builds: 7).first.should == {
@@ -24,7 +24,7 @@ Top 2 flakiest examples
24
24
 
25
25
  context "when there are more than 10 results" do
26
26
  it "only prints the top 10" do
27
- results = (1..20).map do |i|
27
+ results = (1..11).map do |i|
28
28
  {description: "hi#{i}", percent: 1, failure_messages: ["bye#{i}"]}
29
29
  end
30
30
 
@@ -53,4 +53,39 @@ Top 10 flakiest examples
53
53
  TEXT
54
54
  end
55
55
  end
56
+
57
+ it "only prints flaky specs" do
58
+ results = (1..7).map do |i|
59
+ {description: "hi#{i}", percent: 1, failure_messages: ["bye#{i}"]}
60
+ end + (8..10).map do |i|
61
+ {description: "hi#{i}", percent: 0.0, failure_messages: ["bye#{i}"]}
62
+
63
+ end
64
+
65
+ described_class.new(results).to_s.should == <<-TEXT.strip
66
+ Top 7 flakiest examples
67
+ 1) hi1 -- 1%
68
+ * bye1
69
+ 2) hi2 -- 1%
70
+ * bye2
71
+ 3) hi3 -- 1%
72
+ * bye3
73
+ 4) hi4 -- 1%
74
+ * bye4
75
+ 5) hi5 -- 1%
76
+ * bye5
77
+ 6) hi6 -- 1%
78
+ * bye6
79
+ 7) hi7 -- 1%
80
+ * bye7
81
+ TEXT
82
+ end
83
+
84
+ it "only prints flaky specs" do
85
+ results = (1..11).map do |i|
86
+ {description: "hi#{i}", percent: 0, failure_messages: ["bye#{i}"]}
87
+ end
88
+
89
+ described_class.new(results).to_s.should == "None of the specs were flaky"
90
+ end
56
91
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe RspecLogFormatter::Formatter do
4
+
5
+
6
+ it "works" do
7
+ filepath = File.expand_path("../../../fixtures/varying_flakiness.history", __FILE__)
8
+ FileUtils.cp(filepath, 'rspec.history')
9
+ out = StringIO.new
10
+ formatter = RspecLogFormatter::AnalyzerFormatter.new(out)
11
+ formatter.dump_summary(1,2,3,4)
12
+ out.rewind
13
+ out.read.should == <<HEREDOC
14
+ Top 3 flakiest examples
15
+ 1) desc3 -- 75.0%
16
+ * ec10
17
+ msg10
18
+ * ec10
19
+ msg10
20
+ * ec10
21
+ msg10
22
+ 2) desc2 -- 66.66666666666667%
23
+ * ec10
24
+ msg10
25
+ * ec10
26
+ msg10
27
+ 3) desc1 -- 50.0%
28
+ * ec10
29
+ msg10
30
+ HEREDOC
31
+ end
32
+ end
@@ -10,25 +10,65 @@ describe RspecLogFormatter::Formatter do
10
10
  }.merge(opts))
11
11
  end
12
12
 
13
+ def formatter_for_build(build)
14
+ RspecLogFormatter::Formatter.new(double(now: Time.at(0)), keep_builds: 2, build_number: build)
15
+ end
16
+
17
+ it "can truncate the log file" do
18
+ the_example = make_example
19
+ formatter = formatter_for_build(1)
20
+ formatter.example_started(the_example)
21
+ formatter.example_passed(the_example)
22
+ formatter.dump_summary(1,2,3,4)
23
+
24
+ formatter = formatter_for_build(2)
25
+ formatter.example_started(the_example)
26
+ formatter.example_passed(the_example)
27
+ formatter.dump_summary(1,2,3,4)
28
+
29
+ File.open(RspecLogFormatter::Formatter::FILENAME, 'r').read.should == <<HEREDOC
30
+ 1 1969-12-31 16:00:00 -0800 passed description_1 path_1 0.0
31
+ 2 1969-12-31 16:00:00 -0800 passed description_1 path_1 0.0
32
+ HEREDOC
33
+
34
+ formatter = formatter_for_build(3)
35
+ formatter.example_started(the_example)
36
+ formatter.example_passed(the_example)
37
+ formatter.dump_summary(1,2,3,4)
38
+
39
+ formatter = formatter_for_build(4)
40
+ formatter.example_started(the_example)
41
+ formatter.example_passed(the_example)
42
+ formatter.dump_summary(1,2,3,4)
43
+
44
+ File.open(RspecLogFormatter::Formatter::FILENAME, 'r').read.should == <<HEREDOC
45
+ 3 1969-12-31 16:00:00 -0800 passed description_1 path_1 0.0
46
+ 4 1969-12-31 16:00:00 -0800 passed description_1 path_1 0.0
47
+ HEREDOC
48
+ end
49
+
50
+ class FakeClock
51
+ def initialize(now)
52
+ self.now = now
53
+ end
54
+ attr_accessor :now
55
+ end
56
+
13
57
  it "works" do
14
58
  failed_example = make_example(exception: Exception.new("Error"))
15
59
  passed_example = make_example(exception: nil)
16
60
  time = Time.parse("2014-02-06 16:01:10")
17
- clock = double(now: time)
18
- RspecLogFormatter::Formatter::CONFIG.clock = clock
19
-
20
- formatter = RspecLogFormatter::Formatter.new(StringIO.new)
61
+ clock = FakeClock.new(time)
62
+ formatter = RspecLogFormatter::Formatter.new(clock)
21
63
  formatter.example_started(failed_example)
22
- #clock.stub(now: time + 5)
23
- RspecLogFormatter::Formatter::CONFIG.clock = double(now: time + 5)
64
+ clock.now = time + 5
24
65
  formatter.example_failed(failed_example)
25
66
 
26
67
  formatter.example_started(passed_example)
27
- #clock.stub(:now, time + 8)
28
- RspecLogFormatter::Formatter::CONFIG.clock = double(now: time + 8)
68
+ clock.now = time + 8
29
69
  formatter.example_passed(passed_example)
30
70
  formatter.dump_summary(1,2,3,4)
31
- File.open('rspec.history').readlines.should == [
71
+ File.open('rspec.history'). readlines.should == [
32
72
  "\t2014-02-06 16:01:15 -0800\tfailed\tdescription_1\tpath_1\tError\tException\t5.0\n",
33
73
  "\t2014-02-06 16:01:18 -0800\tpassed\tdescription_2\tpath_2\t\t\t3.0\n",
34
74
  ]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec_log_formatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Serguei Filimonov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-07 00:00:00.000000000 Z
11
+ date: 2014-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -85,6 +85,7 @@ files:
85
85
  - lib/rspec_log_formatter/analysis/pretty_printer.rb
86
86
  - lib/rspec_log_formatter/analysis/result.rb
87
87
  - lib/rspec_log_formatter/analysis/score.rb
88
+ - lib/rspec_log_formatter/analyzer_formatter.rb
88
89
  - lib/rspec_log_formatter/formatter.rb
89
90
  - lib/rspec_log_formatter/version.rb
90
91
  - rspec_log_formatter.gemspec
@@ -93,6 +94,7 @@ files:
93
94
  - spec/fixtures/varying_flakiness.history
94
95
  - spec/lib/rspec_log_analyzer/analysis/analyzer_spec.rb
95
96
  - spec/lib/rspec_log_analyzer/analysis/pretty_printer_spec.rb
97
+ - spec/lib/rspec_log_analyzer/analyzer_formatter_spec.rb
96
98
  - spec/lib/rspec_log_analyzer/formatter_spec.rb
97
99
  - spec/spec_helper.rb
98
100
  homepage: ''
@@ -125,5 +127,6 @@ test_files:
125
127
  - spec/fixtures/varying_flakiness.history
126
128
  - spec/lib/rspec_log_analyzer/analysis/analyzer_spec.rb
127
129
  - spec/lib/rspec_log_analyzer/analysis/pretty_printer_spec.rb
130
+ - spec/lib/rspec_log_analyzer/analyzer_formatter_spec.rb
128
131
  - spec/lib/rspec_log_analyzer/formatter_spec.rb
129
132
  - spec/spec_helper.rb