uspec 0.1.1 → 1.0.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: f5dce7ef226b32d0ffef1d178b04c11a474cb3f137bb8697244cec85ace59ad5
4
- data.tar.gz: 9f80cd6442661e2993df1ec9ad7486999d435c962f39adc893db2335f05da4c9
3
+ metadata.gz: adfc4745c3e11f9afa82923366d86c5515745666b98606ded26418cb520b9bb9
4
+ data.tar.gz: b62be6efc2f67ba658c2701b6984764d7fdb36e0acc79f1e20378efeef1c534c
5
5
  SHA512:
6
- metadata.gz: 6cd294e9ec21d0b5d48c2dee3328667e335f6a5c1922d7b28c6d392c146b0237eefa523b42217e6927dab206a453eff72e8f97b5133ec6d86096b3a23df7b037
7
- data.tar.gz: 05f5582a527627d26fbe3563644feb5702fc56d398ac0b5685ffbb953499ba063c238281e175d1b85dcb76b777aed4e4ce05851470da40f27805af340e727461
6
+ metadata.gz: b89e9ab10352cbe0d18278c1d5aa823b72d3d9c40dbf49d0c2791b6f92748841d2018e6ac1ddee04016fa40c6353a76c94d8c6c7bfe11c7197a60606e38180b5
7
+ data.tar.gz: 51dc3f357ffff68b6e7ffc3d1a81376ad2755813490a2749e55bbcef6142ae3432f92076b7dcd5599625f55fb77ce6a8f099612972119bf90f24315e30d7f688
@@ -0,0 +1,21 @@
1
+ version: 2.1
2
+ orbs:
3
+ ruby: circleci/ruby@0.1.2
4
+
5
+ jobs:
6
+ build:
7
+ docker:
8
+ - image: circleci/ruby:2.6.3-stretch-node
9
+ executor: ruby/default
10
+ steps:
11
+ - checkout
12
+ - run:
13
+ name: Which bundler?
14
+ command: bundle -v
15
+ - ruby/bundle-install
16
+ test:
17
+ executor: ruby/default
18
+ steps:
19
+ - run:
20
+ name: Uspec tests
21
+ command: bundle exec uspec
data/.editorconfig ADDED
@@ -0,0 +1,11 @@
1
+ # EditorConfig is awesome: https://EditorConfig.org
2
+
3
+ root = true
4
+
5
+ [*]
6
+ end_of_line = lf
7
+ insert_final_newline = true
8
+ indent_style = space
9
+ indent_size = 2
10
+ charset = utf-8
11
+ trim_trailing_whitespace = true
data/.rubocop.yml ADDED
@@ -0,0 +1,56 @@
1
+ # Rubocop override settings
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.0
5
+
6
+ Metrics/LineLength:
7
+ Max: 120
8
+ Exclude:
9
+ - config_module.gemspec
10
+ - "uspec/**/*"
11
+
12
+ Naming/PredicateName:
13
+ Enabled: false
14
+
15
+ Style/PreferredHashMethods:
16
+ Exclude:
17
+ - "**/*"
18
+
19
+ Style/Documentation:
20
+ Enabled: false
21
+
22
+ Style/MethodDefParentheses:
23
+ Enabled: false
24
+
25
+ Style/ParallelAssignment:
26
+ Enabled: false
27
+
28
+ Style/SingleLineMethods:
29
+ Enabled: false
30
+
31
+ Style/Alias:
32
+ Enabled: false
33
+
34
+ Style/CaseEquality:
35
+ Enabled: false
36
+
37
+ Style/SymbolArray:
38
+ Enabled: false
39
+
40
+ Bundler/OrderedGems:
41
+ Enabled: false
42
+
43
+ Style/StringLiterals:
44
+ EnforcedStyle: double_quotes
45
+
46
+ Style/StringLiteralsInInterpolation:
47
+ EnforcedStyle: double_quotes
48
+
49
+ Layout/AccessModifierIndentation:
50
+ EnforcedStyle: outdent
51
+
52
+ Style/EnforcedStyleForMultiline:
53
+ EnforcedStyle: consistent_comma
54
+
55
+ Naming/RescuedExceptionsVariableName:
56
+ PreferredName: error
data/README.markdown CHANGED
@@ -3,29 +3,45 @@ Uspec
3
3
 
4
4
  Uspec is a shiny little testing framework for your apps!
5
5
 
6
- [![Build Status](https://travis-ci.org/acook/uspec.png?branch=master)](https://travis-ci.org/acook/uspec)
7
- [![Code Climate](https://codeclimate.com/github/acook/uspec.png)](https://codeclimate.com/github/acook/uspec)
6
+ [![Gem Version](https://img.shields.io/gem/v/uspec.svg?style=for-the-badge)](https://rubygems.org/gems/uspec/)
7
+ [![Build Status](https://img.shields.io/circleci/build/github/acook/uspec.svg?style=for-the-badge)](https://app.circleci.com/pipelines/github/acook/uspec)
8
+ [![Code Climate](https://img.shields.io/codeclimate/maintainability/acook/uspec.svg?style=for-the-badge)](https://codeclimate.com/github/acook/uspec)
8
9
 
9
10
  Philosophy / Why Uspec?
10
11
  -----------------------
11
12
 
12
13
  > Uspec is just Ruby!
13
14
 
14
- Unlike other testing frameworks there's no need for special matchers,
15
- there can only be one assertion per test,
15
+ Unlike other testing frameworks there's no need for special matchers,
16
+ there can only be one assertion per test,
16
17
  and you never have to worry that your tests lack assertions.
17
18
 
18
- That's because when the `spec` block is evaluated the return value is used (in a very ruby-like way)
19
- to determine the validity of the statement. Standard Ruby comparisons are your friend!
19
+ That's because when the `spec` block is evaluated the return value is used (in a very ruby-like way)
20
+ to determine if the test has passed or failed. Standard Ruby comparisons are your friend!
20
21
  No more digging around in your test framework's documentation to figure out what matcher you're supposed to use.
21
22
  This also means *no monkey patching* core classes!
22
23
 
23
- Uspec's output is in beautiful ansi technicolor,
24
+ Uspec's output is in beautiful ansi technicolor,
24
25
  with red for failures, green for successes, and yellow for pending specs. Here's a screenshot:
25
26
 
26
27
  ![Screenshot!](http://i.imgur.com/M2F5YvO.png)
27
28
 
28
- Uspec is tiny, painless, and easy to use. Download it and give it a shot. :)
29
+ Uspec is tiny, painless, and easy to use. Download it and give it a try!
30
+
31
+ Example
32
+ -------
33
+
34
+ Uspec is **just Ruby**. The DSL is minimal - there's only one method to remember!
35
+
36
+ Writing a spec is easy:
37
+
38
+ ```ruby
39
+ spec 'AwesomeMcCoolname.generate creates a cool name' do
40
+ AwesomeMcCoolname.generate.include? 'Cool'
41
+ end
42
+ ```
43
+
44
+ That's it!
29
45
 
30
46
  Installation
31
47
  ------------
@@ -38,7 +54,7 @@ And then execute:
38
54
 
39
55
  $ bundle
40
56
 
41
- Or install it yourself as:
57
+ Or install it directly with:
42
58
 
43
59
  $ gem install uspec
44
60
 
@@ -46,46 +62,31 @@ Or install it yourself as:
46
62
  Quickstart
47
63
  ----------
48
64
 
49
- 0. Create a `spec` directory to keep your specs in.
65
+ 0. Create a `uspec` directory to keep your specs in.
50
66
  1. Name your specs ending with `_spec.rb`.
51
- 2. Write some specs in Ruby using the `spec` method.
67
+ 2. Write some specs in Ruby using the `spec` method (example above).
52
68
  2. Use the included `uspec` executable to run your specs.
53
69
 
54
- **Hint:** A lot of people also put `require_relative 'spec_helper'` in their tests for global start up code.
70
+ **Hint:** A lot of people also put `require_relative 'spec_helper'` at the top of their test files for sharing code between tests.
55
71
 
56
- Usage
57
- -----
72
+ Commandline Usage
73
+ -----------------
58
74
 
59
- ```
75
+ ```
60
76
  $ uspec --help
61
77
  uspec - minimalistic ruby testing framework
62
78
  usage: uspec [<file_or_path>...]
63
79
  ```
64
80
 
65
- - Without arguments the `uspec` command will automatially look for `spec` directories and load any `*_spec.rb` files inside them.
81
+ - Without arguments the `uspec` command will automatially look for a `uspec` directory and load any `*_spec.rb` files inside them.
66
82
  - You can also pass in arbitrary files and it will attempt to run them as specs.
67
- - If you pass in directories `uspec` will find and run any specs inside them.
68
- - Uspec will return `0` if all specs pass and `255` if any fail.
69
-
70
- Syntax
71
- ------
72
-
73
- Uspec is **just Ruby**. The DSL is minimal - there's only one method to remember!
74
-
75
- Writing a spec is easy:
76
-
77
- ```ruby
78
- spec 'AwesomeMcCoolname.generate creates a cool name' do
79
- AwesomeMcCoolname.generate.include? 'Cool'
80
- end
81
- ```
82
-
83
- That's it!
83
+ - If you pass in directories `uspec` will scan for and run any specs inside them.
84
+ - Uspec will return the number of failures as its status code to the commandline, 0 if none.
84
85
 
85
86
  Output
86
87
  ------
87
88
 
88
- Examples of Uspec's output below!
89
+ A brief explanation of `uspec`'s output to show you what it can do!
89
90
 
90
91
  ### Success
91
92
 
@@ -157,7 +158,7 @@ When you run the test Uspec will helpfully display:
157
158
  Tips & Tricks
158
159
  -------------
159
160
 
160
- Because there's no matchers and only one method there's no reference documentation to look at, so here are some ideas to get you going!
161
+ Because there's no matchers and only one method there's no need for specialized reference documentation, but here are some ideas to get you going!
161
162
 
162
163
  ### String matching
163
164
 
@@ -190,8 +191,8 @@ What if you want to test that an error has occured? Just use Ruby!
190
191
  spec 'calling AwesomeMcCoolname.awesomeness without specifying the awesomeness level should explode' do
191
192
  begin
192
193
  AwesomeMcCoolname.awesomeness
193
- rescue => error
194
- error.class == ArgumentError || raise
194
+ rescue ArgumentError => error
195
+ error.message.include?("Needs awesomeness level!") || raise
195
196
  end
196
197
  end
197
198
  ```
@@ -200,6 +201,11 @@ If there's no error, then Uspec will see the result of the method call (whatever
200
201
  If the wrong Exception is raised, then because of reraising (by just calling `raise` without parameters),
201
202
  Ruby will dutifully pass along the error for Uspec to display.
202
203
 
204
+ Mocks, Spies, Stubs, and More!
205
+ -----------------------
206
+
207
+ Since `uspec` is a very straight forward testing utility it is easy to use any of the standard Ruby mocking frameworks with it. However, the [Impasta gem](https://github.com/acook/impasta) was made specifically for simple but comprehensive mocking, stubbing, and spying.
208
+
203
209
  Assertions & Debugging
204
210
  ----------------------
205
211
 
@@ -212,7 +218,7 @@ require 'uspec'
212
218
 
213
219
  class MyFoo
214
220
  extend Uspec::DSL
215
-
221
+
216
222
  def assert
217
223
  spec 'foo is valid' do
218
224
  false
@@ -223,19 +229,20 @@ end
223
229
  MyFoo.new.assert
224
230
  ```
225
231
 
226
- If there are any specs that fail, your application will exit with a `255``.
232
+ Assertions will be displayed as they occur, success or failure along with any informative output.
233
+ If there are any specs that fail, when your application exits its error code will equal the number of failures.
227
234
 
228
235
  ```
229
236
  $ ruby foo.rb
230
237
  -- foo is valid: false
231
238
  $ echo $?
232
- 255
239
+ 1
233
240
  ```
234
241
 
235
242
  Uspec is just Ruby
236
243
  ------------------
237
244
 
238
- If for some reason you don't want to use the `uspec` command, you can `require 'uspec'` and `extend Uspec::DSL`.
245
+ If for some reason you don't want to use the `uspec` command, you can `require 'uspec'` and `extend Uspec::DSL`.
239
246
  From there you can just run the file with ruby: `ruby my_test_spec.rb`
240
247
 
241
248
  Contributing
@@ -250,4 +257,4 @@ Contributing
250
257
  Author
251
258
  ------
252
259
 
253
- > Anthony M. Cook 2013-2016
260
+ > Anthony M. Cook 2013-2020
data/bin/uspec CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require_relative '../lib/uspec/cli'
4
- Uspec::CLI.invoke ARGV
4
+ Uspec::CLI.new(ARGV).invoke
data/lib/uspec.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require_relative 'uspec/version'
2
- require_relative 'uspec/formatter'
3
2
  require_relative 'uspec/dsl'
4
3
  require_relative 'uspec/stats'
5
4
 
@@ -9,9 +8,10 @@ module Uspec
9
8
  exit 2
10
9
  end
11
10
 
11
+ # this method used to be how we injected the spec method
12
12
  def self.extended object
13
- object.extend Uspec::DSL
13
+ #unless object.respond_to? :spec
14
+ # object.extend Uspec::DSL
15
+ #end
14
16
  end
15
17
  end
16
-
17
- at_exit { exit Uspec::Stats.exit_code }
data/lib/uspec/cli.rb CHANGED
@@ -2,29 +2,34 @@ require 'pathname'
2
2
  require_relative '../uspec'
3
3
 
4
4
  class Uspec::CLI
5
- class << self
6
- def usage
7
- warn "uspec - minimalistic ruby testing framework"
8
- warn "usage: #{File.basename $0} [<file_or_path>...]"
9
- end
5
+ def initialize args
6
+ usage unless (args & %w[-h --help -? /? -v --version]).empty?
10
7
 
11
- def run_specs paths
12
- uspec_cli = self.new paths
13
- uspec_cli.run_paths
14
- end
8
+ @paths = args
9
+ @pwd = Pathname.pwd.freeze
10
+ @stats = Uspec::Stats.new
11
+ @dsl = Uspec::DSL.new self
12
+ end
13
+ attr :stats, :dsl
15
14
 
16
- def invoke args
17
- if (args & %w[-h --help -? /?]).empty? then
18
- run_specs args
19
- else
20
- usage
21
- end
22
- end
15
+ def usage
16
+ warn "uspec v#{::Uspec::VERSION} - minimalistic ruby testing framework"
17
+ warn "usage: #{File.basename $0} [<file_or_path>...]"
18
+ exit 1
23
19
  end
24
20
 
25
- def initialize paths
26
- @paths = paths
27
- @pwd = Pathname.pwd.freeze
21
+ def run_specs
22
+ run_paths
23
+ end
24
+
25
+ def invoke
26
+ run_specs
27
+ puts @stats.summary
28
+ exit exit_code
29
+ end
30
+
31
+ def exit_code
32
+ [@stats.failure.size, 255].min
28
33
  end
29
34
 
30
35
  def paths
@@ -44,21 +49,37 @@ class Uspec::CLI
44
49
  end
45
50
 
46
51
  def run path
52
+ spec = nil
47
53
  if path.directory? then
48
54
  Pathname.glob(path.join('**', '**_spec.rb')).each do |spec|
49
55
  run spec
50
56
  end
51
57
  elsif path.exist? then
52
58
  puts "#{path.basename path.extname}:"
53
- Uspec::DSL.instance_eval(path.read, path.to_s)
59
+ dsl.instance_eval(path.read, path.to_s)
54
60
  else
55
61
  warn "path not found: #{path}"
56
62
  end
57
- rescue LoadError => result
58
- formatter = Uspec::Formatter.new
59
- print ' -- FAILED TO LOAD TEST FILE DUE TO: '
60
- Uspec::Stats.results << result
61
- puts formatter.colorize(result, result.backtrace)
63
+ rescue Exception => error
64
+
65
+ error_file, error_line, _ = error.backtrace.first.split ?:
66
+
67
+ message = <<-MSG
68
+ #{error.class} : #{error.message}
69
+
70
+ Uspec encountered an error when loading a test file.
71
+ This is probably a typo in the test file or the file it is testing.
72
+
73
+ If you think this is a bug in Uspec please report it: https://github.com/acook/uspec/issues/new
74
+
75
+ Error occured when loading test file `#{spec || path}`.
76
+ The origin of the error may be in file `#{error_file}` on line ##{error_line}.
77
+
78
+ \t#{error.backtrace[0,3].join "\n\t"}
79
+ MSG
80
+ puts
81
+ warn message
82
+ self.class.stats.failure << Uspec::Result.new(message, error, caller)
62
83
  end
63
84
 
64
85
  end
data/lib/uspec/dsl.rb CHANGED
@@ -1,20 +1,55 @@
1
+ require_relative "result"
2
+
1
3
  module Uspec
2
- module DSL
3
- module_function
4
- def spec description
5
- formatter = Uspec::Formatter.new
4
+ class DSL
5
+ def initialize cli
6
+ @__uspec_cli = cli
7
+ end
8
+
9
+ def __uspec_cli
10
+ @__uspec_cli
11
+ end
12
+
13
+ def __uspec_stats
14
+ @__uspec_cli.stats
15
+ end
6
16
 
17
+ def spec description
7
18
  print ' -- ', description
8
19
 
9
- return print(': ' + formatter.yellow('pending') + formatter.vspace) unless block_given?
20
+ if block_given? then
21
+ begin
22
+ raw_result = yield
23
+ rescue Exception => raw_result
24
+ end
25
+ end
26
+
27
+ result = Result.new description, raw_result, caller
10
28
 
11
- begin
12
- result = yield
13
- rescue => result
29
+ unless block_given? then
30
+ result.pending!
14
31
  end
15
32
 
16
- Uspec::Stats.results << result
17
- print ': ', formatter.colorize(result, caller), "\n"
33
+ if result.success?
34
+ __uspec_stats.success << result
35
+ elsif result.pending?
36
+ stats.pending << result
37
+ else
38
+ __uspec_stats.failure << result
39
+ end
40
+
41
+ print ': ', result.pretty, "\n"
42
+ rescue => error
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
+ __uspec_stats.failure << Uspec::Result.new(message, error, caller)
18
53
  end
19
54
  end
20
55
  end
@@ -0,0 +1,111 @@
1
+ require_relative "terminal"
2
+ require "toisb"
3
+
4
+ module Uspec
5
+ class Result
6
+ include Terminal
7
+
8
+ def initialize spec, raw, source
9
+ @spec = spec
10
+ @raw = raw
11
+ @source = source
12
+ @handler = ::TOISB.wrap raw
13
+ end
14
+ attr_reader :spec, :raw, :source, :handler
15
+
16
+ def pretty
17
+ if raw == true then
18
+ green raw
19
+ elsif raw == false then
20
+ red raw
21
+ elsif pending? then
22
+ yellow 'pending'
23
+ elsif Exception === raw then
24
+ [
25
+ red('Exception'), vspace,
26
+ hspace, 'Spec encountered an Exception ', newline,
27
+ hspace, 'in spec at ', source.first, vspace,
28
+ hspace, message, vspace,
29
+ white(trace)
30
+ ].join
31
+ else
32
+ [
33
+ red('Failed'), vspace,
34
+ hspace, 'Spec did not return a boolean value ', newline,
35
+ hspace, 'in spec at ', source.first, vspace,
36
+ hspace, red(subklassinfo), inspector, newline
37
+ ].join
38
+ end
39
+ end
40
+
41
+ def trace
42
+ raw.backtrace.inject(String.new) do |text, line|
43
+ text << "#{hspace}#{line}#{newline}"
44
+ end
45
+ end
46
+
47
+ def message
48
+ "#{red subklassinfo}#{raw.message}"
49
+ end
50
+
51
+ def subklassinfo
52
+ "#{handler.subklassinfo}: "
53
+ end
54
+
55
+ # Attempts to inspect an object
56
+ def inspector
57
+ if String === raw && raw.include?(?\n) then
58
+ # if object is a multiline string, display it unescaped
59
+ [
60
+ vspace,
61
+ hspace, yellow('"""'), newline,
62
+ raw, normal, newline,
63
+ hspace, yellow('"""')
64
+ ].join
65
+ else
66
+ handler.inspector!
67
+ end
68
+ rescue Exception => error
69
+ return handler.simple_inspector if error.message.include? handler.get_id
70
+
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
89
+ end
90
+
91
+ def success?
92
+ raw == true
93
+ end
94
+
95
+ def failure?
96
+ raw != true && !@pending
97
+ end
98
+
99
+ def pending?
100
+ !!@pending
101
+ end
102
+
103
+ def pending!
104
+ @pending = true
105
+ end
106
+
107
+ def inspect
108
+ "#{self.class} for `#{spec}` -> #{pretty}"
109
+ end
110
+ end
111
+ end
data/lib/uspec/stats.rb CHANGED
@@ -1,23 +1,36 @@
1
1
  module Uspec
2
2
  class Stats
3
- class << self
4
- def results?
5
- !results.empty?
6
- end
3
+ def initialize
4
+ clear_results!
5
+ end
6
+ attr :success, :failure, :pending
7
7
 
8
- def results
9
- @results ||= clear_results!
10
- end
8
+ def clear_results!
9
+ @success = Array.new
10
+ @failure = Array.new
11
+ @pending = Array.new
12
+ end
11
13
 
12
- def clear_results!
13
- @results = Array.new
14
- end
14
+ def inspect
15
+ <<-INFO
16
+ #{super} Failures: #{exit_code}
17
+ #{results.map{|r| r.inspect}.join "\n\t" }
18
+ INFO
19
+ end
20
+
21
+ def results
22
+ @success + @failure + @pending
23
+ end
15
24
 
16
- def exit_code
17
- # checking for truthy isn't good enough, it must be exactly true!
18
- failures = results.count{|result| result != true }
19
- failures > 255 ? 255 : failures
20
- end
25
+ def summary
26
+ [
27
+ "test summary: ",
28
+ Uspec::Terminal.green("#{@success.size} successful"),
29
+ ", ",
30
+ Uspec::Terminal.red("#{@failure.size} failed"),
31
+ ", ",
32
+ Uspec::Terminal.yellow("#{@pending.size} pending")
33
+ ].join
21
34
  end
22
35
  end
23
36
  end
@@ -0,0 +1,47 @@
1
+ module Uspec
2
+ module Terminal
3
+ module_function
4
+
5
+ def colors
6
+ {
7
+ red: 1,
8
+ green: 2,
9
+ yellow: 3,
10
+ white: 7
11
+ }
12
+ end
13
+
14
+ def color hue, text = nil
15
+ "#{esc "3#{colors[hue]};1"}#{text}#{normal unless text.nil?}"
16
+ end
17
+
18
+ def esc seq
19
+ "\e[#{seq}m"
20
+ end
21
+
22
+ def normal text=nil
23
+ "#{esc 0}#{text}"
24
+ end
25
+
26
+ def hspace
27
+ ' '
28
+ end
29
+
30
+ def vspace
31
+ "#{newline}#{newline}"
32
+ end
33
+
34
+ def newline
35
+ $/
36
+ end
37
+
38
+ def method_missing name, *args, &block
39
+ if colors.keys.include? name then
40
+ color name, *args
41
+ else
42
+ super
43
+ end
44
+ end
45
+
46
+ end
47
+ end
data/lib/uspec/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Uspec
2
- VERSION = '0.1.1'
2
+ VERSION = '1.0.0'
3
3
  end
data/uspec.gemspec CHANGED
@@ -1,19 +1,29 @@
1
1
  # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
2
+ lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'uspec/version'
4
+ require "uspec/version"
5
5
 
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "uspec"
8
8
  gem.version = Uspec::VERSION
9
- gem.authors = ["Anthony Cook"]
10
- gem.email = ["anthonymichaelcook@gmail.com"]
9
+ gem.authors = ["Anthony M. Cook"]
10
+ gem.email = ["github@anthonymcook.com"]
11
11
  gem.description = %q{Uspec is a shiny little spec framework for your apps! Unlike other testing frameworks there's no need for matchers, there can only be one assertion per test, and you never have to worry that your tests lack assertions.}
12
12
  gem.summary = %q{a shiny little spec framework for your apps!}
13
13
  gem.homepage = "http://github.com/acook/uspec#readme"
14
+ gem.license = "MIT"
14
15
 
15
16
  gem.files = `git ls-files`.split($/)
16
17
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
19
  gem.require_paths = ["lib"]
20
+
21
+ # due to require_relative semantics in 1.9.x and issues with BasicObject support in 2.0
22
+ # technically should still work in 2.0 but some of the test suite won't pass
23
+ gem.required_ruby_version = ">= 2.1"
24
+
25
+ gem.add_dependency "that_object_is_so_basic", "~> 0.0.5"
26
+
27
+ gem.add_development_dependency "pry"
28
+ gem.add_development_dependency "pry-doc"
19
29
  end
data/uspec/cli_spec.rb CHANGED
@@ -12,25 +12,25 @@ end
12
12
  spec 'runs a path of specs' do
13
13
  output = capture do
14
14
  path = Pathname.new(__FILE__).parent.parent.join('example_specs').to_s
15
- Uspec::CLI.run_specs Array(path)
15
+ Uspec::CLI.new(Array(path)).run_specs
16
16
  end
17
17
 
18
- output.include? 'I love passing tests'
18
+ output.include?('I love passing tests') || output
19
19
  end
20
20
 
21
21
  spec 'runs an individual spec' do
22
22
  output = capture do
23
23
  path = Pathname.new(__FILE__).parent.parent.join('example_specs', 'example_spec.rb').to_s
24
- Uspec::CLI.run_specs Array(path)
24
+ Uspec::CLI.new(Array(path)).run_specs
25
25
  end
26
26
 
27
- output.include? 'I love passing tests'
27
+ output.include?('I love passing tests') || output
28
28
  end
29
29
 
30
- spec 'exits with failure status if a test has a broken require' do
30
+ spec 'broken requires in test files count as test failures' do
31
31
  path = Pathname.new(__FILE__).parent.join('test_specs', 'broken_require_spec')
32
32
 
33
- capture do
33
+ output = capture do
34
34
  exec "bin/uspec #{path}"
35
35
  end
36
36
 
@@ -44,5 +44,5 @@ spec 'displays information about test file with broken require' do
44
44
  exec "bin/uspec #{path}"
45
45
  end
46
46
 
47
- output.include? 'cannot load such file'
48
- end
47
+ output.include?('cannot load such file') || output
48
+ end
@@ -0,0 +1,70 @@
1
+ require_relative "uspec_helper"
2
+
3
+ bo = BasicObject.new
4
+
5
+ spec "#pretty doesn't die when given a BasicObject" do
6
+ result = Uspec::Result.new "BasicObject Result", bo, []
7
+ expected = "#<BasicObject:"
8
+ actual = result.pretty
9
+ actual.include?(expected) || actual
10
+ end
11
+
12
+ # If we don't prefix the classname with "::", Ruby defines it under an anonymous class
13
+ class ::TestObject < BasicObject; end
14
+ obj = TestObject.new
15
+
16
+ spec "ensure BasicObject subclasses work" do
17
+ result = Uspec::Result.new "BasicObject Subclass Result", obj, []
18
+ expected = "#<BasicObject/TestObject:"
19
+ actual = result.pretty
20
+ actual.include?(expected) || result.pretty
21
+ end
22
+
23
+ spec "display basic info about Object" do
24
+ result = Uspec::Result.new "Object Result", Object.new, []
25
+ expected = "Object < BasicObject"
26
+ actual = result.pretty
27
+ actual.include?(expected) || result.pretty
28
+ end
29
+
30
+ spec "display basic info about Array" do
31
+ result = Uspec::Result.new "Array Result", [], []
32
+ expected = "Array < Object"
33
+ actual = result.pretty
34
+ actual.include?(expected) || result.pretty
35
+ end
36
+
37
+ spec "display basic info about Array class" do
38
+ result = Uspec::Result.new "Array Class Result", Array, []
39
+ #expected = "Class < ???" # TODO: Make classes display nicer in TOISB
40
+ expected = "#<Class:Object> < #<Class:BasicObject>: \e[0mArray"
41
+ actual = result.pretty
42
+ actual.include?(expected) || result.pretty
43
+ end
44
+
45
+ parent = [obj]
46
+
47
+ spec "ensure parent object of BasicObject subclasses get a useful error message" do
48
+ result = Uspec::Result.new "BasicObject Parent Result", parent, []
49
+ expected = "BasicObject and its subclasses"
50
+ actual = result.pretty
51
+ actual.include?(expected) || result.inspector
52
+ end
53
+
54
+ class ::InspectFail; def inspect; raise RuntimeError, "This error is intentional and part of the test."; end; end
55
+ inspect_fail = InspectFail.new
56
+
57
+ spec "display a useful error message when a user-defined inspect method fails" do
58
+ result = Uspec::Result.new "Inspect Fail Result", inspect_fail, []
59
+ expected = "raises an exception"
60
+ actual = result.pretty
61
+ actual.include?(expected) || result.inspector
62
+ end
63
+
64
+ spec "display strings more like their actual contents" do
65
+ expected = "this string:\nshould display \e[42;2mproperly"
66
+ result = Uspec::Result.new "Inspect Fail Result", expected, []
67
+ actual = result.pretty
68
+ actual.include?(expected) || result.inspector
69
+ end
70
+
data/uspec/uspec_spec.rb CHANGED
@@ -10,6 +10,16 @@ spec 'catches errors' do
10
10
  output.include? 'Exception'
11
11
  end
12
12
 
13
+ spec 'catches even non-StandardError-subclass exceptions' do
14
+ output = capture do
15
+ spec 'not implemented error' do
16
+ raise ::NotImplementedError, 'test exception'
17
+ end
18
+ end
19
+
20
+ output.include? 'Exception'
21
+ end
22
+
13
23
  spec 'complains when spec block returns non boolean' do
14
24
  output = capture do
15
25
  spec 'whatever' do
@@ -17,7 +27,7 @@ spec 'complains when spec block returns non boolean' do
17
27
  end
18
28
  end
19
29
 
20
- output.include? 'Unknown Result'
30
+ output.include? 'Failed'
21
31
  end
22
32
 
23
33
  spec 'marks test as pending when no block supplied' do
@@ -33,24 +43,34 @@ spec 'should not define DSL methods on arbitrary objects' do
33
43
  end
34
44
 
35
45
  spec 'exit code is the number of failures' do
36
- capture do
37
- 50.times do
38
- spec 'fail' do
46
+ expected = 50
47
+ output = capture do
48
+ __uspec_stats.clear_results! # because we're forking, we will have a copy of the current results
49
+
50
+ expected.times do |count|
51
+ spec "fail ##{count + 1}" do
39
52
  false
40
53
  end
41
54
  end
55
+
56
+ exit __uspec_cli.exit_code
42
57
  end
58
+ actual = $?.exitstatus
43
59
 
44
- $?.exitstatus == 50 || $?
60
+ actual == expected || puts("", output) || $?
45
61
  end
46
62
 
47
63
  spec 'if more than 255 failures, exit status is 255' do
48
64
  capture do
65
+ __uspec_stats.clear_results! # because we're forking, we will have a copy of the current results
66
+
49
67
  500.times do
50
68
  spec 'fail' do
51
69
  false
52
70
  end
53
71
  end
72
+
73
+ exit __uspec_cli.exit_code
54
74
  end
55
75
 
56
76
  $?.exitstatus == 255 || $?
metadata CHANGED
@@ -1,29 +1,73 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Anthony Cook
7
+ - Anthony M. Cook
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-15 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-02-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: that_object_is_so_basic
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry-doc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
13
55
  description: Uspec is a shiny little spec framework for your apps! Unlike other testing
14
56
  frameworks there's no need for matchers, there can only be one assertion per test,
15
57
  and you never have to worry that your tests lack assertions.
16
58
  email:
17
- - anthonymichaelcook@gmail.com
59
+ - github@anthonymcook.com
18
60
  executables:
19
61
  - uspec
20
62
  extensions: []
21
63
  extra_rdoc_files: []
22
64
  files:
65
+ - ".circleci/config.yml"
66
+ - ".editorconfig"
23
67
  - ".gitignore"
68
+ - ".rubocop.yml"
24
69
  - ".ruby-gemset"
25
70
  - ".ruby-version"
26
- - ".travis.yml"
27
71
  - Gemfile
28
72
  - LICENSE.txt
29
73
  - README.markdown
@@ -34,16 +78,19 @@ files:
34
78
  - lib/uspec.rb
35
79
  - lib/uspec/cli.rb
36
80
  - lib/uspec/dsl.rb
37
- - lib/uspec/formatter.rb
81
+ - lib/uspec/result.rb
38
82
  - lib/uspec/stats.rb
83
+ - lib/uspec/terminal.rb
39
84
  - lib/uspec/version.rb
40
85
  - uspec.gemspec
41
86
  - uspec/cli_spec.rb
87
+ - uspec/result_spec.rb
42
88
  - uspec/test_specs/broken_require_spec
43
89
  - uspec/uspec_helper.rb
44
90
  - uspec/uspec_spec.rb
45
91
  homepage: http://github.com/acook/uspec#readme
46
- licenses: []
92
+ licenses:
93
+ - MIT
47
94
  metadata: {}
48
95
  post_install_message:
49
96
  rdoc_options: []
@@ -53,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
53
100
  requirements:
54
101
  - - ">="
55
102
  - !ruby/object:Gem::Version
56
- version: '0'
103
+ version: '2.1'
57
104
  required_rubygems_version: !ruby/object:Gem::Requirement
58
105
  requirements:
59
106
  - - ">="
data/.travis.yml DELETED
@@ -1,23 +0,0 @@
1
- language: ruby
2
-
3
- rvm:
4
- - 2.2.3
5
- - 2.0.0
6
- - 1.9.3
7
- - 1.9.2
8
-
9
- - jruby-19mode
10
- - ruby-head
11
-
12
- before_install:
13
- - gem update bundler
14
- before_script:
15
- - bundle exec gem list
16
- script: bundle exec uspec
17
-
18
- matrix:
19
- allow_failures:
20
- - rvm: ruby-head
21
- - rvm: jruby-19mode
22
-
23
- sudo: false
@@ -1,90 +0,0 @@
1
- module Uspec
2
- class Formatter
3
- def colors
4
- {
5
- red: 1,
6
- green: 2,
7
- yellow: 3,
8
- white: 7
9
- }
10
- end
11
-
12
- def color hue, text = nil
13
- esc("3#{colors[hue]};1") + "#{text}#{normal}"
14
- end
15
-
16
- def esc seq
17
- "\e[#{seq}m"
18
- end
19
-
20
- def normal text=nil
21
- esc(0) + text.to_s
22
- end
23
-
24
- def colorize result, source
25
- if result == true then
26
- green result
27
- elsif result == false then
28
- red result
29
- elsif result.is_a? Exception then
30
- [
31
- red('Exception'), vspace,
32
- hspace, 'Spec encountered an Exception ', newline,
33
- hspace, 'in spec at ', source.first, vspace,
34
- hspace, message(result), vspace,
35
- white(trace result)
36
- ].join
37
- else
38
- [
39
- red('Unknown Result'), vspace,
40
- hspace, 'Spec did not return a boolean value ', newline,
41
- hspace, 'in spec at ', source.first, vspace,
42
- hspace, red(classinfo(result)), result.inspect, newline
43
- ].join
44
- end
45
- end
46
-
47
- def trace error
48
- error.backtrace.inject(String.new) do |text, line|
49
- text << hspace + line + newline
50
- end
51
- end
52
-
53
- def message error
54
- red(classinfo error) + error.message
55
- end
56
-
57
- def classinfo object
58
- "#{classify object} < #{superclass object}: "
59
- end
60
-
61
- def classify object
62
- object.is_a?(Module) ? object : object.class
63
- end
64
-
65
- def superclass object
66
- classify(object).superclass
67
- end
68
-
69
- def hspace
70
- ' '
71
- end
72
-
73
- def vspace
74
- newline + newline
75
- end
76
-
77
- def newline
78
- $/
79
- end
80
-
81
- def method_missing name, *args, &block
82
- if colors.keys.include? name then
83
- color name, *args
84
- else
85
- super
86
- end
87
- end
88
-
89
- end
90
- end