uspec 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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