minitag 0.2.0 → 0.3.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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +9 -4
- data/lib/minitag.rb +8 -15
- data/lib/minitag/context.rb +103 -0
- data/lib/minitag/tag_extension.rb +15 -13
- data/lib/minitag/tag_registry.rb +39 -0
- data/lib/minitag/version.rb +1 -1
- data/lib/minitest/minitag_plugin.rb +2 -2
- metadata +4 -5
- data/lib/minitag/tag.rb +0 -44
- data/lib/minitag/tag_mapper.rb +0 -37
- data/lib/minitag/tag_matcher.rb +0 -43
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8004bb1833fb4829727720b31f79334793e459d8bcb956914bbd6cddb93c85a2
|
|
4
|
+
data.tar.gz: 40271847cdace3dcf99f483d59530b45496fc1a02fc5208e56c6a1f5817c03de
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 89b73ed8cdb55e205b3692ebd67c301785ae6e8fb7fcc856c32d0cc863024eb55bbaaa899a439cf1bdb2bef64627f1de7fbc171650dd95b6794ab64f3f6da121
|
|
7
|
+
data.tar.gz: 21be5c61d05d203558b664dbe92a08c01ac809b84580ddbf4ac6a648067e175cebb1c9b7912e91673f14f315f789ae11ee09bf653860b4ed67d53262fecd8db0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -33,6 +33,7 @@ Require `minitag` in our `test_helper.rb`:
|
|
|
33
33
|
|
|
34
34
|
We can tag specific tests with one or more tags.
|
|
35
35
|
|
|
36
|
+
It is important to point out that tags associated with a test have no concept of being inclusive or exclusive. This distinction is only valid for [tag filters](#running-tests-with-tag-filters).
|
|
36
37
|
|
|
37
38
|
```rb
|
|
38
39
|
class MyTest < Minitest::Test
|
|
@@ -43,15 +44,19 @@ class MyTest < Minitest::Test
|
|
|
43
44
|
end
|
|
44
45
|
```
|
|
45
46
|
|
|
46
|
-
### Running tests
|
|
47
|
+
### Running tests with tag filters
|
|
47
48
|
|
|
48
49
|
We can now run our test suite with specific tags:
|
|
49
50
|
|
|
50
|
-
`$ bundle exec rake test --tag '
|
|
51
|
+
`$ bundle exec rake test --tag 'unit'`
|
|
51
52
|
|
|
52
|
-
|
|
53
|
+
or even multiple tags:
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
`$ bundle exec rake test --tag 'unit' --tag 'services' --tag '~model'`
|
|
56
|
+
|
|
57
|
+
### More on tag filters
|
|
58
|
+
|
|
59
|
+
Tag filters can be:
|
|
55
60
|
1. `inclusive`
|
|
56
61
|
2. `exclusive` with the `~` prefix:
|
|
57
62
|
|
data/lib/minitag.rb
CHANGED
|
@@ -2,26 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
require 'minitest'
|
|
4
4
|
require 'minitag/version'
|
|
5
|
-
require 'minitag/
|
|
6
|
-
require 'minitag/tag_mapper'
|
|
7
|
-
require 'minitag/tag_matcher'
|
|
5
|
+
require 'minitag/context'
|
|
8
6
|
require 'minitag/tag_extension'
|
|
9
7
|
|
|
10
8
|
# Namespace for classes or modules providing tagging functionality
|
|
11
9
|
# to Minitest::Test
|
|
12
10
|
module Minitag
|
|
13
11
|
class << self
|
|
14
|
-
#
|
|
15
|
-
def
|
|
16
|
-
@
|
|
12
|
+
# Execution context of the test suite.
|
|
13
|
+
def context
|
|
14
|
+
@context ||= Context.new
|
|
17
15
|
end
|
|
18
16
|
|
|
19
|
-
# Add tag specified by the `--tag` or `-t` option.
|
|
20
|
-
def
|
|
21
|
-
|
|
17
|
+
# Add filtering tag to context specified by the `--tag` or `-t` option.
|
|
18
|
+
def add_filter(tag)
|
|
19
|
+
context.add_filter(tag)
|
|
22
20
|
end
|
|
23
21
|
|
|
24
|
-
# Tags from the last `tag` method
|
|
22
|
+
# Tags from the last `tag` method awaiting to be associated with a test.
|
|
25
23
|
def pending_tags
|
|
26
24
|
@pending_tags || []
|
|
27
25
|
end
|
|
@@ -30,10 +28,5 @@ module Minitag
|
|
|
30
28
|
def pending_tags=(tags)
|
|
31
29
|
@pending_tags = Array(tags)
|
|
32
30
|
end
|
|
33
|
-
|
|
34
|
-
# The mapping of tags and tests.
|
|
35
|
-
def tag_mapping
|
|
36
|
-
@tag_mapping ||= Minitag::TagMapper.new
|
|
37
|
-
end
|
|
38
31
|
end
|
|
39
32
|
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'set'
|
|
4
|
+
require_relative './tag_registry'
|
|
5
|
+
|
|
6
|
+
module Minitag
|
|
7
|
+
# Represents the execution context of the test suite.
|
|
8
|
+
class Context
|
|
9
|
+
def initialize
|
|
10
|
+
@inclusive_filters = Set.new
|
|
11
|
+
@exclusive_filters = Set.new
|
|
12
|
+
@tag_registry = Minitag::TagRegistry.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Associates tags with a name taking into account its namespace.
|
|
16
|
+
#
|
|
17
|
+
# @param [String] namespace the namespace which a name belongs.
|
|
18
|
+
# @param [String] name the test name.
|
|
19
|
+
# @param [Array] tags the collection of tags.
|
|
20
|
+
#
|
|
21
|
+
# @return [void]
|
|
22
|
+
def add_tags(namespace:, name:, tags:)
|
|
23
|
+
@tag_registry.add(namespace: namespace, name: name, tags: tags)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Adds a filter tag.
|
|
27
|
+
# Tags with a ~ prefix are exclusive filters and inclusive filters otherwise.
|
|
28
|
+
#
|
|
29
|
+
# param [String] name the name of the filter tag.
|
|
30
|
+
#
|
|
31
|
+
# Invariants:
|
|
32
|
+
# - A filter will always be a String without the ~ prefix.
|
|
33
|
+
#
|
|
34
|
+
# @return [void]
|
|
35
|
+
def add_filter(tag)
|
|
36
|
+
if tag.start_with?('~')
|
|
37
|
+
@exclusive_filters << tag[1..-1]
|
|
38
|
+
else
|
|
39
|
+
@inclusive_filters << tag
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Indicates when a context has no filters.
|
|
44
|
+
#
|
|
45
|
+
# @return [boolean] whether a context has no filters.
|
|
46
|
+
def no_filters?
|
|
47
|
+
@inclusive_filters.empty? && @exclusive_filters.empty?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Detects whether the name associated with a namespace contains tags
|
|
51
|
+
# that matches the filtering criteria.
|
|
52
|
+
#
|
|
53
|
+
# @param [String] namespace the namespace which a test name belongs.
|
|
54
|
+
# @param [String] name the test name.
|
|
55
|
+
#
|
|
56
|
+
# Invariants:
|
|
57
|
+
# - Returns true when no filters are present.
|
|
58
|
+
#
|
|
59
|
+
# return [boolean] whether there was a match or not.
|
|
60
|
+
def match?(namespace:, name:)
|
|
61
|
+
return true if no_filters?
|
|
62
|
+
|
|
63
|
+
tags = @tag_registry.fetch(namespace: namespace, name: name)
|
|
64
|
+
match_inclusive_filters?(tags) && match_exclusive_filters?(tags)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# Detects whether any of the tags matches the inclusive filters.
|
|
70
|
+
#
|
|
71
|
+
# @param [Set] tags the set of tags.
|
|
72
|
+
#
|
|
73
|
+
# Invariants:
|
|
74
|
+
# - Returns true when no inclusive filters are specified.
|
|
75
|
+
# - Returns false when inclusive filters are specified but there
|
|
76
|
+
# are no tags.
|
|
77
|
+
#
|
|
78
|
+
# return [boolean] whether there was a match or not.
|
|
79
|
+
def match_inclusive_filters?(tags)
|
|
80
|
+
return true if @inclusive_filters.empty?
|
|
81
|
+
return false if @inclusive_filters.any? && tags.empty?
|
|
82
|
+
|
|
83
|
+
(@inclusive_filters & tags).any?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Detects whether any of the tags matches the exclusive filters.
|
|
87
|
+
#
|
|
88
|
+
# @param [Set] tags the set of tags.
|
|
89
|
+
#
|
|
90
|
+
# Invariants:
|
|
91
|
+
# - Returns true when no exclusive filters are specified.
|
|
92
|
+
# - Returns true when exclusive filters are specified and there
|
|
93
|
+
# are no tags.
|
|
94
|
+
#
|
|
95
|
+
# return [boolean] whether there was a match or not.
|
|
96
|
+
def match_exclusive_filters?(tags)
|
|
97
|
+
return true if @exclusive_filters.empty?
|
|
98
|
+
return true if @exclusive_filters.any? && tags.empty?
|
|
99
|
+
|
|
100
|
+
(@exclusive_filters & tags).none?
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -7,15 +7,24 @@ module Minitag
|
|
|
7
7
|
# - Associate tags with tests
|
|
8
8
|
# - Filter tests based on the specified tags
|
|
9
9
|
module TagExtension
|
|
10
|
+
# Add tags to be associated with the next test definition.
|
|
11
|
+
#
|
|
12
|
+
# It is important to notice that tags associated with a test have no concept
|
|
13
|
+
# of inclusive or exclusive tags. This distinction is only valid for tag
|
|
14
|
+
# filters.
|
|
15
|
+
#
|
|
16
|
+
# @param [Array] tags the list of tags to be associated with a test case.
|
|
17
|
+
#
|
|
18
|
+
# return [void]
|
|
10
19
|
def tag(*tags)
|
|
11
|
-
Minitag.pending_tags = tags
|
|
20
|
+
Minitag.pending_tags = tags.map { |tag| tag.to_s.strip.downcase }
|
|
12
21
|
end
|
|
13
22
|
|
|
14
23
|
define_method(:method_added) do |name|
|
|
15
24
|
if name[/\Atest_/]
|
|
16
|
-
Minitag.
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
Minitag.context.add_tags(
|
|
26
|
+
namespace: self, name: name, tags: Minitag.pending_tags
|
|
27
|
+
)
|
|
19
28
|
|
|
20
29
|
Minitag.pending_tags = []
|
|
21
30
|
end
|
|
@@ -23,17 +32,10 @@ module Minitag
|
|
|
23
32
|
|
|
24
33
|
def runnable_methods
|
|
25
34
|
methods = super.dup
|
|
26
|
-
return methods if Minitag.
|
|
27
|
-
|
|
28
|
-
execution_tags = Minitag.execution_tags
|
|
29
|
-
inclusive_tags = execution_tags.select(&:inclusive?).map(&:name)
|
|
30
|
-
exclusive_tags = execution_tags.select(&:exclusive?).map(&:name)
|
|
35
|
+
return methods if Minitag.context.no_filters?
|
|
31
36
|
|
|
32
37
|
methods.select do |runnable_method|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Minitag::TagMatcher.inclusive_match?(inclusive_tags, runnable_method_tags) &&
|
|
36
|
-
Minitag::TagMatcher.exclusive_match?(exclusive_tags, runnable_method_tags)
|
|
38
|
+
Minitag.context.match?(namespace: self, name: runnable_method)
|
|
37
39
|
end
|
|
38
40
|
end
|
|
39
41
|
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'set'
|
|
4
|
+
|
|
5
|
+
module Minitag
|
|
6
|
+
# Stores tags associated with a namespace and name.
|
|
7
|
+
class TagRegistry
|
|
8
|
+
def initialize
|
|
9
|
+
@repository = Hash.new { |h, k| h[k] = Set.new }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Associates tags with a name taking into account its namespace.
|
|
13
|
+
#
|
|
14
|
+
# @param [String] namespace the namespace which a test name belongs.
|
|
15
|
+
# @param [String] name the test name.
|
|
16
|
+
# @param [Array] tags the collection of tags.
|
|
17
|
+
#
|
|
18
|
+
# @return [void]
|
|
19
|
+
def add(namespace:, name:, tags:)
|
|
20
|
+
@repository[key(namespace, name)] = Set.new(tags)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Fetches tags associated with a test name and namespace.
|
|
24
|
+
#
|
|
25
|
+
# @param [String] namespace the namespace which a test name belongs.
|
|
26
|
+
# @param [String] name the test name.
|
|
27
|
+
#
|
|
28
|
+
# @return [Set] the tags associated with the specified namespace and name.
|
|
29
|
+
def fetch(namespace:, name:)
|
|
30
|
+
@repository[key(namespace, name)]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def key(namespace, name)
|
|
36
|
+
"#{namespace}_#{name}"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
data/lib/minitag/version.rb
CHANGED
|
@@ -8,13 +8,13 @@ module Minitest
|
|
|
8
8
|
def self.plugin_minitag_options(opts, options)
|
|
9
9
|
opts.on '-t', '--tag TAG' do |tag|
|
|
10
10
|
options[:tags] ||= []
|
|
11
|
-
options[:tags] << tag
|
|
11
|
+
options[:tags] << tag.to_s.strip.downcase
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def self.plugin_minitag_init(options)
|
|
16
16
|
Array(options[:tags]).each do |tag|
|
|
17
|
-
Minitag.
|
|
17
|
+
Minitag.context.add_filter(tag)
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: minitag
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bernardo de Araujo
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-07-
|
|
11
|
+
date: 2020-07-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -85,10 +85,9 @@ files:
|
|
|
85
85
|
- bin/console
|
|
86
86
|
- bin/setup
|
|
87
87
|
- lib/minitag.rb
|
|
88
|
-
- lib/minitag/
|
|
88
|
+
- lib/minitag/context.rb
|
|
89
89
|
- lib/minitag/tag_extension.rb
|
|
90
|
-
- lib/minitag/
|
|
91
|
-
- lib/minitag/tag_matcher.rb
|
|
90
|
+
- lib/minitag/tag_registry.rb
|
|
92
91
|
- lib/minitag/version.rb
|
|
93
92
|
- lib/minitest/minitag_plugin.rb
|
|
94
93
|
- minitag.gemspec
|
data/lib/minitag/tag.rb
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Minitag
|
|
4
|
-
# Represents a tag in our system.
|
|
5
|
-
# Provides helper methods to identify the type of a tag, which can
|
|
6
|
-
# only one of the following:
|
|
7
|
-
# - inclusive
|
|
8
|
-
# - exclusive (name with ~ as a prefix)
|
|
9
|
-
class Tag
|
|
10
|
-
attr_reader :name
|
|
11
|
-
|
|
12
|
-
# Initializes a tag. Tags with a ~ prefix are deemed exclusive and
|
|
13
|
-
# inclusive otherwise.
|
|
14
|
-
#
|
|
15
|
-
# param [String] name the name of the tag
|
|
16
|
-
#
|
|
17
|
-
# Invariants:
|
|
18
|
-
# - A tag name will always be a String without the ~ prefix
|
|
19
|
-
# after initialization.
|
|
20
|
-
def initialize(name)
|
|
21
|
-
@name = name.to_s
|
|
22
|
-
@exclusive = false
|
|
23
|
-
|
|
24
|
-
return unless @name.start_with?('~')
|
|
25
|
-
|
|
26
|
-
@name = @name[1..-1]
|
|
27
|
-
@exclusive = true
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Whether this tag needs to be excluded or not.
|
|
31
|
-
#
|
|
32
|
-
# return [boolean]
|
|
33
|
-
def exclusive?
|
|
34
|
-
@exclusive
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Whether this tag needs to be included or not.
|
|
38
|
-
#
|
|
39
|
-
# return [boolean]
|
|
40
|
-
def inclusive?
|
|
41
|
-
!exclusive?
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
data/lib/minitag/tag_mapper.rb
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Minitag
|
|
4
|
-
# Stores the mapping between a test name and its existing tags.
|
|
5
|
-
class TagMapper
|
|
6
|
-
def initialize
|
|
7
|
-
@repository = Hash.new { |h, k| h[k] = [] }
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# Associates a tag with a test name takinto into account is context.
|
|
11
|
-
#
|
|
12
|
-
# @param [String] context the context which a test name belongs.
|
|
13
|
-
# @param [String] name the test name.
|
|
14
|
-
# @param [String] tag the tag name.
|
|
15
|
-
#
|
|
16
|
-
# @return [void]
|
|
17
|
-
def add(context:, name:, tag:)
|
|
18
|
-
@repository[key(context, name)] << Minitag::Tag.new(tag)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Fetches tags associated with a test name and context.
|
|
22
|
-
#
|
|
23
|
-
# @param [String] context the context which a test name belongs.
|
|
24
|
-
# @param [String] name the test name.
|
|
25
|
-
#
|
|
26
|
-
# @return [Array] the tags associated with the test.
|
|
27
|
-
def fetch(context:, name:)
|
|
28
|
-
@repository[key(context, name)]
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
private
|
|
32
|
-
|
|
33
|
-
def key(context, name)
|
|
34
|
-
"#{context}_#{name}"
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
data/lib/minitag/tag_matcher.rb
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Minitag
|
|
4
|
-
# Introduce different match? methods based on the type of the chosen tags.
|
|
5
|
-
class TagMatcher
|
|
6
|
-
# Detects if any of the desired tags match any of the existing ones.
|
|
7
|
-
#
|
|
8
|
-
# @param [Array] desired_tags the tags specified by `--tag`.
|
|
9
|
-
# @param [Array] existing_tags the tags specified by the `tag` method.
|
|
10
|
-
#
|
|
11
|
-
# Invariants:
|
|
12
|
-
# - Always returns true when no desired tags are specified.
|
|
13
|
-
# - Always returns false when desired tags are specified but there are
|
|
14
|
-
# no existing tags.
|
|
15
|
-
#
|
|
16
|
-
# return [boolean] whether there was a match or not.
|
|
17
|
-
def self.inclusive_match?(desired_tags, existing_tags)
|
|
18
|
-
return true if desired_tags.empty?
|
|
19
|
-
return false if desired_tags.any? && existing_tags.empty?
|
|
20
|
-
|
|
21
|
-
(desired_tags & existing_tags).any?
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Detects if there are no matches between any of the desired tags
|
|
25
|
-
# and existing ones.
|
|
26
|
-
#
|
|
27
|
-
# @param desired_tags [Array] tags specified by `--tag`.
|
|
28
|
-
# @param existing_tags [Array] tags specified by the `tag` method.
|
|
29
|
-
#
|
|
30
|
-
# Invariants:
|
|
31
|
-
# - Always returns true when no desired tags are specified.
|
|
32
|
-
# - Always returns true when desired tags are specified but there are
|
|
33
|
-
# no existing tags.
|
|
34
|
-
#
|
|
35
|
-
# return [boolean] whether there was no match or not.
|
|
36
|
-
def self.exclusive_match?(desired_tags, existing_tags)
|
|
37
|
-
return true if desired_tags.empty?
|
|
38
|
-
return true if desired_tags.any? && existing_tags.empty?
|
|
39
|
-
|
|
40
|
-
(desired_tags & existing_tags).none?
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|