loupe 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/loupe/test.rb ADDED
@@ -0,0 +1,270 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Loupe's expectations are heavily inspired by or adapted from Minitest and rspec-expectations implementations. The
4
+ # originals licenses can be found below.
5
+ #
6
+ # Minitest https://github.com/seattlerb/minitest
7
+ #
8
+ # (The MIT License)
9
+ #
10
+ # Copyright © Ryan Davis, seattle.rb
11
+ #
12
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13
+ # documentation files (the 'Software'), to deal in the Software without restriction, including without limitation
14
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15
+ # to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of
18
+ # the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
21
+ # THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
+ # IN THE SOFTWARE.
25
+
26
+ # Rspec-expectations
27
+ #
28
+ # https://github.com/rspec/rspec-expectations
29
+ #
30
+ # The MIT License (MIT)
31
+ #
32
+ # Copyright © 2012 David Chelimsky, Myron Marston Copyright © 2006 David Chelimsky, The RSpec Development Team
33
+ # Copyright © 2005 Steven Baker
34
+ #
35
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
36
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation
37
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
38
+ # to permit persons to whom the Software is furnished to do so, subject to the following conditions:
39
+ #
40
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of
41
+ # the Software.
42
+ #
43
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
44
+ # THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
46
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47
+ # DEALINGS IN THE SOFTWARE.
48
+
49
+ module Loupe
50
+ # Test
51
+ #
52
+ # The parent class for tests. Tests should
53
+ # inherit from this class in order to be run.
54
+ class Test
55
+ # @return [Loupe::Reporter]
56
+ attr_reader :reporter
57
+
58
+ # @return [Integer]
59
+ attr_reader :line_number
60
+
61
+ # @return [String]
62
+ attr_reader :file
63
+
64
+ # @return [Loupe::Color]
65
+ attr_reader :color
66
+
67
+ # @return [String]
68
+ attr_reader :name
69
+
70
+ # @return [Hash<Class, Array<Integer>>]
71
+ def self.classes
72
+ @classes ||= {}
73
+ end
74
+
75
+ # @param number [Integer]
76
+ # @return [void]
77
+ def self.add_line_number(number)
78
+ classes[@current_class] << number
79
+ end
80
+
81
+ # @param test_class [Class]
82
+ # @return [void]
83
+ def self.inherited(test_class)
84
+ @current_class = test_class
85
+ classes[test_class] = []
86
+ super
87
+ end
88
+
89
+ # @return [Array<Symbol>]
90
+ def self.test_list
91
+ instance_methods(false).grep(/^test.*/)
92
+ end
93
+
94
+ # Run a single test with designated by `method_name`
95
+ #
96
+ # @param method_name [Symbol]
97
+ # @param options [Hash<Symbol, BasicObject>]
98
+ # @return [Loupe::Reporter]
99
+ def self.run(method_name, options = {})
100
+ reporter = options[:interactive] ? PagedReporter.new(options) : PlainReporter.new(options)
101
+ new(reporter, method_name, options).run
102
+ reporter
103
+ rescue Expectation::ExpectationFailed
104
+ reporter
105
+ end
106
+
107
+ # @param reporter [Loupe::Reporter]
108
+ # @param method_name [Symbol]
109
+ # @param options [Hash<Symbol, BasicObject>]
110
+ # @return [Loupe::Test]
111
+ def initialize(reporter, method_name, options = {})
112
+ @reporter = reporter
113
+ @color = Color.new(options[:color])
114
+ @name = method_name
115
+ @method = method(method_name)
116
+ @file, @line_number = @method.source_location
117
+ end
118
+
119
+ # Run the instantiated test, which corresponds to a single
120
+ # method.
121
+ # @return [void]
122
+ def run
123
+ @reporter.increment_test_count
124
+ before
125
+ @method.call
126
+ after
127
+ @reporter.increment_success_count
128
+ end
129
+
130
+ # @return [void]
131
+ def before; end
132
+
133
+ # @return [void]
134
+ def after; end
135
+
136
+ protected
137
+
138
+ # expect(target)
139
+ #
140
+ # Initial construct for any expectation. Instantiates an Expectation object
141
+ # on which verifications can be performed. Any expectation can be chained to reuse
142
+ # the object if the `target` is the same.
143
+ #
144
+ # Example:
145
+ # expect(collection)
146
+ # .to_not_be_empty
147
+ # .to_include(object)
148
+ # .be_an_instance_of(Array)
149
+ #
150
+ # @return [Loupe::Expectation]
151
+ def expect(target)
152
+ Expectation.new(target, self)
153
+ end
154
+
155
+ # expect_output_to_match(stdout, stderr) { block }
156
+ #
157
+ # Expects the output generated by the execution of `block` to match the matchers used
158
+ # for `stdout` and `stderr`. If the `block` only prints to one of the two, simply pass
159
+ # `nil` for the one that is not of interest.
160
+ #
161
+ # Example:
162
+ # expect_output_to_match("foo") do
163
+ # puts "foo"
164
+ # end
165
+ #
166
+ # expect_output_to_match(nil, /error: .*/) do
167
+ # $stderr.puts "error: operation failed"
168
+ # end
169
+ #
170
+ # @return [void]
171
+ def expect_output_to_match(stdout = nil, stderr = nil, &block)
172
+ raise ArgumentError, "expect_output_to_match requires a block to capture output." unless block
173
+
174
+ out, err = capture_io(&block)
175
+
176
+ match_or_equal(stdout, out) if stdout
177
+ match_or_equal(stderr, err) if stderr
178
+ end
179
+
180
+ # expect_output_to_not_match(stdout, stderr) { block }
181
+ #
182
+ # Expects the output generated by the execution of `block` to not match the matchers used
183
+ # for `stdout` and `stderr`. If the `block` only prints to one of the two, simply pass
184
+ # `nil` for the one that is not of interest.
185
+ #
186
+ # Example:
187
+ # expect_output_to_not_match("foo") do
188
+ # puts "bar"
189
+ # end
190
+ #
191
+ # expect_output_to_not_match(nil, /error: network failed.*/) do
192
+ # $stderr.puts "error: record not unique"
193
+ # end
194
+ #
195
+ # @return [void]
196
+ def expect_output_to_not_match(stdout = nil, stderr = nil, &block)
197
+ raise ArgumentError, "expect_output_to_not_match requires a block to capture output." unless block
198
+
199
+ out, err = capture_io(&block)
200
+
201
+ refute_match_or_equal(stdout, out) if stdout
202
+ refute_match_or_equal(stderr, err) if stderr
203
+ end
204
+
205
+ # expect_output_to_be_empty { block }
206
+ #
207
+ # Expects the output generated by `block` to be empty for both `$stdout` and `$stderr`.
208
+ # That is, expects the `block` to not print anything to either `$stdout` or `$stderr`.
209
+ # For matching to the output of the `block`, see {#expect_output_to_match}.
210
+ #
211
+ # Example:
212
+ # expect_output_to_be_empty do
213
+ # puts "bar" if false
214
+ # end
215
+ #
216
+ # @return [void]
217
+ def expect_output_to_be_empty(&block)
218
+ expect_output_to_match("", "", &block)
219
+ end
220
+
221
+ # expect_output_to_not_be_empty { block }
222
+ #
223
+ # Expects the output generated by `block` to not be empty for both `$stdout` and `$stderr`.
224
+ # That is, expects the `block` to print something to either `$stdout` or `$stderr`.
225
+ # For matching to the output of the `block`, see {#expect_output_to_not_match}.
226
+ #
227
+ # Example:
228
+ # expect_output_to_not_be_empty do
229
+ # puts "foo"
230
+ # end
231
+ #
232
+ # @return [void]
233
+ def expect_output_to_not_be_empty(&block)
234
+ expect_output_to_not_match("", "", &block)
235
+ end
236
+
237
+ private
238
+
239
+ # @param matcher [Regexp, String]
240
+ # @param output [String]
241
+ # @return [void]
242
+ def match_or_equal(matcher, output)
243
+ matcher.is_a?(Regexp) ? expect(matcher).to_match(output) : expect(matcher).to_be_equal_to(output)
244
+ end
245
+
246
+ # @param matcher [Regexp, String]
247
+ # @param output [String]
248
+ # @return [void]
249
+ def refute_match_or_equal(matcher, output)
250
+ matcher.is_a?(Regexp) ? expect(matcher).to_not_match(output) : expect(matcher).to_not_be_equal_to(output)
251
+ end
252
+
253
+ # @return [Array<String>]
254
+ def capture_io
255
+ new_stdout = StringIO.new
256
+ new_stderr = StringIO.new
257
+ stdout = $stdout
258
+ stderr = $stderr
259
+ $stdout = new_stdout
260
+ $stderr = new_stderr
261
+
262
+ yield
263
+
264
+ [new_stdout.string, new_stderr.string]
265
+ ensure
266
+ $stdout = stdout
267
+ $stderr = stderr
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Loupe
4
+ # @return [String]
5
+ VERSION = "0.1.5"
6
+ end
data/lib/loupe.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "loupe/version"
4
+ require "loupe/color"
5
+ require "loupe/expectation"
6
+ require "loupe/test"
7
+ require "loupe/failure"
8
+ require "loupe/reporter"
9
+ require "loupe/executor"
10
+ require "loupe/cli"
11
+
12
+ module Loupe # :nodoc:
13
+ autoload :PlainReporter, "loupe/plain_reporter"
14
+ autoload :PagedReporter, "loupe/paged_reporter"
15
+ autoload :QueueServer, "loupe/queue_server"
16
+ autoload :ProcessExecutor, "loupe/process_executor"
17
+ autoload :RactorExecutor, "loupe/ractor_executor"
18
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: loupe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - Vinicius Stock
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-09-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: drb
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: io-console
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.5'
41
+ description: Loupe is a Ruby test framework that can run tests in parallel in Ractor
42
+ or forked process mode
43
+ email:
44
+ - stock@hey.com
45
+ executables:
46
+ - loupe
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - exe/loupe
54
+ - lib/loupe.rb
55
+ - lib/loupe/cli.rb
56
+ - lib/loupe/color.rb
57
+ - lib/loupe/executor.rb
58
+ - lib/loupe/expectation.rb
59
+ - lib/loupe/failure.rb
60
+ - lib/loupe/paged_reporter.rb
61
+ - lib/loupe/plain_reporter.rb
62
+ - lib/loupe/process_executor.rb
63
+ - lib/loupe/queue_server.rb
64
+ - lib/loupe/ractor_executor.rb
65
+ - lib/loupe/rake_task.rb
66
+ - lib/loupe/reporter.rb
67
+ - lib/loupe/test.rb
68
+ - lib/loupe/version.rb
69
+ homepage: https://github.com/vinistock/loupe
70
+ licenses:
71
+ - MIT
72
+ metadata:
73
+ homepage_uri: https://github.com/vinistock/loupe
74
+ source_code_uri: https://github.com/vinistock/loupe
75
+ changelog_uri: https://github.com/vinistock/loupe/blob/master/CHANGELOG.md
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 2.7.0
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 3.2.27
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Loupe is a Rubyy test framework with built in parallelism
95
+ test_files: []