uspec 1.3.0 → 1.5.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,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d17e77cb5065265172f613c90f9edfb022c217386b56d34af6858b078ba406d8
4
- data.tar.gz: 1c77be04e49ca61e243d7c35aa84c9de56dac3ae8f099ba351f6efa5d9a5ca38
3
+ metadata.gz: f5ebd02acebff5a7d7ffa72dfe23a30b6ef1789acffb41b540758d1cf4d1f083
4
+ data.tar.gz: ffbc0c4e20c8a4c4376e0ba059ecedc9e8f1589ada86a31998a6b628b1d30df9
5
5
  SHA512:
6
- metadata.gz: cf99ec58c05e076e9060b7ac71271e5fcdfd8ab44e03810b41a1ac2a67a4921777dca4ed2a5c27637f071b20fabb0262118b4a7214448b63ea8193450dc663b6
7
- data.tar.gz: eb1c4de66aef1dfef542774fd18b9484bf26778bfe5651c0594fc6cd543472003c32484048435a41d9baacdf3695376fcb1e25fd659ff36183072ddb44eafb41
6
+ metadata.gz: aecd905b5420be09dca096a188180e98b6af4514e82d58d3e510500d33899e21034ba143bb77de0536e2f00b126e4635478ecc48f7f6b2b2fa7a6c614d3f3e42
7
+ data.tar.gz: 98990be1d95c445bb8791b3fc11acefc4fc90013ae533b884db4829ad4e965695d58c1788bdc250fe9181a5eb30956b6f17f7c4afa75732e9a71e565f3f90fb7
data/README.markdown CHANGED
@@ -69,7 +69,7 @@ Output
69
69
 
70
70
  Uspec's output is in beautiful ANSI technicolor, with red for failures, green for successes, and yellow for pending specs.
71
71
 
72
- ![Screenshot!](https://i.imgur.com/Baqggck.png)
72
+ ![uspec examples](https://github.com/acook/uspec/assets/71984/0ceb4319-e671-4159-88d6-6319ebf6cbd3)
73
73
 
74
74
  A brief explanation of `uspec`'s output to show you what it can do!
75
75
 
@@ -1,21 +1,20 @@
1
1
  require_relative 'spec_helper'
2
2
 
3
- spec 'I love passing tests' do
3
+ spec 'I love passing tests! Passing tests return `true`' do
4
4
  true
5
5
  end
6
6
 
7
7
  spec "This is an idea, but I haven't written the test yet"
8
8
 
9
- spec 'Failing tests display a red' do
9
+ spec 'This is a failing test. Failing tests return `false`' do
10
10
  false
11
11
  end
12
12
 
13
- spec 'Inspects non-boolean value that the spec block returns' do
13
+ spec 'Non-boolean values are shown in detail' do
14
14
  'non-boolean value'
15
15
  end
16
16
 
17
- spec 'Displays informative exceptions' do
17
+ spec 'Exceptions are handled and displayed' do
18
18
  class ExampleError < RuntimeError; end
19
- raise ExampleError
19
+ raise ExampleError, "an example error for demonstration"
20
20
  end
21
-
@@ -1,10 +1,3 @@
1
1
  require 'bundler/setup'
2
2
 
3
3
  Bundler.require :development, :test
4
-
5
- require 'uspec'
6
-
7
- Dir.chdir File.dirname(__FILE__)
8
-
9
- extend Uspec
10
-
data/lib/uspec/cli.rb CHANGED
@@ -3,8 +3,6 @@ require_relative '../uspec'
3
3
 
4
4
  class Uspec::CLI
5
5
  def initialize args
6
- usage unless (args & %w[-h --help -? /? -v --version]).empty?
7
-
8
6
  @paths = args
9
7
  @pwd = Pathname.pwd.freeze
10
8
  @stats = Uspec::Stats.new
@@ -15,6 +13,9 @@ class Uspec::CLI
15
13
  def usage
16
14
  warn "uspec v#{::Uspec::VERSION} - minimalistic ruby testing framework"
17
15
  warn "usage: #{File.basename $0} [<file_or_path>...]"
16
+ warn ""
17
+ warn "\t\t--full_backtrace\tshow full backtrace"
18
+ warn "\t\t--\t\t\tstop checking paths for options (good if a path begins with a dash)"
18
19
  exit 1
19
20
  end
20
21
 
@@ -23,6 +24,7 @@ class Uspec::CLI
23
24
  end
24
25
 
25
26
  def invoke
27
+ parse_options @paths
26
28
  run_specs
27
29
  die!
28
30
  end
@@ -61,49 +63,42 @@ class Uspec::CLI
61
63
  end
62
64
 
63
65
  def run_paths
66
+ check_options = true
67
+
64
68
  paths.each do |path|
65
69
  run @pwd.join path
66
70
  end
67
71
  end
68
72
 
69
73
  def run path
70
- spec = nil
74
+ p, line = path.to_s.split(?:)
75
+ path = Pathname.new p
76
+
71
77
  if path.directory? then
72
78
  Pathname.glob(path.join('**', '**_spec.rb')).each do |spec|
73
79
  run spec
74
80
  end
75
81
  elsif path.exist? then
76
82
  puts "#{path.basename path.extname}:"
77
- harness.define.instance_eval(path.read, path.to_s)
83
+ harness.file_eval path, line
78
84
  else
79
85
  warn "path not found: #{path}"
80
86
  end
81
- rescue Exception => error
87
+ end
82
88
 
83
- if SignalException === error || SystemExit === error then
84
- exit 3
89
+ def parse_options args
90
+ args.each_with_index do |arg, i|
91
+ if arg == '--' then
92
+ return args
93
+ elsif arg == '--full_backtrace' then
94
+ Uspec::Errors.full_backtrace!
95
+ args.delete_at i
96
+ elsif !(args & %w[-h --help -? /? -v --version]).empty?
97
+ usage
98
+ elsif arg[0] == ?- then
99
+ warn "unknown option: #{arg}"
100
+ args.delete_at i
101
+ end
85
102
  end
86
-
87
- error_file, error_line, _ = error.backtrace.first.split ?:
88
-
89
- message = <<-MSG
90
- #{error.class} : #{error.message}
91
-
92
- Uspec encountered an error when loading a test file.
93
- This is probably a typo in the test file or the file it is testing.
94
-
95
- If you think this is a bug in Uspec please report it: https://github.com/acook/uspec/issues/new
96
-
97
- Error occured when loading test file `#{spec || path}`.
98
- The origin of the error may be in file `#{error_file}` on line ##{error_line}.
99
-
100
- \t#{error.backtrace[0,3].join "\n\t"}
101
- MSG
102
- puts
103
- warn message
104
- stats << Uspec::Result.new(message, error, caller)
105
-
106
- handle_interrupt! error
107
103
  end
108
-
109
104
  end
data/lib/uspec/define.rb CHANGED
@@ -6,7 +6,7 @@ module Uspec
6
6
  end
7
7
 
8
8
  def spec description, &block
9
- @__uspec_harness.spec_eval description, &block
9
+ @__uspec_harness.spec_eval description, caller, &block
10
10
  end
11
11
  end
12
12
  end
@@ -0,0 +1,177 @@
1
+ require_relative "terminal"
2
+
3
+ module Uspec
4
+ module Errors
5
+ module_function
6
+
7
+ extend Uspec::Terminal
8
+
9
+ MSG_USPEC_BUG_URL = "https://github.com/acook/uspec/issues/new"
10
+ MSG_IF_USPEC_BUG = "If you think this is a bug in Uspec please report it: #{MSG_USPEC_BUG_URL}"
11
+ TRACE_EXCLUDE_PATTERN = /#{Uspec.libpath.join 'lib'}|#{Uspec.libpath.join 'bin'}/
12
+
13
+ def handle_file_error error, path, cli = nil
14
+ error_info = error_context error
15
+
16
+ message = <<~MSG
17
+ Uspec encountered an error when loading a test file.
18
+ This is probably a typo in the test file or the file it is testing.
19
+
20
+ Error occured when loading test file `#{path}`.
21
+ #{error_info}
22
+ MSG
23
+
24
+ handle_error message, error, cli
25
+ end
26
+
27
+ def handle_internal_error error, cli = nil
28
+ error_info = error_context error, skip_internal: false
29
+
30
+ message = <<~MSG
31
+ Uspec encountered an internal error!
32
+
33
+ #{error_info}
34
+ MSG
35
+
36
+ handle_error message, error, cli
37
+ end
38
+
39
+ def handle_error message, error, cli
40
+ result = Uspec::Result.new(message, error, true)
41
+
42
+ puts
43
+ warn error_format error, message, leading_newline: false
44
+
45
+ cli.handle_interrupt! result.raw if cli
46
+ result
47
+ end
48
+
49
+ def msg_spec_error error, desc
50
+ error_info = error_context error
51
+
52
+ info = <<~MSG
53
+ Error occured when evaluating spec `#{desc}`.
54
+ #{error_info}
55
+ MSG
56
+ body = error_format error, info, first_line_indent: false
57
+
58
+ message = <<~MSG
59
+ #{red 'Exception'}
60
+ #{body}
61
+ MSG
62
+
63
+ message
64
+ end
65
+
66
+ def msg_spec_value error
67
+ error_info = white bt_format(bt_get error).chomp
68
+
69
+ message = <<~MSG
70
+ #{error.message}
71
+ #{error_info}
72
+ MSG
73
+
74
+ error_format error, message, header: false
75
+ end
76
+
77
+ def msg_source_error error, desc, cli = nil
78
+ error_info = error_context error
79
+
80
+ message = <<~MSG
81
+ Uspec detected a bug in your source code!
82
+
83
+ Calling #inspect on an object will recusively call #inspect on its instance variables and contents.
84
+ If one of those contained objects does not have an #inspect method you will see this message.
85
+ You will also get this message if your #inspect method or one of its callees raises an exception.
86
+ This is most likely to happen with BasicObject and its subclasses.
87
+
88
+ Error occured when evaluating spec `#{desc}`.
89
+ #{error_info}
90
+ MSG
91
+
92
+ error_format error, message, first_line_indent: false
93
+ end
94
+
95
+ def error_context error, skip_internal: true
96
+ bt = bt_get error
97
+ error_line = bt.first.split(?:)
98
+ [
99
+ error_origin(*error_line),
100
+ white(bt_format(bt, skip_internal)),
101
+ MSG_IF_USPEC_BUG
102
+ ].join ?\n
103
+ end
104
+
105
+ def bt_get error
106
+ error.backtrace || caller[3..-1]
107
+ end
108
+
109
+ def error_origin error_file, error_line, *_
110
+ "The origin of the error may be in file `#{error_file}` on line ##{error_line}."
111
+ end
112
+
113
+ def error_format error, message, first_line_indent: true, leading_newline: true, header: true
114
+ h = ""
115
+
116
+ if header then
117
+ h << newline if leading_newline
118
+ h << hspace if first_line_indent
119
+ h << error_header(error)
120
+ h << vspace
121
+ end
122
+
123
+ error_indent(error, h + message)
124
+ end
125
+
126
+ def error_indent error, message
127
+ a = message.split(newline)
128
+ a << ""
129
+ a.join("#{newline}#{hspace}")
130
+ end
131
+
132
+ def error_header error
133
+ "#{red subklassinfo error}#{error.message}"
134
+ end
135
+
136
+ def subklassinfo obj
137
+ "#{::TOISB.wrap(obj).subklassinfo}: "
138
+ end
139
+
140
+ def bt_format bt, skip_internal = true
141
+ skip_internal = skip_internal && !full_backtrace?
142
+ bt_indent bt_clean(bt, skip_internal)
143
+ end
144
+
145
+ def bt_indent bt
146
+ "#{newline}#{hspace}" + bt.join("#{newline}#{hspace}") + newline if bt
147
+ end
148
+
149
+ def bt_clean bt, skip_internal = true
150
+ bt.inject(Array.new) do |t, line|
151
+ next t if skip_internal && line.match(TRACE_EXCLUDE_PATTERN)
152
+ t << bt_rewrite_caller(line)
153
+ end if bt
154
+ end
155
+
156
+ def bt_rewrite_caller line
157
+ return line if full_backtrace?
158
+ if line.match TRACE_EXCLUDE_PATTERN then
159
+ line
160
+ else
161
+ line.sub /file_eval/, 'spec_block'
162
+ end
163
+ end
164
+
165
+ def full_backtrace?
166
+ @full_backtrace
167
+ end
168
+
169
+ def full_backtrace!
170
+ @full_backtrace = true
171
+ end
172
+
173
+ def clean_backtrace!
174
+ @full_backtrace = false
175
+ end
176
+ end
177
+ end
data/lib/uspec/harness.rb CHANGED
@@ -14,45 +14,55 @@ module Uspec
14
14
  cli.stats
15
15
  end
16
16
 
17
- def spec_eval description, &block
17
+ def file_eval path, line
18
+ @path = path
19
+ @line = line
20
+ define.instance_eval(path.read, path.to_s)
21
+ rescue Exception => error
22
+ raise error if SystemExit === error
23
+ result = Uspec::Errors.handle_file_error error, path, cli
24
+ stats << result if result
25
+ end
26
+
27
+ def spec_eval description, source, &block
28
+ return if @line && !source.first.include?("#{@path}:#{@line}")
29
+
30
+ ex = nil
18
31
  state = 0
19
32
  print ' -- ', description
20
33
 
21
34
  if block then
22
35
  begin
23
36
  state = 1
24
- raw_result = Uspec::Spec.new(self, description, &block).__uspec_block
37
+ spec = Uspec::Spec.new(self, description, &block)
38
+ raw_result = spec.__uspec_block
25
39
  state = 2
26
40
  rescue Exception => raw_result
27
41
  state = 3
42
+ ex = true
28
43
  end
29
44
  end
30
45
 
31
- result = Uspec::Result.new description, raw_result, caller
46
+ result = Uspec::Result.new spec, raw_result, ex
32
47
 
33
48
  unless block then
34
49
  state = 4
35
50
  result.pending!
36
51
  end
37
52
 
38
- stats << result
39
-
40
53
  print ': ', result.pretty, "\n"
41
54
  rescue => error
42
- state = 5
43
- message = <<-MSG
44
- #{error.class} : #{error.message}
45
-
46
- Uspec encountered an internal error, please report this bug: https://github.com/acook/uspec/issues/new
47
-
48
- \t#{error.backtrace.join "\n\t"}
49
- MSG
50
- puts
51
- warn message
52
- stats << Uspec::Result.new(message, error, caller)
55
+ result = Uspec::Errors.handle_internal_error error, cli
53
56
  ensure
54
- cli.handle_interrupt! result.raw
57
+ stats << result if result
58
+ cli.handle_interrupt! result ? result.raw : raw_result
55
59
  return [state, error, result, raw_result]
56
60
  end
61
+
62
+ def inspect
63
+ <<~MSG.chomp
64
+ <#{self.class}##{self.object_id} @cli=#{@cli ? '<...>' : @cli} @define=#{@define ? '<...>' : @define}>
65
+ MSG
66
+ end
57
67
  end
58
68
  end
data/lib/uspec/result.rb CHANGED
@@ -7,13 +7,15 @@ module Uspec
7
7
 
8
8
  PREFIX = "#{Uspec::Terminal.newline}#{Uspec::Terminal.yellow}>\t#{Uspec::Terminal.normal}"
9
9
 
10
- def initialize spec, raw, source
10
+ def initialize spec, raw, ex
11
11
  @spec = spec
12
12
  @raw = raw
13
- @source = source
13
+ @ex = ex
14
14
  @handler = ::TOISB.wrap raw
15
+ @full_backtrace = false
16
+ @caller = caller
15
17
  end
16
- attr_reader :spec, :raw, :source, :handler
18
+ attr_reader :spec, :raw, :ex, :handler, :full_backtrace
17
19
 
18
20
  def pretty
19
21
  if raw == true then
@@ -22,70 +24,60 @@ module Uspec
22
24
  red raw
23
25
  elsif pending? then
24
26
  yellow 'pending'
25
- elsif Exception === raw then
26
- [
27
- red('Exception'), vspace,
28
- hspace, 'Spec encountered an Exception ', newline,
29
- hspace, 'in spec at ', source.first, vspace,
30
- hspace, message, vspace,
31
- white(trace)
32
- ].join
27
+ elsif ex == true then
28
+ Uspec::Errors.msg_spec_error raw, desc
33
29
  else
34
- [
35
- red('Failed'), vspace,
36
- hspace, 'Spec did not return a boolean value ', newline,
37
- hspace, 'in spec at ', source.first, vspace,
38
- hspace, red(subklassinfo), inspector, (Class === raw ? ' Class' : ''), newline
39
- ].join
40
- end
41
- end
42
-
43
- def trace
44
- raw.backtrace.inject(String.new) do |text, line|
45
- text << "#{hspace}#{line}#{newline}"
30
+ nonboolean
46
31
  end
47
32
  end
48
33
 
49
- def message
50
- "#{red subklassinfo}#{raw.message}"
34
+ def source
35
+ @source ||= Uspec::Errors.bt_clean @caller
51
36
  end
52
37
 
53
38
  def subklassinfo
54
39
  "#{handler.subklassinfo}: "
55
40
  end
56
41
 
42
+ def desc
43
+ if String === spec then
44
+ spec
45
+ elsif Uspec::Spec === spec then
46
+ spec.instance_variable_get :@__uspec_description
47
+ else
48
+ spec.inspect
49
+ end
50
+ end
51
+
52
+ def nonboolean
53
+ [
54
+ red('Failed'), vspace,
55
+ hspace, 'Spec did not return a boolean value ', newline,
56
+ hspace, 'in spec at ', source.first, vspace,
57
+ hspace, red(subklassinfo), inspector, (Class === raw ? ' Class' : ''), newline
58
+ ].join
59
+
60
+ end
61
+
57
62
  # Attempts to inspect an object
58
63
  def inspector
59
64
  if String === raw && raw.include?(?\n) then
60
65
  # if object is a multiline string, display it unescaped
61
-
62
66
  [
63
67
  raw.split(newline).unshift(newline).join(PREFIX), normal, newline,
64
68
  ].join
69
+ elsif Exception === raw then
70
+ Uspec::Errors.msg_spec_value raw
65
71
  else
66
72
  handler.inspector!
67
73
  end
68
74
  rescue Exception => error
69
75
  return handler.simple_inspector if error.message.include? handler.get_id
70
76
 
71
- error_file, error_line, _ = error.backtrace[4].split ?:
72
-
73
- <<-MSG
74
-
75
- #{error.class} : #{error.message}
76
-
77
- Uspec detected a bug in your source code!
78
- Calling #inspect on an object will recusively call #inspect on its instance variables and contents.
79
- If one of those contained objects does not have an #inspect method you will see this message.
80
- You will also get this message if your #inspect method or one of its callees raises an exception.
81
- This is most likely to happen with BasicObject and its subclasses.
82
-
83
- If you think this is a bug in Uspec please report it: https://github.com/acook/uspec/issues/new
84
-
85
- Error may have occured in test `#{spec}` in file `#{error_file}` on line ##{error_line}.
86
-
87
- \t#{error.backtrace.join "\n\t"}
88
- MSG
77
+ [
78
+ red('Unable to Inspect Object'), newline,
79
+ Uspec::Errors.msg_source_error(error, desc),
80
+ ].join
89
81
  end
90
82
 
91
83
  def success?
@@ -105,7 +97,7 @@ module Uspec
105
97
  end
106
98
 
107
99
  def inspect
108
- "#{self.class} for `#{spec}` -> #{pretty}"
100
+ "#{self.class} for `#{desc}` -> #{pretty}"
109
101
  end
110
102
  end
111
103
  end
data/lib/uspec/spec.rb CHANGED
@@ -5,6 +5,7 @@ module Uspec
5
5
 
6
6
  def initialize harness, description, &block
7
7
  @__uspec_description = description
8
+ @__uspec_block = block
8
9
  @__uspec_harness = harness
9
10
  ns = harness.define
10
11
 
data/lib/uspec/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Uspec
2
- VERSION = '1.3.0'
2
+ VERSION = '1.5.0'
3
3
  end
data/lib/uspec.rb CHANGED
@@ -1,8 +1,3 @@
1
- require_relative 'uspec/version'
2
- require_relative 'uspec/harness'
3
- require_relative 'uspec/define'
4
- require_relative 'uspec/stats'
5
-
6
1
  module Uspec
7
2
  def self.included object
8
3
  warn 'Use extend instead of include.'
@@ -15,4 +10,14 @@ module Uspec
15
10
  # object.extend Uspec::DSL
16
11
  #end
17
12
  end
13
+
14
+ def self.libpath
15
+ Pathname.new(__FILE__).dirname.dirname
16
+ end
18
17
  end
18
+
19
+ require_relative 'uspec/version'
20
+ require_relative 'uspec/errors'
21
+ require_relative 'uspec/harness'
22
+ require_relative 'uspec/define'
23
+ require_relative 'uspec/stats'
data/uspec/cli_spec.rb CHANGED
@@ -1,14 +1,5 @@
1
1
  require_relative 'uspec_helper'
2
2
 
3
- def new_cli path = '.'
4
- Uspec::CLI.new(Array(path))
5
- end
6
-
7
- def run_specs path
8
- new_cli(path).run_specs
9
- end
10
-
11
-
12
3
  spec 'shows usage' do
13
4
  output = capture do
14
5
  exec 'bin/uspec -h'
@@ -25,7 +16,7 @@ spec 'runs a path of specs' do
25
16
  output.include?('I love passing tests') || output
26
17
  end
27
18
 
28
- spec 'runs an individual spec' do
19
+ spec 'runs an individual file' do
29
20
  output = outstr do
30
21
  run_specs exdir.join('example_spec.rb').to_s
31
22
  end
@@ -33,6 +24,14 @@ spec 'runs an individual spec' do
33
24
  output.include?('I love passing tests') || output
34
25
  end
35
26
 
27
+ spec 'runs an individual spec' do
28
+ output = outstr do
29
+ run_specs exdir.join('example_spec.rb:13').to_s
30
+ end
31
+
32
+ !output.include?('I love passing tests') && output.include?('non-boolean') || output
33
+ end
34
+
36
35
  spec 'broken requires in test files count as test failures' do
37
36
  output, status = Open3.capture2e "#{root}/bin/uspec #{testdir.join('broken_require_spec')}"
38
37
 
data/uspec/dsl_spec.rb CHANGED
@@ -4,7 +4,7 @@ spec 'catches errors' do
4
4
  cli = new_cli
5
5
 
6
6
  output = outstr do
7
- cli.harness.define.spec 'exception' do
7
+ cli.harness.define.spec 'exception spec' do
8
8
  raise 'test exception'
9
9
  end
10
10
  end
@@ -0,0 +1,37 @@
1
+ require_relative "uspec_helper"
2
+
3
+ spec 'file errors are captured' do
4
+ cli = new_cli
5
+
6
+ output = outstr do
7
+ cli.harness.file_eval testdir.join('broken_require_spec'), nil
8
+ end
9
+
10
+ output.include?('Uspec encountered an error when loading') || output
11
+ end
12
+
13
+ spec 'internal errors are captured' do
14
+ cli = new_cli
15
+
16
+ output = outstr do
17
+ cli.harness.spec_eval BasicObject.new, BasicObject.new do
18
+ raise 'block error'
19
+ end
20
+ end
21
+
22
+ output.include?('Uspec encountered an internal error') || output
23
+ end
24
+
25
+ spec 'source errors are captured' do
26
+ bo = BasicObject.new
27
+ def bo.inspect
28
+ invalid_for_source_error
29
+ end
30
+
31
+ a = [ bo ]
32
+
33
+ result = Uspec::Result.new "source error result", a, true
34
+ output = result.inspector
35
+
36
+ output.include?('Uspec detected a bug in your source') || output
37
+ end
data/uspec/result_spec.rb CHANGED
@@ -3,7 +3,7 @@ require_relative "uspec_helper"
3
3
  bo = BasicObject.new
4
4
 
5
5
  spec "#pretty doesn't die when given a BasicObject" do
6
- result = Uspec::Result.new "BasicObject Result", bo, []
6
+ result = Uspec::Result.new "BasicObject Result", bo, nil
7
7
  expected = "#<BasicObject:"
8
8
  actual = result.pretty
9
9
  actual.include?(expected) || actual
@@ -14,28 +14,28 @@ class ::TestObject < BasicObject; end
14
14
  obj = TestObject.new
15
15
 
16
16
  spec "ensure BasicObject subclass instances work" do
17
- result = Uspec::Result.new "BasicObject Subclass Result", obj, []
17
+ result = Uspec::Result.new "BasicObject Subclass Result", obj, nil
18
18
  expected = "#<BasicObject/TestObject:"
19
19
  actual = result.pretty
20
20
  actual.include?(expected) || result.pretty
21
21
  end
22
22
 
23
23
  spec "display basic info about Object" do
24
- result = Uspec::Result.new "Object Result", Object.new, []
24
+ result = Uspec::Result.new "Object Result", Object.new, nil
25
25
  expected = "Object < BasicObject: \e[0m#<Object:"
26
26
  actual = result.pretty
27
27
  actual.include?(expected) || result.pretty
28
28
  end
29
29
 
30
30
  spec "display basic info about Array" do
31
- result = Uspec::Result.new "Array Result", [], []
31
+ result = Uspec::Result.new "Array Result", [], nil
32
32
  expected = "Array < Object"
33
33
  actual = result.pretty
34
34
  actual.include?(expected) || result.pretty
35
35
  end
36
36
 
37
37
  spec "display basic info about Array class" do
38
- result = Uspec::Result.new "Array Class Result", Array, []
38
+ result = Uspec::Result.new "Array Class Result", Array, nil
39
39
  expected = "Class < Module: \e[0mArray Class"
40
40
  actual = result.pretty
41
41
  actual.include?(expected) || result.pretty
@@ -44,7 +44,7 @@ end
44
44
  parent = [obj]
45
45
 
46
46
  spec "ensure parent object of BasicObject subclasses get a useful error message" do
47
- result = Uspec::Result.new "BasicObject Parent Result", parent, []
47
+ result = Uspec::Result.new "BasicObject Parent Result", parent, nil
48
48
  expected = "BasicObject and its subclasses"
49
49
  actual = result.pretty
50
50
  actual.include?(expected) || result.inspector
@@ -54,7 +54,7 @@ class ::InspectFail; def inspect; raise RuntimeError, "This error is intentional
54
54
  inspect_fail = InspectFail.new
55
55
 
56
56
  spec "display a useful error message when a user-defined inspect method fails" do
57
- result = Uspec::Result.new "Inspect Fail Result", inspect_fail, []
57
+ result = Uspec::Result.new "Inspect Fail Result", inspect_fail, nil
58
58
  expected = "raises an exception"
59
59
  actual = result.pretty
60
60
  actual.include?(expected) || result.inspector
@@ -63,7 +63,52 @@ end
63
63
  spec "display strings more like their actual contents" do
64
64
  string = "this string:\nshould display \e\[42;2mproperly"
65
65
  expected = /this string:\n.*should display \e\[42;2mproperly/
66
- result = Uspec::Result.new "Inspect Fail Result", string, []
66
+ result = Uspec::Result.new "Inspect Fail Result", string, nil
67
67
  actual = result.pretty
68
68
  actual.match?(expected) || result.inspector
69
69
  end
70
+
71
+ def exception_value
72
+ raise "A test exception!"
73
+ rescue => err
74
+ return err
75
+ end
76
+
77
+ spec "handles exception values" do
78
+ result = Uspec::Result.new "Exception Value Result", exception_value, nil
79
+ expected = "RuntimeError < StandardError: \e[0mA test exception!"
80
+ actual = result.pretty
81
+ actual.include?(expected) || result.pretty
82
+ end
83
+
84
+ spec "handles exception values including backtraces" do
85
+ result = Uspec::Result.new "Exception Value Result", exception_value, nil
86
+ expected = "exception_value"
87
+ actual = result.pretty
88
+ actual.include?(expected) || result.pretty
89
+ end
90
+
91
+ spec "handles raised exceptions" do
92
+ result = Uspec::Result.new "Exception Raised Result", exception_value, true
93
+ expected = "RuntimeError < StandardError: \e[0mA test exception!"
94
+ actual = result.pretty
95
+ actual.include?(expected) || result.pretty
96
+ end
97
+
98
+ spec "handles raised exceptions without backtraces" do
99
+ result = Uspec::Result.new "Exception Raised Result", Exception.new, true
100
+ expected = "Exception < Object: \e[0mException"
101
+ actual = result.pretty
102
+ actual.include?(expected) || result.pretty
103
+ end
104
+
105
+ spec "doesn't show 'run' for spec file in stack trace" do
106
+ Uspec::Errors.clean_backtrace!
107
+
108
+ result = Uspec::Result.new "No Run Exception Trace Result", exception_value, true
109
+ expected = /uspec.*run/
110
+ actual = result.pretty
111
+
112
+ Uspec::Errors.full_backtrace!
113
+ !actual.match?(expected) || result.pretty
114
+ end
data/uspec/stats_spec.rb CHANGED
@@ -1,12 +1,19 @@
1
1
  require_relative 'uspec_helper'
2
2
 
3
+ def stats_object
4
+ Uspec::Stats.new
5
+ end
6
+
3
7
  spec 'stats can be inspected' do
8
+ # this is a regression test
9
+ # the issue it covers occured because of a refactor where stats had a custom inspect method
10
+ # stats no longer has a custom inspect method, but this makes sure that nothing breaks
4
11
  actual = @__uspec_harness.stats.inspect
5
12
  actual.include?("failure") || actual
6
13
  end
7
14
 
8
15
  spec 'stats inspect does not have any stray whitespace' do
9
- output = @__uspec_harness.stats.inspect
16
+ output = stats_object.inspect
10
17
  match = output.match /(.*(?: |\n))/m
11
18
  match == nil || match
12
19
  end
@@ -0,0 +1,8 @@
1
+ class ErrorValue < StandardError
2
+ end
3
+
4
+ spec "error value spec" do
5
+ raise ErrorValue, "A test exception!"
6
+ rescue ErrorValue => err
7
+ return err
8
+ end
@@ -0,0 +1,3 @@
1
+ spec BasicObject.new do
2
+ raise 'block error'
3
+ end
@@ -0,0 +1,8 @@
1
+ spec "this spec will create a source error due to a broken inspect method" do
2
+ bo = BasicObject.new
3
+ def bo.inspect
4
+ invalid_for_source_error
5
+ end
6
+
7
+ [ bo ]
8
+ end
@@ -9,6 +9,8 @@ require 'stringio'
9
9
  require_relative '../lib/uspec'
10
10
  extend Uspec
11
11
 
12
+ Uspec::Errors.full_backtrace!
13
+
12
14
  def capture
13
15
  readme, writeme = IO.pipe
14
16
  pid = fork do
@@ -59,3 +61,11 @@ end
59
61
  def testdir
60
62
  specdir.join('test_specs')
61
63
  end
64
+
65
+ def new_cli path = '.'
66
+ Uspec::CLI.new(Array(path))
67
+ end
68
+
69
+ def run_specs path
70
+ new_cli(path).run_specs
71
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony M. Cook
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-23 00:00:00.000000000 Z
11
+ date: 2024-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: that_object_is_so_basic
@@ -50,6 +50,7 @@ files:
50
50
  - lib/uspec.rb
51
51
  - lib/uspec/cli.rb
52
52
  - lib/uspec/define.rb
53
+ - lib/uspec/errors.rb
53
54
  - lib/uspec/harness.rb
54
55
  - lib/uspec/result.rb
55
56
  - lib/uspec/spec.rb
@@ -59,16 +60,20 @@ files:
59
60
  - uspec.gemspec
60
61
  - uspec/cli_spec.rb
61
62
  - uspec/dsl_spec.rb
63
+ - uspec/errors_spec.rb
62
64
  - uspec/result_spec.rb
63
65
  - uspec/stats_spec.rb
64
66
  - uspec/test_specs/break_spec
65
67
  - uspec/test_specs/broken_require_spec
68
+ - uspec/test_specs/error_value_spec
69
+ - uspec/test_specs/internal_error_spec
66
70
  - uspec/test_specs/ivar_spec
67
71
  - uspec/test_specs/kill_this_script.sh
68
72
  - uspec/test_specs/kill_this_spec
69
73
  - uspec/test_specs/method_spec
70
74
  - uspec/test_specs/pending_spec
71
75
  - uspec/test_specs/return_spec
76
+ - uspec/test_specs/source_error_spec
72
77
  - uspec/test_specs/value_spec
73
78
  - uspec/uspec_helper.rb
74
79
  - uspec/uspec_spec.rb