lopata 0.1.13 → 0.1.17

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