spectre-core 1.8.4 → 1.12.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.
@@ -1,3 +1,4 @@
1
+ require_relative '../spectre'
1
2
  require 'date'
2
3
 
3
4
  module Spectre
@@ -98,6 +99,7 @@ module Spectre
98
99
 
99
100
  def log_debug message
100
101
  return unless @@debug
102
+
101
103
  add_log(message)
102
104
  delegate(:log_debug, message)
103
105
  end
@@ -141,4 +143,4 @@ module Spectre
141
143
 
142
144
  Spectre.delegate :log, :info, :debug, :group, :separate, to: self
143
145
  end
144
- end
146
+ end
data/lib/spectre/mixin.rb CHANGED
@@ -1,41 +1,58 @@
1
- require 'ostruct'
2
-
3
- module Spectre
4
- module Mixin
5
- class << self
6
- @@mixins = {}
7
-
8
- def mixin desc, &block
9
- @@mixins[desc] = block
10
- end
11
-
12
- def run desc, with: []
13
- raise "no mixin with desc '#{desc}' defined" unless @@mixins.key? desc
14
- Logger.log_debug "running mixin '#{desc}'"
15
-
16
- if with.is_a? Array
17
- @@mixins[desc].call *with
18
- else
19
- @@mixins[desc].call with
20
- end
21
- end
22
-
23
- alias_method :also, :run
24
- alias_method :step, :run
25
- end
26
-
27
- Spectre.register do |config|
28
- if not config.key? 'mixin_patterns'
29
- return
30
- end
31
-
32
- config['mixin_patterns'].each do |pattern|
33
- Dir.glob(pattern).each do|f|
34
- require_relative File.join(Dir.pwd, f)
35
- end
36
- end
37
- end
38
-
39
- Spectre.delegate :mixin, :run, :also, :step, to: Mixin
40
- end
41
- end
1
+ require_relative '../spectre'
2
+ require_relative 'logger'
3
+
4
+ require 'ostruct'
5
+
6
+ module Spectre
7
+ module Mixin
8
+ class MixinContext < Spectre::DslClass
9
+ def initialize desc
10
+ @__desc = desc
11
+ end
12
+
13
+ def required params, *keys
14
+ missing_keys = keys.select { |x| !params.to_h.key? x }
15
+ Spectre::Logger.log_debug("required parameters for '#{@__desc}': #{keys.join ', '}")
16
+ raise ArgumentError, "mixin '#{@__desc}' requires #{keys.join ', '}, but only has #{missing_keys.join ', '} given" unless missing_keys.empty?
17
+ end
18
+
19
+ def optional params, *keys
20
+ Spectre::Logger.log_debug("optional parameters for '#{@__desc}': #{keys.join ', '}")
21
+ params
22
+ end
23
+ end
24
+
25
+ class << self
26
+ @@mixins = {}
27
+
28
+ def mixin desc, &block
29
+ @@mixins[desc] = block
30
+ end
31
+
32
+ def run desc, with: []
33
+ raise "no mixin with desc '#{desc}' defined" unless @@mixins.key? desc
34
+
35
+ Spectre::Logger.log_debug "running mixin '#{desc}'"
36
+
37
+ params = with || {}
38
+
39
+ ctx = MixinContext.new(desc)
40
+
41
+ if params.is_a? Array
42
+ return_val = ctx._execute(*params, &@@mixins[desc])
43
+ elsif params.is_a? Hash
44
+ return_val = ctx._execute(OpenStruct.new(params), &@@mixins[desc])
45
+ else
46
+ return_val = ctx._execute(params, &@@mixins[desc])
47
+ end
48
+
49
+ return_val.is_a?(Hash) ? OpenStruct.new(return_val) : return_val
50
+ end
51
+
52
+ alias_method :also, :run
53
+ alias_method :step, :run
54
+ end
55
+
56
+ Spectre.delegate :mixin, :run, :also, :step, to: self
57
+ end
58
+ end
@@ -1,103 +1,102 @@
1
- module Spectre::Reporter
2
- class Console
3
- def initialize config
4
- @config = config
5
- end
6
-
7
- def report run_infos
8
-
9
- report_str = ''
10
-
11
- errors = 0
12
- failures = 0
13
- skipped = run_infos.select { |x| x.skipped? }.count
14
-
15
- run_infos
16
- .select { |x| x.error != nil or x.failure != nil }
17
- .each_with_index do |run_info, index|
18
-
19
- spec = run_info.spec
20
-
21
- report_str += "\n#{index+1}) #{format_title(run_info)}\n"
22
-
23
- if run_info.failure
24
- report_str += " Expected #{run_info.failure.expectation}"
25
- report_str += " with #{run_info.data}" if run_info.data
26
- report_str += " during #{spec.context.__desc}" if spec.context.__desc
27
-
28
- report_str += " but it failed"
29
-
30
- if run_info.failure.cause
31
- report_str += "\n with an unexpected error:\n"
32
- report_str += format_exception(run_info.failure.cause)
33
-
34
- elsif run_info.failure.message and not run_info.failure.message.empty?
35
- report_str += " with:\n #{run_info.failure.message}"
36
-
37
- else
38
- report_str += '.'
39
- end
40
-
41
- report_str += "\n"
42
- failures += 1
43
-
44
- else
45
- report_str += " but an unexpected error occured during run\n"
46
- report_str += format_exception(run_info.error)
47
- errors += 1
48
- end
49
- end
50
-
51
- if failures + errors > 0
52
- summary = ''
53
- summary += "#{run_infos.length - failures - errors - skipped} succeeded "
54
- summary += "#{failures} failures " if failures > 0
55
- summary += "#{errors} errors " if errors > 0
56
- summary += "#{skipped} skipped " if skipped > 0
57
- summary += "#{run_infos.length} total"
58
- print "\n#{summary}\n".red
59
- else
60
- summary = ''
61
- summary = "\nRun finished successfully"
62
- summary += " (#{skipped} skipped)" if skipped > 0
63
- print "#{summary}\n".green
64
- end
65
-
66
- puts report_str.red
67
- end
68
-
69
- private
70
-
71
- def format_title run_info
72
- title = run_info.spec.subject.desc
73
- title += ' ' + run_info.spec.desc
74
- title += " (#{'%.3f' % run_info.duration}s)"
75
- title += " [#{run_info.spec.name}]"
76
- title
77
- end
78
-
79
- def format_exception error
80
- non_spectre_files = error.backtrace.select { |x| !x.include? 'lib/spectre' }
81
-
82
- if non_spectre_files.count > 0
83
- causing_file = non_spectre_files.first
84
- else
85
- causing_file = error.backtrace[0]
86
- end
87
-
88
- matches = causing_file.match(/(.*\.rb):(\d+)/)
89
-
90
- return '' unless matches
91
-
92
- file, line = matches.captures
93
- file.slice!(Dir.pwd + '/')
94
-
95
- str = ''
96
- str += " file.....: #{file}\n"
97
- str += " line.....: #{line}\n"
98
- str += " type.....: #{error.class}\n"
99
- str += " message..: #{error.message}\n"
100
- str
101
- end
102
- end
103
- end
1
+ module Spectre::Reporter
2
+ class Console
3
+ def initialize config
4
+ @config = config
5
+ end
6
+
7
+ def report run_infos
8
+ report_str = ''
9
+
10
+ errors = 0
11
+ failures = 0
12
+ skipped = run_infos.select { |x| x.skipped? }.count
13
+
14
+ run_infos
15
+ .select { |x| x.error != nil or x.failure != nil }
16
+ .each_with_index do |run_info, index|
17
+ spec = run_info.spec
18
+
19
+ report_str += "\n#{index+1}) #{format_title(run_info)}\n"
20
+
21
+ if run_info.failure
22
+ report_str += " Expected #{run_info.failure.expectation}"
23
+ report_str += " with #{run_info.data}" if run_info.data
24
+ report_str += " during #{spec.context.__desc}" if spec.context.__desc
25
+
26
+ report_str += " but it failed"
27
+
28
+ if run_info.failure.cause
29
+ report_str += "\n with an unexpected error:\n"
30
+ report_str += format_exception(run_info.failure.cause)
31
+
32
+ elsif run_info.failure.message and not run_info.failure.message.empty?
33
+ report_str += " with:\n #{run_info.failure.message}"
34
+
35
+ else
36
+ report_str += '.'
37
+ end
38
+
39
+ report_str += "\n"
40
+ failures += 1
41
+
42
+ else
43
+ report_str += " but an unexpected error occured during run\n"
44
+ report_str += format_exception(run_info.error)
45
+ errors += 1
46
+ end
47
+ end
48
+
49
+ if failures + errors > 0
50
+ summary = ''
51
+ summary += "#{run_infos.length - failures - errors - skipped} succeeded "
52
+ summary += "#{failures} failures " if failures > 0
53
+ summary += "#{errors} errors " if errors > 0
54
+ summary += "#{skipped} skipped " if skipped > 0
55
+ summary += "#{run_infos.length} total"
56
+ print "\n#{summary}\n".red
57
+ else
58
+ summary = ''
59
+ summary = "\nRun finished successfully"
60
+ summary += " (#{skipped} skipped)" if skipped > 0
61
+ print "#{summary}\n".green
62
+ end
63
+
64
+ puts report_str.red
65
+ end
66
+
67
+ private
68
+
69
+ def format_title run_info
70
+ title = run_info.spec.subject.desc
71
+ title += ' ' + run_info.spec.desc
72
+ title += " (#{'%.3f' % run_info.duration}s)"
73
+ title += " [#{run_info.spec.name}]"
74
+ title
75
+ end
76
+
77
+ def format_exception error
78
+ non_spectre_files = error.backtrace.select { |x| !x.include? 'lib/spectre' }
79
+
80
+ if non_spectre_files.count > 0
81
+ causing_file = non_spectre_files.first
82
+ else
83
+ causing_file = error.backtrace[0]
84
+ end
85
+
86
+ matches = causing_file.match(/(.*\.rb):(\d+)/)
87
+
88
+ return '' unless matches
89
+
90
+ file, line = matches.captures
91
+ file.slice!(Dir.pwd + '/')
92
+
93
+ str = ''
94
+ str += " file.....: #{file}\n"
95
+ str += " line.....: #{line}\n"
96
+ str += " type.....: #{error.class}\n"
97
+ str += " message..: #{error.message}\n"
98
+ str += " backtrace: \n #{error.backtrace.join("\n ")}\n" if @config['debug']
99
+ str
100
+ end
101
+ end
102
+ end
@@ -1,98 +1,100 @@
1
- # https://llg.cubic.org/docs/junit/
2
- # Azure mappings: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/test/publish-test-results?view=azure-devops&tabs=junit%2Cyaml
3
-
4
- module Spectre::Reporter
5
- class JUnit
6
- def initialize config
7
- @config = config
8
- end
9
-
10
- def report run_infos
11
- now = Time.now.getutc
12
- timestamp = now.strftime('%s')
13
- datetime = now.strftime('%FT%T%:z')
14
-
15
- xml_str = '<?xml version="1.0" encoding="UTF-8" ?>'
16
- xml_str += '<testsuites>'
17
-
18
- suite_id = 0
19
-
20
- run_infos.group_by { |x| x.spec.subject }.each do |subject, run_infos|
21
- failures = run_infos.select { |x| x.failure != nil }
22
- errors = run_infos.select { |x| x.error != nil }
23
- skipped = run_infos.select { |x| x.skipped? }
24
-
25
- xml_str += '<testsuite package="' + subject.desc + '" id="' + suite_id.to_s + '" name="' + subject.desc + '" timestamp="' + datetime + '" tests="' + run_infos.count.to_s + '" failures="' + failures.count.to_s + '" errors="' + errors.count.to_s + '" skipped="' + skipped.count.to_s + '">'
26
- suite_id += 1
27
-
28
- run_infos.each do |run_info|
29
- xml_str += '<testcase classname="' + run_info.spec.file.to_s + '" name="' + run_info.spec.desc + '" timestamp="' + run_info.started.to_s + '" time="' + ('%.3f' % run_info.duration) + '">'
30
-
31
- if run_info.failure and !run_info.failure.cause
32
- failure_message = "Expected #{run_info.failure.expectation}"
33
- failure_message += " with #{run_info.data}" if run_info.data
34
-
35
- if run_info.failure.message
36
- failure_message += " but it failed with #{run_info.failure.message}"
37
- else
38
- failure_message += " but it failed"
39
- end
40
-
41
- xml_str += '<failure message="' + failure_message.gsub('"', '`') + '"></failure>'
42
- end
43
-
44
-
45
- if run_info.error or (run_info.failure and run_info.failure.cause)
46
- error = run_info.error || run_info.failure.cause
47
-
48
- type = error.class.name
49
- failure_message = error.message
50
- text = error.backtrace.join "\n"
51
-
52
- xml_str += '<error message="' + failure_message.gsub('"', '`') + '" type="' + type + '">'
53
- xml_str += '<![CDATA[' + text + ']]>'
54
- xml_str += '</error>'
55
- end
56
-
57
-
58
- if run_info.log.count > 0 or run_info.properties.count > 0 or run_info.data
59
- xml_str += '<system-out>'
60
-
61
- if run_info.properties.count > 0
62
- run_info.properties.each do |key, val|
63
- xml_str += "#{key}: #{val}\n"
64
- end
65
- end
66
-
67
- if run_info.data
68
- data_str = run_info.data
69
- data_str = run_info.data.inspect unless run_info.data.is_a? String or run_info.data.is_a? Integer
70
- xml_str += "data: #{data_str}\n"
71
- end
72
-
73
- if run_info.log.count > 0
74
- messages = run_info.log.map { |x| "[#{x[0].strftime('%F %T')}] #{x[1]}" }
75
- xml_str += messages.join("\n")
76
- end
77
-
78
- xml_str += '</system-out>'
79
- end
80
-
81
- xml_str += '</testcase>'
82
- end
83
-
84
- xml_str += '</testsuite>'
85
- end
86
-
87
- xml_str += '</testsuites>'
88
-
89
- Dir.mkdir @config['out_path'] if not Dir.exist? @config['out_path']
90
-
91
- file_path = File.join(@config['out_path'], "spectre-junit_#{timestamp}.xml")
92
-
93
- File.open(file_path, 'w') do |file|
94
- file.write(xml_str)
95
- end
96
- end
97
- end
98
- end
1
+ # https://llg.cubic.org/docs/junit/
2
+ # Azure mappings: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/test/publish-test-results?view=azure-devops&tabs=junit%2Cyaml
3
+
4
+ module Spectre::Reporter
5
+ class JUnit
6
+ def initialize config
7
+ @config = config
8
+ end
9
+
10
+ def report run_infos
11
+ now = Time.now.getutc
12
+ timestamp = now.strftime('%s')
13
+ datetime = now.strftime('%FT%T%:z')
14
+
15
+ xml_str = '<?xml version="1.0" encoding="UTF-8" ?>'
16
+ xml_str += '<testsuites>'
17
+
18
+ suite_id = 0
19
+
20
+ run_infos.group_by { |x| x.spec.subject }.each do |subject, run_infos|
21
+ failures = run_infos.select { |x| x.failure != nil }
22
+ errors = run_infos.select { |x| x.error != nil }
23
+ skipped = run_infos.select { |x| x.skipped? }
24
+
25
+ xml_str += '<testsuite package="' + subject.desc + '" id="' + suite_id.to_s + '" name="' + subject.desc + '" timestamp="' + datetime + '" tests="' + run_infos.count.to_s + '" failures="' + failures.count.to_s + '" errors="' + errors.count.to_s + '" skipped="' + skipped.count.to_s + '">'
26
+ suite_id += 1
27
+
28
+ run_infos.each do |run_info|
29
+ xml_str += '<testcase classname="' + run_info.spec.file.to_s + '" name="' + run_info.spec.desc + '" timestamp="' + run_info.started.to_s + '" time="' + ('%.3f' % run_info.duration) + '">'
30
+
31
+ if run_info.failure and !run_info.failure.cause
32
+ failure_message = "Expected #{run_info.failure.expectation}"
33
+ failure_message += " with #{run_info.data}" if run_info.data
34
+
35
+ if run_info.failure.message
36
+ failure_message += " but it failed with #{run_info.failure.message}"
37
+ else
38
+ failure_message += " but it failed"
39
+ end
40
+
41
+ xml_str += '<failure message="' + failure_message.gsub('"', '`') + '"></failure>'
42
+ end
43
+
44
+
45
+ if run_info.error or (run_info.failure and run_info.failure.cause)
46
+ error = run_info.error || run_info.failure.cause
47
+
48
+ type = error.class.name
49
+ failure_message = error.message
50
+ text = error.backtrace.join "\n"
51
+
52
+ xml_str += '<error message="' + failure_message.gsub('"', '`') + '" type="' + type + '">'
53
+ xml_str += '<![CDATA[' + text + ']]>'
54
+ xml_str += '</error>'
55
+ end
56
+
57
+
58
+ if run_info.log.count > 0 or run_info.properties.count > 0 or run_info.data
59
+ xml_str += '<system-out>'
60
+ xml_str += '<![CDATA['
61
+
62
+ if run_info.properties.count > 0
63
+ run_info.properties.each do |key, val|
64
+ xml_str += "#{key}: #{val}\n"
65
+ end
66
+ end
67
+
68
+ if run_info.data
69
+ data_str = run_info.data
70
+ data_str = run_info.data.inspect unless run_info.data.is_a? String or run_info.data.is_a? Integer
71
+ xml_str += "data: #{data_str}\n"
72
+ end
73
+
74
+ if run_info.log.count > 0
75
+ messages = run_info.log.map { |x| "[#{x[0].strftime('%F %T')}] #{x[1]}" }
76
+ xml_str += messages.join("\n")
77
+ end
78
+
79
+ xml_str += ']]>'
80
+ xml_str += '</system-out>'
81
+ end
82
+
83
+ xml_str += '</testcase>'
84
+ end
85
+
86
+ xml_str += '</testsuite>'
87
+ end
88
+
89
+ xml_str += '</testsuites>'
90
+
91
+ Dir.mkdir @config['out_path'] unless Dir.exist? @config['out_path']
92
+
93
+ file_path = File.join(@config['out_path'], "spectre-junit_#{timestamp}.xml")
94
+
95
+ File.open(file_path, 'w') do |file|
96
+ file.write(xml_str)
97
+ end
98
+ end
99
+ end
100
+ end
@@ -1,46 +1,49 @@
1
- require 'ostruct'
2
-
3
- module Spectre
4
- module Resources
5
- class ResourceCollection
6
- def initialize
7
- @items = {}
8
- end
9
-
10
- def add name, path
11
- @items[name] = path
12
- end
13
-
14
- def [] name
15
- raise "Resource with name '#{name}' does not exist" if not @items.key? name
16
- @items[name]
17
- end
18
- end
19
-
20
- class << self
21
- @@resources = ResourceCollection.new
22
-
23
- def resources
24
- @@resources
25
- end
26
- end
27
-
28
- Spectre.register do |config|
29
- return if !config.key? 'resource_paths'
30
-
31
- config['resource_paths'].each do |resource_path|
32
- resource_files = Dir.glob File.join(resource_path, '**/*')
33
-
34
- resource_files.each do |file|
35
- file.slice! resource_path
36
- file = file[1..-1]
37
- @@resources.add file, File.expand_path(File.join resource_path, file)
38
- end
39
- end
40
-
41
- @@resources.freeze
42
- end
43
-
44
- Spectre.delegate :resources, to: Resources
45
- end
46
- end
1
+ require_relative '../spectre'
2
+
3
+ require 'ostruct'
4
+
5
+ module Spectre
6
+ module Resources
7
+ class ResourceCollection
8
+ def initialize
9
+ @items = {}
10
+ end
11
+
12
+ def add name, path
13
+ @items[name] = path
14
+ end
15
+
16
+ def [] name
17
+ raise "Resource with name '#{name}' does not exist" unless @items.key? name
18
+
19
+ @items[name]
20
+ end
21
+ end
22
+
23
+ class << self
24
+ @@resources = ResourceCollection.new
25
+
26
+ def resources
27
+ @@resources
28
+ end
29
+ end
30
+
31
+ Spectre.register do |config|
32
+ return unless config.key? 'resource_paths'
33
+
34
+ config['resource_paths'].each do |resource_path|
35
+ resource_files = Dir.glob File.join(resource_path, '**/*')
36
+
37
+ resource_files.each do |file|
38
+ file.slice! resource_path
39
+ file = file[1..-1]
40
+ @@resources.add file, File.expand_path(File.join resource_path, file)
41
+ end
42
+ end
43
+
44
+ @@resources.freeze
45
+ end
46
+
47
+ Spectre.delegate :resources, to: self
48
+ end
49
+ end