minitest-tagz 1.6.0 → 1.7.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 +5 -5
- data/.travis.yml +4 -1
- data/lib/minitest/tagz.rb +19 -204
- data/lib/minitest/tagz/minitest_patch.rb +56 -0
- data/lib/minitest/tagz/minitest_test_patch.rb +13 -0
- data/lib/minitest/tagz/patcher.rb +73 -0
- data/lib/minitest/tagz/tagger.rb +39 -0
- data/lib/minitest/tagz/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1a7c2e69a5484b7fe73c7ef7f2f87c22453647b1
|
4
|
+
data.tar.gz: c5fd2e1086daca6e88a567764dd82f6bb21b061e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 481ae12df1710000e24b1f5c09b7e50f34192f40c4f9bcf7fdffc4dc9241539c8b2afe0cb87a5d04fae978550dcd754d955a83e62e8002ef4067a7d4bb861da4
|
7
|
+
data.tar.gz: 4f0df35fc26d5b5a08b336f21541fe765fcf8eba5981092bdaebf0bccc87835ff71252318bed73e270713962f251099db5c17e578ceb5321daa7da421b0a2080
|
data/.travis.yml
CHANGED
data/lib/minitest/tagz.rb
CHANGED
@@ -1,208 +1,12 @@
|
|
1
1
|
require 'minitest'
|
2
|
+
require 'minitest/tagz/minitest_patch'
|
3
|
+
require 'minitest/tagz/minitest_test_patch'
|
4
|
+
require 'minitest/tagz/tagger'
|
5
|
+
require 'minitest/tagz/patcher'
|
2
6
|
require 'minitest/tagz/version'
|
3
7
|
|
4
8
|
module Minitest
|
5
9
|
module Tagz
|
6
|
-
# The strategy for patching the Minitest run time
|
7
|
-
module MinitestRunnerStrategy
|
8
|
-
class << self
|
9
|
-
def serialize(owner, test_name)
|
10
|
-
"#{owner} >> #{test_name}"
|
11
|
-
end
|
12
|
-
|
13
|
-
module RunnableMethodsFilter
|
14
|
-
def runnable_methods
|
15
|
-
all_runnables = super
|
16
|
-
|
17
|
-
if Tagz.positive_tags.any?
|
18
|
-
all_runnables.select! do |r|
|
19
|
-
serialized = MinitestRunnerStrategy.serialize(self, r)
|
20
|
-
tags_on_runnable = MinitestRunnerStrategy.tag_map[serialized]
|
21
|
-
next false unless tags_on_runnable
|
22
|
-
(Tagz.positive_tags - tags_on_runnable).empty?
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
if Tagz.negative_tags.any?
|
27
|
-
all_runnables.reject! do |r|
|
28
|
-
serialized = MinitestRunnerStrategy.serialize(self, r)
|
29
|
-
tags_on_runnable = MinitestRunnerStrategy.tag_map[serialized]
|
30
|
-
next false unless tags_on_runnable
|
31
|
-
(Tagz.negative_tags & tags_on_runnable).any?
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
all_runnables
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
module RunPatch
|
40
|
-
def run(*args)
|
41
|
-
# Check for no match and don't filter runnable methods if there would be no match
|
42
|
-
if Tagz.run_all_if_no_match?
|
43
|
-
run_map = Runnable.runnables.reduce({}) {|memo, r| memo[r] = r.runnable_methods; memo}
|
44
|
-
should_skip_filter = run_map.all? do |ctxt, methods|
|
45
|
-
methods.all? do |m|
|
46
|
-
serialized = MinitestRunnerStrategy.serialize(ctxt, m)
|
47
|
-
tags = MinitestRunnerStrategy.tag_map[serialized]
|
48
|
-
tags.nil? ||
|
49
|
-
tags.empty? ||
|
50
|
-
((tags & Tagz.positive_tags).empty? &&
|
51
|
-
(tags & Tagz.negative_tags).empty?)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
if should_skip_filter
|
55
|
-
puts "Couldn't find any runnables with the given tag, running all runnables" if Tagz.log_if_no_match?
|
56
|
-
return super
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
::Minitest::Test.singleton_class.class_eval { prepend(RunnableMethodsFilter) }
|
61
|
-
super
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def patch
|
66
|
-
::Minitest.singleton_class.class_eval { prepend(RunPatch) }
|
67
|
-
end
|
68
|
-
|
69
|
-
def tag_map
|
70
|
-
@tag_map ||= {}
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Patch the Minitest runtime to hook into Tagz
|
76
|
-
MinitestRunnerStrategy.patch
|
77
|
-
|
78
|
-
# Alias
|
79
|
-
RunnerStrategy = MinitestRunnerStrategy
|
80
|
-
|
81
|
-
# Was more useful when I was trying to add
|
82
|
-
# shoulda-context support
|
83
|
-
module BaseMixin
|
84
|
-
def tag(*tags)
|
85
|
-
Tagz.declare_tag_assignment(self, tags)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# Was more useful when I was trying to add
|
90
|
-
# shoulda-context support
|
91
|
-
class TaggerFactory
|
92
|
-
def self.create_tagger(owner, pending_tags)
|
93
|
-
patchers = [MinitestPatcher]
|
94
|
-
Tagger.new(patchers, owner, pending_tags)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Represents the individual instance of a `tag` call
|
99
|
-
# It is essentially a state machine that works with the
|
100
|
-
# patcher to patch and unpatch Minitest properly
|
101
|
-
class Tagger
|
102
|
-
def tags_declared
|
103
|
-
patch_test_definitions
|
104
|
-
@awaiting_initial_test_definition = true
|
105
|
-
end
|
106
|
-
|
107
|
-
attr_reader :patchers, :owner, :pending_tags
|
108
|
-
|
109
|
-
def initialize(patchers, owner, pending_tags)
|
110
|
-
@patchers = patchers
|
111
|
-
@owner = owner
|
112
|
-
@pending_tags = pending_tags.map(&:to_s)
|
113
|
-
super()
|
114
|
-
end
|
115
|
-
|
116
|
-
def patch_test_definitions
|
117
|
-
@patchers.each {|p| p.patch(self)}
|
118
|
-
end
|
119
|
-
|
120
|
-
def unpatch_test_definitions
|
121
|
-
@patchers.each(&:unpatch)
|
122
|
-
end
|
123
|
-
|
124
|
-
def handle_initial_test_definition
|
125
|
-
is_initial = @awaiting_initial_test_definition
|
126
|
-
@awaiting_initial_test_definition = false if is_initial
|
127
|
-
res = yield
|
128
|
-
unpatch_test_definitions if is_initial
|
129
|
-
res
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# Patches Minitest to track tags
|
134
|
-
module MinitestPatcher
|
135
|
-
::Minitest::Test.extend(Tagz::BaseMixin)
|
136
|
-
|
137
|
-
class << self
|
138
|
-
def patch(state_machine)
|
139
|
-
patch_minitest_test(state_machine)
|
140
|
-
patch_minitest_spec(state_machine) if spec_included?
|
141
|
-
end
|
142
|
-
|
143
|
-
def unpatch
|
144
|
-
unpatch_minitest_test
|
145
|
-
unpatch_minitest_spec if spec_included?
|
146
|
-
end
|
147
|
-
|
148
|
-
private
|
149
|
-
|
150
|
-
def spec_included?
|
151
|
-
!defined?(::Minitest::Spec).nil?
|
152
|
-
end
|
153
|
-
|
154
|
-
def patch_minitest_test(state_machine)
|
155
|
-
Minitest::Test.class_eval do
|
156
|
-
self.singleton_class.class_eval do
|
157
|
-
alias :old_method_added :method_added
|
158
|
-
|
159
|
-
define_method(:method_added) do |name|
|
160
|
-
if name[/^test_/]
|
161
|
-
state_machine.handle_initial_test_definition do
|
162
|
-
Tagz::RunnerStrategy.tag_map ||= {}
|
163
|
-
Tagz::RunnerStrategy.tag_map[Tagz::RunnerStrategy.serialize(self, name)] ||= []
|
164
|
-
Tagz::RunnerStrategy.tag_map[Tagz::RunnerStrategy.serialize(self, name)] += state_machine.pending_tags
|
165
|
-
old_method_added(name)
|
166
|
-
end
|
167
|
-
else
|
168
|
-
old_method_added(name)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
def unpatch_minitest_test
|
176
|
-
Minitest::Test.class_eval do
|
177
|
-
self.singleton_class.class_eval do
|
178
|
-
undef_method :method_added
|
179
|
-
alias :method_added :old_method_added
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def patch_minitest_spec(state_machine)
|
185
|
-
Kernel.module_eval do
|
186
|
-
alias :old_describe :describe
|
187
|
-
|
188
|
-
define_method(:describe) do |*args, &block|
|
189
|
-
state_machine.handle_initial_test_definition do
|
190
|
-
old_describe(*args, &block)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
def unpatch_minitest_spec
|
197
|
-
Kernel.module_eval do
|
198
|
-
undef_method :describe
|
199
|
-
alias :describe :old_describe
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
# Main extensions to Minitest
|
206
10
|
class << self
|
207
11
|
attr_accessor :run_all_if_no_match, :log_if_no_match
|
208
12
|
|
@@ -211,6 +15,7 @@ module Minitest
|
|
211
15
|
|
212
16
|
# Create a master TagSet that you wish to test. You only
|
213
17
|
# want to run tests with tags in this set
|
18
|
+
#
|
214
19
|
# @param [Enumerable<Symbol>] tags - a list of tags you want to test
|
215
20
|
# @param [Boolean] run_all_if_no_match - will run all tests if no tests are found with the tag
|
216
21
|
# @param [Boolean] log_if_no_match - puts if no match specs found
|
@@ -220,23 +25,33 @@ module Minitest
|
|
220
25
|
@log_if_no_match = log_if_no_match
|
221
26
|
end
|
222
27
|
|
28
|
+
# @private
|
223
29
|
def chosen_tags
|
224
30
|
@chosen_tags ||= []
|
225
31
|
end
|
226
32
|
|
33
|
+
# @private
|
227
34
|
def positive_tags
|
228
35
|
chosen_tags.reject {|t| t.is_a?(String) && t[/^-/]}
|
229
36
|
end
|
230
37
|
|
38
|
+
# @private
|
231
39
|
def negative_tags
|
232
40
|
chosen_tags.select {|t| t.is_a?(String) && t[/^-/]}.map {|t| t[1..-1]}
|
233
41
|
end
|
234
42
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
43
|
+
# @private
|
44
|
+
def serialize(owner, test_name)
|
45
|
+
"#{owner} >> #{test_name}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# @private
|
49
|
+
def tag_map
|
50
|
+
@tag_map ||= {}
|
239
51
|
end
|
240
52
|
end
|
241
53
|
end
|
242
54
|
end
|
55
|
+
|
56
|
+
Minitest.singleton_class.prepend(Minitest::Tagz::MinitestPatch)
|
57
|
+
Minitest::Test.extend(Minitest::Tagz::MinitestTestPatch)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Minitest
|
2
|
+
module Tagz
|
3
|
+
module MinitestPatch
|
4
|
+
def run(*args)
|
5
|
+
# Check for no match and don't filter runnable methods if there would be no match
|
6
|
+
if Tagz.run_all_if_no_match?
|
7
|
+
run_map = Minitest::Runnable.runnables.reduce({}) {|memo, r| memo[r] = r.runnable_methods; memo}
|
8
|
+
should_skip_filter = run_map.all? do |ctxt, methods|
|
9
|
+
methods.all? do |m|
|
10
|
+
serialized = Tagz.serialize(ctxt, m)
|
11
|
+
tags = Tagz.tag_map[serialized]
|
12
|
+
tags.nil? ||
|
13
|
+
tags.empty? ||
|
14
|
+
((tags & Tagz.positive_tags).empty? &&
|
15
|
+
(tags & Tagz.negative_tags).empty?)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
if should_skip_filter
|
19
|
+
puts "Couldn't find any runnables with the given tag, running all runnables" if Tagz.log_if_no_match?
|
20
|
+
return super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Minitest::Test.singleton_class.class_eval { prepend(MinitestPatch::RunnableMethodsPatch) }
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
# Patch which is used ot filter Minitest's `runnable_methods`
|
29
|
+
module RunnableMethodsPatch
|
30
|
+
def runnable_methods
|
31
|
+
all_runnables = super
|
32
|
+
|
33
|
+
if Tagz.positive_tags.any?
|
34
|
+
all_runnables.select! do |r|
|
35
|
+
serialized = Tagz.serialize(self, r)
|
36
|
+
tags_on_runnable = Tagz.tag_map[serialized]
|
37
|
+
next false unless tags_on_runnable
|
38
|
+
(Tagz.positive_tags - tags_on_runnable).empty?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if Tagz.negative_tags.any?
|
43
|
+
all_runnables.reject! do |r|
|
44
|
+
serialized = Tagz.serialize(self, r)
|
45
|
+
tags_on_runnable = Tagz.tag_map[serialized]
|
46
|
+
next false unless tags_on_runnable
|
47
|
+
(Tagz.negative_tags & tags_on_runnable).any?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
all_runnables
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Adds the `tag` method to Minitest::Test. When we encounter a `tag` then we
|
2
|
+
# want to create a state machine that will be used to patch/unpatch Minitest
|
3
|
+
module Minitest
|
4
|
+
module Tagz
|
5
|
+
module MinitestTestPatch
|
6
|
+
def tag(*tags)
|
7
|
+
state_machine = Tagger.new([Minitest::Tagz::Patcher], self, tags)
|
8
|
+
state_machine.tags_declared!
|
9
|
+
state_machine
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Responsible for patching/unpatching Minitest. When `tag` is called we patch Minitest and
|
2
|
+
module Minitest
|
3
|
+
module Tagz
|
4
|
+
module Patcher
|
5
|
+
class << self
|
6
|
+
def patch(state_machine)
|
7
|
+
patch_minitest_test(state_machine)
|
8
|
+
patch_minitest_spec(state_machine) if spec_included?
|
9
|
+
end
|
10
|
+
|
11
|
+
def unpatch
|
12
|
+
unpatch_minitest_test
|
13
|
+
unpatch_minitest_spec if spec_included?
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def spec_included?
|
19
|
+
!defined?(::Minitest::Spec).nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def patch_minitest_test(state_machine)
|
23
|
+
Minitest::Test.class_eval do
|
24
|
+
self.singleton_class.class_eval do
|
25
|
+
alias :old_method_added :method_added
|
26
|
+
|
27
|
+
define_method(:method_added) do |name|
|
28
|
+
if name[/^test_/]
|
29
|
+
state_machine.handle_initial_test_definition! do
|
30
|
+
Tagz.tag_map ||= {}
|
31
|
+
Tagz.tag_map[Tagz.serialize(self, name)] ||= []
|
32
|
+
Tagz.tag_map[Tagz.serialize(self, name)] += state_machine.pending_tags
|
33
|
+
old_method_added(name)
|
34
|
+
end
|
35
|
+
else
|
36
|
+
old_method_added(name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def unpatch_minitest_test
|
44
|
+
Minitest::Test.class_eval do
|
45
|
+
self.singleton_class.class_eval do
|
46
|
+
undef_method :method_added
|
47
|
+
alias :method_added :old_method_added
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def patch_minitest_spec(state_machine)
|
53
|
+
Kernel.module_eval do
|
54
|
+
alias :old_describe :describe
|
55
|
+
|
56
|
+
define_method(:describe) do |*args, &block|
|
57
|
+
state_machine.handle_initial_test_definition! do
|
58
|
+
old_describe(*args, &block)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def unpatch_minitest_spec
|
65
|
+
Kernel.module_eval do
|
66
|
+
undef_method :describe
|
67
|
+
alias :describe :old_describe
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Minitest
|
2
|
+
module Tagz
|
3
|
+
# Represents the individual instance of a `tag` call
|
4
|
+
# It is essentially a state machine that works with the
|
5
|
+
# patcher to patch and unpatch Minitest properly
|
6
|
+
class Tagger
|
7
|
+
attr_reader :patchers, :owner, :pending_tags
|
8
|
+
|
9
|
+
def initialize(patchers, owner, pending_tags)
|
10
|
+
@patchers = patchers
|
11
|
+
@owner = owner
|
12
|
+
@pending_tags = pending_tags.map(&:to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
def tags_declared!
|
16
|
+
patch_test_definitions
|
17
|
+
@awaiting_initial_test_definition = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def handle_initial_test_definition!
|
21
|
+
is_initial = @awaiting_initial_test_definition
|
22
|
+
@awaiting_initial_test_definition = false if is_initial
|
23
|
+
res = yield
|
24
|
+
unpatch_test_definitions if is_initial
|
25
|
+
res
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def patch_test_definitions
|
31
|
+
@patchers.each {|p| p.patch(self)}
|
32
|
+
end
|
33
|
+
|
34
|
+
def unpatch_test_definitions
|
35
|
+
@patchers.each(&:unpatch)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minitest-tagz
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Bodah
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -112,6 +112,10 @@ files:
|
|
112
112
|
- Rakefile
|
113
113
|
- lib/minitest/tagz.rb
|
114
114
|
- lib/minitest/tagz/focus.rb
|
115
|
+
- lib/minitest/tagz/minitest_patch.rb
|
116
|
+
- lib/minitest/tagz/minitest_test_patch.rb
|
117
|
+
- lib/minitest/tagz/patcher.rb
|
118
|
+
- lib/minitest/tagz/tagger.rb
|
115
119
|
- lib/minitest/tagz/version.rb
|
116
120
|
- minitest-tagz.gemspec
|
117
121
|
homepage: https://github.com/jbodah/minitest-tagz
|
@@ -134,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
138
|
version: '0'
|
135
139
|
requirements: []
|
136
140
|
rubyforge_project:
|
137
|
-
rubygems_version: 2.
|
141
|
+
rubygems_version: 2.5.2.3
|
138
142
|
signing_key:
|
139
143
|
specification_version: 4
|
140
144
|
summary: yet another tags implementation for Minitest
|