minitag 0.3.2 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 100ac9cc9bfef52b3aa37c8606e6a447c74459bd52df6fcda671950a6d3968e2
4
- data.tar.gz: 0fe274909e46e1a0f8f812d0ec7891ae60d2a90beb92523fd7ff3720c040e7a0
3
+ metadata.gz: 3149cc0ce5b301309d45193c6e997b300adb38c6944b2e0c22a0e2634d5e576b
4
+ data.tar.gz: a15958d81aaa6f99f2d2656cb4ee3840e877bd2c0bf8f4ff877ad6514bb1bfca
5
5
  SHA512:
6
- metadata.gz: 44754017cba905183452e103376d8228157ec6db852b4ff3764e89d0c66889a85e78a2867ba4f05ebbc18f7c46011583b4be5ade2239c8d75a9ccd276b083d24
7
- data.tar.gz: 96de93bec156b177800d63d9ca7638dcd09eb20fcfd6e547f424f51b5bb1e2112a3b16f516990c096d1c47bce288b060d92b61238ff17a5652d4a1cb6e251fe6
6
+ metadata.gz: a4ee8c9f7de0386c4275b997c426bb12be7eff7fbd76b7966fde47e8452e35d529e496e6cfb3ccd02e0ab50a622c60ca3d8d2204ae8de940c26e4e9f57124603
7
+ data.tar.gz: 726bb9c4307f77aba61d23966b339d8a26f20e4b9238dba73546466e942abead18c8e7c7842eb37ab02fb3b9e85c7a2ff6203f830b623c4267790963f65f3a63
@@ -0,0 +1,36 @@
1
+ name: continuous-integration
2
+ on:
3
+ push:
4
+ pull_request:
5
+ branches:
6
+ - master
7
+
8
+ jobs:
9
+ ci:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ - name: Set up Ruby 2.7
14
+ uses: actions/setup-ruby@v1
15
+ with:
16
+ ruby-version: "2.7"
17
+ - name: Cache gems
18
+ uses: actions/cache@v2
19
+ with:
20
+ path: vendor/bundle
21
+ key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
22
+ restore-keys: |
23
+ ${{ runner.os }}-gem-
24
+ - name: Install gems
25
+ run: |
26
+ sed -i '/ruby ".*"/,+1 d' Gemfile
27
+ bundle_version=`awk '/BUNDLED WITH/{getline; gsub(/ /, "", $0); print}' Gemfile.lock`
28
+ gem install bundler --no-document -v ${bundle_version}
29
+ bundle config retry "3"
30
+ bundle config jobs "$(nproc)"
31
+ bundle config path vendor/bundle
32
+ bundle install
33
+ - name: Run RuboCop
34
+ run: bundle exec rubocop --parallel
35
+ - name: Run tests
36
+ run: bundle exec rake test
@@ -1,13 +1,8 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
3
 
4
- Metrics/AbcSize:
5
- Enabled: false
6
-
7
- Metrics/CyclomaticComplexity:
8
- Enabled: false
9
-
10
4
  Layout/LineLength:
11
5
  Max: 120
12
6
 
13
-
7
+ Metrics/ClassLength:
8
+ Enabled: false
data/Gemfile CHANGED
@@ -4,5 +4,7 @@ source 'https://rubygems.org'
4
4
 
5
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
+ ruby '>= 2.6'
8
+
7
9
  # Specify your gem's dependencies in minitag.gemspec
8
10
  gemspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- minitag (0.3.2)
4
+ minitag (0.6.0)
5
5
  minitest (~> 5.0)
6
6
 
7
7
  GEM
@@ -39,5 +39,8 @@ DEPENDENCIES
39
39
  rake (>= 12.3.3)
40
40
  rubocop (~> 0.87.1)
41
41
 
42
+ RUBY VERSION
43
+ ruby 2.6.3p62
44
+
42
45
  BUNDLED WITH
43
46
  1.17.2
data/README.md CHANGED
@@ -1,11 +1,19 @@
1
- [![Gem Version](https://badge.fury.io/rb/minitag.svg)](https://badge.fury.io/rb/minitag)
1
+ [![Gem Version](https://badge.fury.io/rb/minitag.svg)](https://badge.fury.io/rb/minitag) [![](https://github.com/bernardoamc/minitag/workflows/continuous-integration/badge.svg)](https://github.com/bernardoamc/minitag/actions?query=workflow%3Acontinuous-integration)
2
2
 
3
3
  # Minitag
4
4
 
5
- [![Build Status](https://travis-ci.org/bernardoamc/minitag.svg?branch=master)](https://travis-ci.org/bernardoamc/minitag)
5
+ A simple gem that allow developers using minitest to specify tags for their classes and tests, and run their test suite based on these tags.
6
6
 
7
- A simple gem that allow developers to tag their minitest tests and run tests
8
- based on these tags.
7
+ This gem should be framework agnostic, let me know if you encounter any problems
8
+ running this within the framework of your choice.
9
+
10
+ ## When should I use this?
11
+
12
+ - When there's a need to split a test suite into different CI steps.
13
+ - During development, it's helpful to have extra flexibility when running a big
14
+ test suite.
15
+ - When there are tests that you want to run only occasionality. For example,
16
+ tests that perform network calls or have expensive side effects.
9
17
 
10
18
  ## Installation
11
19
 
@@ -25,20 +33,24 @@ $ gem install minitag
25
33
 
26
34
  ### Setup
27
35
 
28
- Require `minitag` in our `test_helper.rb`:
36
+ Require `minitag` within `test_helper.rb`:
29
37
 
30
38
  `require 'minitag'`
31
39
 
32
40
  ### Adding tags
33
41
 
34
- We can tag specific tests with one or more tags.
42
+ We can tag specific classes or tests with one or more tags.
35
43
 
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).
44
+ It is important to point out that tags associated with a class or test have no concept of being inclusive or exclusive. This distinction is only valid for [tag filters](#running-tests-with-tag-filters).
37
45
 
38
46
  ```rb
39
47
  class MyTest < Minitest::Test
48
+ # Every test within this class will inherit this tag
49
+ tag_namespace 'my_namespace_tag'
50
+
51
+ # Only the test below will have this tag
40
52
  tag 'my_tag', 'another_tag'
41
- test '#hello minitag' do
53
+ def test_hello_minitest
42
54
  # ...
43
55
  end
44
56
  end
@@ -1,14 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'set'
3
4
  require 'minitest'
4
5
  require 'minitag/version'
5
6
  require 'minitag/context'
7
+ require 'minitag/extension_registry'
8
+ require 'minitag/minitest_tag'
6
9
  require 'minitag/tag_extension'
7
10
 
8
11
  # Namespace for classes or modules providing tagging functionality
9
12
  # to Minitest::Test
10
13
  module Minitag
11
14
  class << self
15
+ # Registry of classes that requires extension by Minitag::TagExtension.
16
+ def extension_registry
17
+ @extension_registry ||= ExtensionRegistry.new
18
+ end
19
+
20
+ # Register a class for extension.
21
+ def register_for_extension(klass)
22
+ extension_registry.register(klass)
23
+ end
24
+
12
25
  # Execution context of the test suite.
13
26
  def context
14
27
  @context ||= Context.new
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
3
  require_relative './tag_registry'
5
4
 
6
5
  module Minitag
@@ -19,12 +18,25 @@ module Minitag
19
18
  # @param [Array] tags the collection of tags.
20
19
  #
21
20
  # @return [void]
22
- def add_tags(namespace:, name:, tags:)
21
+ def add_test_tags(namespace:, name:, tags:)
23
22
  @tag_registry.add(namespace: namespace, name: name, tags: tags)
24
23
  end
25
24
 
25
+ # Add tags to an entire namespace. Every test within the namespace will
26
+ # share these tags.
27
+ #
28
+ # @param [String] namespace the namespace that contain tests.
29
+ # @param [Array] tags the collection of tags.
30
+ #
31
+ # @return [void]
32
+ def add_namespace_tags(namespace:, tags:)
33
+ @tag_registry.add_for_namespace(namespace: namespace, tags: tags)
34
+ end
35
+
26
36
  # Adds a filter tag.
27
- # Tags with a ~ prefix are treated as exclusive filters or inclusive filters otherwise.
37
+ #
38
+ # Tags with a ~ prefix are treated as exclusive filters or inclusive filters
39
+ # otherwise.
28
40
  #
29
41
  # param [String] name the name of the filter tag.
30
42
  #
@@ -34,7 +46,7 @@ module Minitag
34
46
  # @return [void]
35
47
  def add_filter(tag)
36
48
  if tag.start_with?('~')
37
- @exclusive_filters << tag[1..-1]
49
+ @exclusive_filters << tag[1..]
38
50
  else
39
51
  @inclusive_filters << tag
40
52
  end
@@ -62,7 +74,7 @@ module Minitag
62
74
  def match?(namespace:, name:)
63
75
  return true if no_filters?
64
76
 
65
- tags = @tag_registry.fetch(namespace: namespace, name: name)
77
+ tags = @tag_registry.get(namespace: namespace, name: name)
66
78
  match_inclusive_filters?(tags) && match_exclusive_filters?(tags)
67
79
  end
68
80
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Minitag
4
+ # Stores and extends classes that relies on tags with the Minitag::TagExtension
5
+ # module.
6
+ class ExtensionRegistry
7
+ def initialize
8
+ @registry = {}
9
+ end
10
+
11
+ # Extends a class with Minitag::TagExtension and stores it as extended.
12
+ #
13
+ # Invariants:
14
+ # - Classes that were already extended will be ignored during this operation.
15
+ #
16
+ # @param [Class] klass a class that will be extended.
17
+ #
18
+ # @return [void]
19
+ def register(klass)
20
+ return if @registry.key?(klass)
21
+
22
+ @registry[klass] = true
23
+ klass.singleton_class.prepend(Minitag::TagExtension)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Minitag
4
+ # Module used to extend Minitest::Test with the tag method.
5
+ module MinitestTag
6
+ # Add tags to be associated with an entire class that inherits from
7
+ # Minitest::Test. Every test that belongs to this class will also inherit
8
+ # these tags.
9
+ #
10
+ # It is important to notice that tags associated with a class have no
11
+ # concept of being inclusive or exclusive. This distinction is only
12
+ # valid for tag filters.
13
+ #
14
+ # @param [Array] tags the list of tags to be associated with a test class.
15
+ #
16
+ # @return [void]
17
+ def tag_namespace(*tags)
18
+ Minitag.context.add_namespace_tags(
19
+ namespace: to_s,
20
+ tags: tags.map { |tag| tag.to_s.strip.downcase }
21
+ )
22
+ end
23
+
24
+ # Add tags to be associated with the next test definition and extends the
25
+ # class from which the tag method is being used with Minitag::TagExtension.
26
+ #
27
+ # It is important to notice that tags associated with a test have no concept
28
+ # of being inclusive or exclusive. This distinction is only valid for tag
29
+ # filters.
30
+ #
31
+ # @param [Array] tags the list of tags to be associated with a test case.
32
+ #
33
+ # @return [void]
34
+ def tag(*tags)
35
+ Minitag.pending_tags = tags.map { |tag| tag.to_s.strip.downcase }
36
+ Minitag.register_for_extension(self)
37
+ end
38
+
39
+ # Decides which methods to run based on an Array of test names provided by
40
+ # the superclass and the tags defined within test classes.
41
+ #
42
+ # Invariants:
43
+ # - Returns the full list of test names when the test suite runs without
44
+ # any tag filtering.
45
+ #
46
+ # @return [Array] the list of test names that should run.
47
+ def runnable_methods
48
+ methods = super.dup
49
+ return methods if Minitag.context.no_filters?
50
+
51
+ methods.select do |runnable_method|
52
+ Minitag.context.match?(namespace: to_s, name: runnable_method)
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ Minitest::Test.singleton_class.prepend(Minitag::MinitestTag)
@@ -1,44 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Minitag
4
- # Module used to extend Minitest::Test.
5
- # It has the following responsibilities:
6
- # - Introduce the tag functionality
7
- # - Associate tags with tests
8
- # - Filter tests based on the specified tags
4
+ # Responsible for listening to added methods and associating tags
5
+ # with those.
9
6
  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 being inclusive or exclusive. 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]
19
- def tag(*tags)
20
- Minitag.pending_tags = tags.map { |tag| tag.to_s.strip.downcase }
21
- end
22
-
23
7
  define_method(:method_added) do |name|
24
8
  if name[/\Atest_/]
25
- Minitag.context.add_tags(
26
- namespace: self, name: name, tags: Minitag.pending_tags
9
+ Minitag.context.add_test_tags(
10
+ namespace: to_s, name: name, tags: Minitag.pending_tags
27
11
  )
28
12
 
29
13
  Minitag.pending_tags = []
30
14
  end
31
15
  end
32
-
33
- def runnable_methods
34
- methods = super.dup
35
- return methods if Minitag.context.no_filters?
36
-
37
- methods.select do |runnable_method|
38
- Minitag.context.match?(namespace: self, name: runnable_method)
39
- end
40
- end
41
16
  end
42
17
  end
43
-
44
- Minitest::Test.singleton_class.prepend(Minitag::TagExtension)
@@ -1,13 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
-
5
3
  module Minitag
6
- # Stores tags associated with a test name, which belongs to a namespace.
7
- # The namespace is usually the class which the test belongs to.
4
+ # Stores tags associated with a namespace or a single test case.
5
+ #
6
+ # A namespace is usually the class which tests belongs to.
8
7
  class TagRegistry
9
8
  def initialize
10
- @repository = Hash.new { |h, k| h[k] = Set.new }
9
+ @registry = {}
11
10
  end
12
11
 
13
12
  # Associates tags with a name taking into account its namespace.
@@ -20,7 +19,19 @@ module Minitag
20
19
  #
21
20
  # @return [void]
22
21
  def add(namespace:, name:, tags:)
23
- @repository[key(namespace, name)] = Set.new(tags)
22
+ @registry[key(namespace, name)] = Set.new(tags)
23
+ end
24
+
25
+ # Associates tags with a namespace.
26
+ #
27
+ # Duplicated tags will be removed during this operation.
28
+ #
29
+ # @param [String] namespace the context which a test name belongs.
30
+ # @param [Array] tags the collection of tags associated with a test.
31
+ #
32
+ # @return [void]
33
+ def add_for_namespace(namespace:, tags:)
34
+ @registry[namespace] = Set.new(tags)
24
35
  end
25
36
 
26
37
  # Fetches tags associated with a test name and namespace.
@@ -29,8 +40,10 @@ module Minitag
29
40
  # @param [String] name the test name.
30
41
  #
31
42
  # @return [Set] the tags associated with the specified namespace and test name.
32
- def fetch(namespace:, name:)
33
- @repository[key(namespace, name)]
43
+ def get(namespace:, name:)
44
+ @registry.fetch(namespace, Set.new).union(
45
+ @registry.fetch(key(namespace, name), Set.new)
46
+ )
34
47
  end
35
48
 
36
49
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Minitag
4
- VERSION = '0.3.2'
4
+ VERSION = '0.6.0'
5
5
  end
@@ -14,7 +14,7 @@ module Minitest
14
14
 
15
15
  def self.plugin_minitag_init(options)
16
16
  Array(options[:tags]).each do |tag|
17
- Minitag.context.add_filter(tag)
17
+ Minitag.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.3.2
4
+ version: 0.6.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-12 00:00:00.000000000 Z
11
+ date: 2020-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -73,9 +73,9 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
+ - ".github/workflows/ci.yml"
76
77
  - ".gitignore"
77
78
  - ".rubocop.yml"
78
- - ".travis.yml"
79
79
  - CODE_OF_CONDUCT.md
80
80
  - Gemfile
81
81
  - Gemfile.lock
@@ -86,6 +86,8 @@ files:
86
86
  - bin/setup
87
87
  - lib/minitag.rb
88
88
  - lib/minitag/context.rb
89
+ - lib/minitag/extension_registry.rb
90
+ - lib/minitag/minitest_tag.rb
89
91
  - lib/minitag/tag_extension.rb
90
92
  - lib/minitag/tag_registry.rb
91
93
  - lib/minitag/version.rb
@@ -1,7 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.6.3
7
- before_install: gem install bundler -v 1.17.2