lopata 0.1.13 → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,103 +1,103 @@
1
- module Lopata
2
- module Observers
3
- # @private
4
- # Based on RSpec::Core::BacktraceFormatter
5
- #
6
- # Provides ability to format backtrace and find source code by file and line number.
7
- class BacktraceFormatter
8
- # @private
9
- attr_accessor :exclusion_patterns, :inclusion_patterns
10
-
11
- def initialize
12
- patterns = %w[ /lib\d*/ruby/ bin/ exe/lopata /lib/bundler/ /exe/bundle /\.rvm/ ]
13
- patterns.map! { |s| Regexp.new(s.gsub("/", File::SEPARATOR)) }
14
-
15
- @exclusion_patterns = [Regexp.union(*patterns)]
16
- @inclusion_patterns = []
17
-
18
- inclusion_patterns << Regexp.new(Dir.getwd)
19
- end
20
-
21
- # Filter backtrace.
22
- #
23
- # @param backtrace [Array<String>] exception backtrace
24
- # @return [Array<String>] backtrace lines except ruby libraries, gems and executable files.
25
- def format(backtrace)
26
- return [] unless backtrace
27
- return backtrace if backtrace.empty?
28
-
29
- backtrace.map { |l| backtrace_line(l) }.compact.
30
- tap do |filtered|
31
- if filtered.empty?
32
- filtered.concat backtrace
33
- filtered << ""
34
- filtered << " Showing full backtrace because every line was filtered out."
35
- end
36
- end
37
- end
38
-
39
-
40
- # Extracts error message from excetion
41
- #
42
- # @param exception [Exception]
43
- # @param include_backtrace [Boolean] whether to add formatted backtrace to output
44
- # @return [String] error message from excetion, incuding source code line.
45
- def error_message(exception, include_backtrace: false)
46
- backtrace = format(exception.backtrace)
47
- source_line = extract_source_line(backtrace.first)
48
- msg = ''
49
- msg << "\n#{source_line}\n" if source_line
50
- msg << "#{exception.class.name}: " unless exception.class.name =~ /RSpec/
51
- msg << exception.message if exception.message
52
- msg << "\n#{backtrace.join("\n")}\n" if include_backtrace
53
- msg
54
- end
55
-
56
- def extract_source_line(backtrace_line)
57
- file_and_line_number = backtrace_line.match(/(.+?):(\d+)(|:\d+)/)
58
- return nil unless file_and_line_number
59
- file_path, line_number = file_and_line_number[1..2]
60
- return nil unless File.exist?(file_path)
61
- lines = File.read(file_path).split("\n")
62
- lines[line_number.to_i - 1]
63
- end
64
-
65
- def backtrace_line(line)
66
- relative_path(line) unless exclude?(line)
67
- end
68
-
69
- def exclude?(line)
70
- matches?(exclusion_patterns, line) && !matches?(inclusion_patterns, line)
71
- end
72
-
73
- private
74
-
75
- def matches?(patterns, line)
76
- patterns.any? { |p| line =~ p }
77
- end
78
-
79
- # Matches strings either at the beginning of the input or prefixed with a
80
- # whitespace, containing the current path, either postfixed with the
81
- # separator, or at the end of the string. Match groups are the character
82
- # before and the character after the string if any.
83
- #
84
- # http://rubular.com/r/fT0gmX6VJX
85
- # http://rubular.com/r/duOrD4i3wb
86
- # http://rubular.com/r/sbAMHFrOx1
87
- def relative_path_regex
88
- @relative_path_regex ||= /(\A|\s)#{File.expand_path('.')}(#{File::SEPARATOR}|\s|\Z)/
89
- end
90
-
91
- # @param line [String] current code line
92
- # @return [String] relative path to line
93
- def relative_path(line)
94
- line = line.sub(relative_path_regex, "\\1.\\2".freeze)
95
- line = line.sub(/\A([^:]+:\d+)$/, '\\1'.freeze)
96
- return nil if line == '-e:1'.freeze
97
- line
98
- rescue SecurityError
99
- nil
100
- end
101
- end
102
- end
103
- end
1
+ module Lopata
2
+ module Observers
3
+ # @private
4
+ # Based on RSpec::Core::BacktraceFormatter
5
+ #
6
+ # Provides ability to format backtrace and find source code by file and line number.
7
+ class BacktraceFormatter
8
+ # @private
9
+ attr_accessor :exclusion_patterns, :inclusion_patterns
10
+
11
+ def initialize
12
+ patterns = %w[ /lib\d*/ruby/ bin/ exe/lopata /lib/bundler/ /exe/bundle /\.rvm/ /rvm/ ]
13
+ patterns.map! { |s| Regexp.new(s.gsub("/", File::SEPARATOR)) }
14
+
15
+ @exclusion_patterns = [Regexp.union(*patterns)]
16
+ @inclusion_patterns = []
17
+
18
+ inclusion_patterns << Regexp.new(Dir.getwd)
19
+ end
20
+
21
+ # Filter backtrace.
22
+ #
23
+ # @param backtrace [Array<String>] exception backtrace
24
+ # @return [Array<String>] backtrace lines except ruby libraries, gems and executable files.
25
+ def format(backtrace)
26
+ return [] unless backtrace
27
+ return backtrace if backtrace.empty?
28
+
29
+ backtrace.map { |l| backtrace_line(l) }.compact.
30
+ tap do |filtered|
31
+ if filtered.empty?
32
+ filtered.concat backtrace
33
+ filtered << ""
34
+ filtered << " Showing full backtrace because every line was filtered out."
35
+ end
36
+ end
37
+ end
38
+
39
+
40
+ # Extracts error message from excetion
41
+ #
42
+ # @param exception [Exception]
43
+ # @param include_backtrace [Boolean] whether to add formatted backtrace to output
44
+ # @return [String] error message from excetion, incuding source code line.
45
+ def error_message(exception, include_backtrace: false)
46
+ backtrace = format(exception.backtrace)
47
+ source_line = extract_source_line(backtrace.first)
48
+ msg = ''
49
+ msg << "\n#{source_line}\n" if source_line
50
+ msg << "#{exception.class.name}: " unless exception.class.name =~ /RSpec/
51
+ msg << exception.message if exception.message
52
+ msg << "\n#{backtrace.join("\n")}\n" if include_backtrace
53
+ msg
54
+ end
55
+
56
+ def extract_source_line(backtrace_line)
57
+ file_and_line_number = backtrace_line.match(/(.+?):(\d+)(|:\d+)/)
58
+ return nil unless file_and_line_number
59
+ file_path, line_number = file_and_line_number[1..2]
60
+ return nil unless File.exist?(file_path)
61
+ lines = File.read(file_path).split("\n")
62
+ lines[line_number.to_i - 1]
63
+ end
64
+
65
+ def backtrace_line(line)
66
+ relative_path(line) unless exclude?(line)
67
+ end
68
+
69
+ def exclude?(line)
70
+ matches?(exclusion_patterns, line) && !matches?(inclusion_patterns, line)
71
+ end
72
+
73
+ private
74
+
75
+ def matches?(patterns, line)
76
+ patterns.any? { |p| line =~ p }
77
+ end
78
+
79
+ # Matches strings either at the beginning of the input or prefixed with a
80
+ # whitespace, containing the current path, either postfixed with the
81
+ # separator, or at the end of the string. Match groups are the character
82
+ # before and the character after the string if any.
83
+ #
84
+ # http://rubular.com/r/fT0gmX6VJX
85
+ # http://rubular.com/r/duOrD4i3wb
86
+ # http://rubular.com/r/sbAMHFrOx1
87
+ def relative_path_regex
88
+ @relative_path_regex ||= /(\A|\s)#{File.expand_path('.')}(#{File::SEPARATOR}|\s|\Z)/
89
+ end
90
+
91
+ # @param line [String] current code line
92
+ # @return [String] relative path to line
93
+ def relative_path(line)
94
+ line = line.sub(relative_path_regex, "\\1.\\2".freeze)
95
+ line = line.sub(/\A([^:]+:\d+)$/, '\\1'.freeze)
96
+ return nil if line == '-e:1'.freeze
97
+ line
98
+ rescue SecurityError
99
+ nil
100
+ end
101
+ end
102
+ end
103
+ end
@@ -1,34 +1,34 @@
1
- module Lopata
2
- module Observers
3
- # Lopata allows observe scenarios execution.
4
- # All the observers are subclasses of Lopata::Observers::BaseObserver.
5
- #
6
- # @see Lopata::Observers::ConsoleOutputObserver for implementation example
7
- class BaseObserver
8
- # Called before scenarios execution.
9
- # All the scenarios are prepared at the moment, so it may be used to get number of scenarios
10
- # via world.scenarios.count
11
- #
12
- # @param world [Lopata::World]
13
- def started(world)
14
- end
15
-
16
- # Called after all scenarios execution.
17
- # All the scenarios are finished at the moment, so it may be used for output statistics.
18
- #
19
- # @param world [Lopata::World]
20
- def finished(world)
21
- end
22
-
23
- # Called before single scenario execution.
24
- # @param scenario [Lopata::Scenario::Execution]
25
- def scenario_started(scenario)
26
- end
27
-
28
- # Called after single scenario execution.
29
- # @param scenario [Lopata::Scenario::Execution]
30
- def scenario_finished(scenario)
31
- end
32
- end
33
- end
1
+ module Lopata
2
+ module Observers
3
+ # Lopata allows observe scenarios execution.
4
+ # All the observers are subclasses of Lopata::Observers::BaseObserver.
5
+ #
6
+ # @see Lopata::Observers::ConsoleOutputObserver for implementation example
7
+ class BaseObserver
8
+ # Called before scenarios execution.
9
+ # All the scenarios are prepared at the moment, so it may be used to get number of scenarios
10
+ # via world.scenarios.count
11
+ #
12
+ # @param world [Lopata::World]
13
+ def started(world)
14
+ end
15
+
16
+ # Called after all scenarios execution.
17
+ # All the scenarios are finished at the moment, so it may be used for output statistics.
18
+ #
19
+ # @param world [Lopata::World]
20
+ def finished(world)
21
+ end
22
+
23
+ # Called before single scenario execution.
24
+ # @param scenario [Lopata::Scenario::Execution]
25
+ def scenario_started(scenario)
26
+ end
27
+
28
+ # Called after single scenario execution.
29
+ # @param scenario [Lopata::Scenario::Execution]
30
+ def scenario_finished(scenario)
31
+ end
32
+ end
33
+ end
34
34
  end
@@ -1,100 +1,100 @@
1
- require_relative 'backtrace_formatter'
2
- require 'forwardable'
3
-
4
- module Lopata
5
- module Observers
6
- # @private
7
- class ConsoleOutputObserver < BaseObserver
8
- extend Forwardable
9
- # @private
10
- attr_reader :output
11
- # @private
12
- def_delegators :output, :puts, :flush
13
-
14
- def initialize
15
- @output = $stdout
16
- end
17
-
18
- # @see Lopata::Observers::BaseObserver#finished
19
- def finished(world)
20
- total = statuses.values.inject(0, &:+)
21
- counts = statuses.map do |status, count|
22
- colored("%d %s", status) % [count, status]
23
- end
24
- details = counts.empty? ? "" : "(%s)" % counts.join(', ')
25
- puts "#{total} scenario%s %s" % [total == 1 ? '' : 's', details]
26
- end
27
-
28
- # @see Lopata::Observers::BaseObserver#scenario_finished
29
- def scenario_finished(scenario)
30
- message = "#{scenario.title} #{bold(scenario.status.to_s.upcase)}"
31
- puts colored(message, scenario.status)
32
-
33
- statuses[scenario.status] ||= 0
34
- statuses[scenario.status] += 1
35
-
36
- if scenario.failed?
37
- scenario.steps.each do |step|
38
- puts colored(" #{status_marker(step.status)} #{step.title}", step.status)
39
- puts indent(4, backtrace_formatter.error_message(step.exception, include_backtrace: true)) if step.failed?
40
- end
41
- end
42
-
43
- flush
44
- end
45
-
46
- private
47
-
48
- def colored(text, status)
49
- case status
50
- when :failed then red(text)
51
- when :passed then green(text)
52
- when :skipped then cyan(text)
53
- when :pending then yellow(text)
54
- else text
55
- end
56
- end
57
-
58
- {
59
- red: 31,
60
- green: 32,
61
- cyan: 36,
62
- yellow: 33,
63
- bold: 1,
64
- }.each do |color, code|
65
- define_method(color) do |text|
66
- wrap(text, code)
67
- end
68
- end
69
-
70
- def wrap(text, code)
71
- "\e[#{code}m#{text}\e[0m"
72
- end
73
-
74
- def backtrace_formatter
75
- @backtrace_formatter ||= Lopata::Observers::BacktraceFormatter.new
76
- end
77
-
78
- def status_marker(status)
79
- case status
80
- when :failed then "[!]"
81
- when :skipped then "[-]"
82
- when :pending then "[?]"
83
- else "[+]"
84
- end
85
- end
86
-
87
- # Adds indent to text
88
- # @param cols [Number] number of spaces to be added
89
- # @param text [String] text to add indent
90
- # @return [String] text with indent
91
- def indent(cols, text)
92
- text.split("\n").map { |line| " " * cols + line }.join("\n")
93
- end
94
-
95
- def statuses
96
- @statuses ||= {}
97
- end
98
- end
99
- end
100
- end
1
+ require_relative 'backtrace_formatter'
2
+ require 'forwardable'
3
+
4
+ module Lopata
5
+ module Observers
6
+ # @private
7
+ class ConsoleOutputObserver < BaseObserver
8
+ extend Forwardable
9
+ # @private
10
+ attr_reader :output
11
+ # @private
12
+ def_delegators :output, :puts, :flush
13
+
14
+ def initialize
15
+ @output = $stdout
16
+ end
17
+
18
+ # @see Lopata::Observers::BaseObserver#finished
19
+ def finished(world)
20
+ total = statuses.values.inject(0, &:+)
21
+ counts = statuses.map do |status, count|
22
+ colored("%d %s", status) % [count, status]
23
+ end
24
+ details = counts.empty? ? "" : "(%s)" % counts.join(', ')
25
+ puts "#{total} scenario%s %s" % [total == 1 ? '' : 's', details]
26
+ end
27
+
28
+ # @see Lopata::Observers::BaseObserver#scenario_finished
29
+ def scenario_finished(scenario)
30
+ message = "#{scenario.title} #{bold(scenario.status.to_s.upcase)}"
31
+ puts colored(message, scenario.status)
32
+
33
+ statuses[scenario.status] ||= 0
34
+ statuses[scenario.status] += 1
35
+
36
+ if scenario.failed?
37
+ scenario.steps.each do |step|
38
+ puts colored(" #{status_marker(step.status)} #{step.title}", step.status)
39
+ puts indent(4, backtrace_formatter.error_message(step.exception, include_backtrace: true)) if step.failed?
40
+ end
41
+ end
42
+
43
+ flush
44
+ end
45
+
46
+ private
47
+
48
+ def colored(text, status)
49
+ case status
50
+ when :failed then red(text)
51
+ when :passed then green(text)
52
+ when :skipped then cyan(text)
53
+ when :pending then yellow(text)
54
+ else text
55
+ end
56
+ end
57
+
58
+ {
59
+ red: 31,
60
+ green: 32,
61
+ cyan: 36,
62
+ yellow: 33,
63
+ bold: 1,
64
+ }.each do |color, code|
65
+ define_method(color) do |text|
66
+ wrap(text, code)
67
+ end
68
+ end
69
+
70
+ def wrap(text, code)
71
+ "\e[#{code}m#{text}\e[0m"
72
+ end
73
+
74
+ def backtrace_formatter
75
+ @backtrace_formatter ||= Lopata::Observers::BacktraceFormatter.new
76
+ end
77
+
78
+ def status_marker(status)
79
+ case status
80
+ when :failed then "[!]"
81
+ when :skipped then "[-]"
82
+ when :pending then "[?]"
83
+ else "[+]"
84
+ end
85
+ end
86
+
87
+ # Adds indent to text
88
+ # @param cols [Number] number of spaces to be added
89
+ # @param text [String] text to add indent
90
+ # @return [String] text with indent
91
+ def indent(cols, text)
92
+ text.split("\n").map { |line| " " * cols + line }.join("\n")
93
+ end
94
+
95
+ def statuses
96
+ @statuses ||= {}
97
+ end
98
+ end
99
+ end
100
+ end