rspec_log_formatter 0.0.1 → 0.1.0

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.
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