yard_example_runner 0.1.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.
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake'
4
+ require 'rake/tasklib'
5
+
6
+ module YardExampleRunner
7
+ # Rake task for running YARD @example tags as tests.
8
+ #
9
+ # @example Define the task with defaults
10
+ # YardExampleRunner::RakeTask.new
11
+ #
12
+ # @example Define the task with custom options
13
+ # YardExampleRunner::RakeTask.new do |task|
14
+ # task.run_examples_opts = %w[-v]
15
+ # task.pattern = 'app/**/*.rb'
16
+ # end
17
+ #
18
+ # @api public
19
+ #
20
+ class RakeTask < ::Rake::TaskLib
21
+ # The name of the Rake task
22
+ #
23
+ # @example
24
+ # task = YardExampleRunner::RakeTask.new
25
+ # task.name #=> 'yard:run-examples'
26
+ #
27
+ # @return [String] the task name
28
+ #
29
+ attr_accessor :name
30
+
31
+ # Options passed to the +yard run-examples+ command
32
+ #
33
+ # @example
34
+ # task = YardExampleRunner::RakeTask.new
35
+ # task.run_examples_opts = %w[-v]
36
+ # task.run_examples_opts #=> ['-v']
37
+ #
38
+ # @return [Array<String>] the command-line options
39
+ #
40
+ attr_accessor :run_examples_opts
41
+
42
+ # Glob pattern for files to pass to +yard run-examples+
43
+ #
44
+ # @example
45
+ # task = YardExampleRunner::RakeTask.new
46
+ # task.pattern = 'app/**/*.rb'
47
+ # task.pattern #=> 'app/**/*.rb'
48
+ #
49
+ # @return [String] the glob pattern, or an empty string to use the default
50
+ #
51
+ attr_accessor :pattern
52
+
53
+ # Creates and registers the Rake task
54
+ #
55
+ # @example
56
+ # YardExampleRunner::RakeTask.new do |task|
57
+ # task.run_examples_opts = %w[-v]
58
+ # task.pattern = 'app/**/*.rb'
59
+ # end
60
+ #
61
+ # @param name [String] the Rake task name
62
+ #
63
+ # @yield [self] gives the task instance to the block for configuration
64
+ #
65
+ # @return [void]
66
+ #
67
+ def initialize(name = 'yard:run-examples')
68
+ super()
69
+ @name = name
70
+ @run_examples_opts = []
71
+ @pattern = ''
72
+ yield self if block_given?
73
+ define
74
+ end
75
+
76
+ protected
77
+
78
+ # Defines the Rake task
79
+ #
80
+ # @return [void]
81
+ #
82
+ # @api private
83
+ #
84
+ def define
85
+ desc 'Run YARD @example tags as tests'
86
+ task(name) do
87
+ args = run_examples_opts + (pattern.empty? ? [] : [pattern])
88
+ abort unless system('yard', 'run-examples', *args)
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module YardExampleRunner
4
+ # The current gem version
5
+ # @return [String] the current gem version.
6
+ VERSION = '0.1.0'
7
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yard'
4
+ require 'minitest'
5
+ require 'minitest/spec'
6
+
7
+ require_relative 'yard/cli/run_examples'
8
+ require_relative 'yard_example_runner/example'
9
+ require_relative 'yard_example_runner/expectation'
10
+ require_relative 'yard_example_runner/version'
11
+
12
+ # Provides configuration and hooks for running YARD @example tags as tests.
13
+ #
14
+ # @api public
15
+ #
16
+ module YardExampleRunner
17
+ # Configures YardExampleRunner
18
+ #
19
+ # @example
20
+ # YardExampleRunner.configure do |runner|
21
+ # runner.before { @value = 1 }
22
+ # runner.after { puts 'done' }
23
+ # end
24
+ #
25
+ # @yield [self] gives the module itself to the block for configuration
26
+ #
27
+ # @return [void]
28
+ #
29
+ # @api public
30
+ #
31
+ def self.configure
32
+ yield self
33
+ end
34
+
35
+ # Registers a block to be called before each example, or before a specific test
36
+ #
37
+ # The block is evaluated in the same context as the example.
38
+ #
39
+ # @example Register a global before hook
40
+ # YardExampleRunner.before { @value = 1 }
41
+ #
42
+ # @example Register a hook for a specific test
43
+ # YardExampleRunner.before('#my_method') { @value = 42 }
44
+ #
45
+ # @param test [String, nil] the test name to match, or +nil+ for all tests
46
+ #
47
+ # @param blk [Proc] the block to call before the matched example(s)
48
+ #
49
+ # @return [void]
50
+ #
51
+ # @api public
52
+ #
53
+ def self.before(test = nil, &blk)
54
+ hooks[:before] << { test: test, block: blk }
55
+ end
56
+
57
+ # Registers a block to be called after each example, or after a specific test
58
+ #
59
+ # The block is evaluated in the same context as the example.
60
+ #
61
+ # @example Register a global after hook
62
+ # YardExampleRunner.after { puts 'done' }
63
+ #
64
+ # @example Register a hook for a specific test
65
+ # YardExampleRunner.after('#my_method') { puts 'my_method done' }
66
+ #
67
+ # @param test [String, nil] the test name to match, or +nil+ for all tests
68
+ #
69
+ # @param blk [Proc] the block to call after the matched example(s)
70
+ #
71
+ # @return [void]
72
+ #
73
+ # @api public
74
+ #
75
+ def self.after(test = nil, &blk)
76
+ hooks[:after] << { test: test, block: blk }
77
+ end
78
+
79
+ # Registers a block to be called after all examples have run
80
+ #
81
+ # The block is evaluated in a different context from the examples. Delegates
82
+ # to +Minitest.after_run+.
83
+ #
84
+ # @example
85
+ # YardExampleRunner.after_run { puts 'All examples finished' }
86
+ #
87
+ # @return [void]
88
+ #
89
+ # @api public
90
+ #
91
+ def self.after_run(&)
92
+ Minitest.after_run(&)
93
+ end
94
+
95
+ # Registers a test definition to be skipped
96
+ #
97
+ # @example
98
+ # YardExampleRunner.skip '#my_method'
99
+ #
100
+ # @param test [String] the test name or definition path to skip
101
+ #
102
+ # @return [void]
103
+ #
104
+ # @api public
105
+ #
106
+ def self.skip(test)
107
+ skips << test
108
+ end
109
+
110
+ # Returns the array of test definitions registered to be skipped
111
+ #
112
+ # @return [Array<String>] the registered skip patterns
113
+ #
114
+ # @api private
115
+ #
116
+ def self.skips
117
+ @skips ||= []
118
+ end
119
+
120
+ # Returns the hash of registered before/after hooks
121
+ #
122
+ # @return [Hash{Symbol => Array<Hash>}] the registered hooks grouped by type
123
+ #
124
+ # @api private
125
+ #
126
+ def self.hooks
127
+ @hooks ||= {}.tap do |hash|
128
+ hash[:before] = []
129
+ hash[:after] = []
130
+ end
131
+ end
132
+ end
133
+
134
+ YARD::CLI::CommandParser.commands[:'run-examples'] = YARD::CLI::RunExamples
data/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "devDependencies": {
3
+ "@commitlint/cli": "^19.8.0",
4
+ "@commitlint/config-conventional": "^19.8.0",
5
+ "husky": "^9.1.7",
6
+ "markdownlint-cli": "^0.47.0"
7
+ },
8
+ "scripts": {
9
+ "lint:md": "markdownlint '**/*.md' --ignore node_modules --ignore vendor",
10
+ "prepare": "husky"
11
+ }
12
+ }
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cucumber/rake/task'
4
+
5
+ Cucumber::Rake::Task.new do |task|
6
+ task.cucumber_opts = %w[-f progress features --publish-quiet]
7
+ end
8
+
9
+ CLEAN << 'tmp'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+
5
+ # Make it so that calling `rake release` just calls `rake release:rubygem_push` to
6
+ # avoid creating and pushing a new tag.
7
+
8
+ Rake::Task['release'].clear
9
+ desc 'Customized release task to avoid creating a new tag'
10
+ task release: 'release:rubygem_push'
11
+
12
+ CLOBBER << 'Gemfile.lock'
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc 'Run markdownlint on all Markdown files'
4
+ task :markdownlint do
5
+ sh 'npm run lint:md'
6
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop/rake_task'
4
+
5
+ RuboCop::RakeTask.new
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # YARD documentation for this project can NOT be built with JRuby or TruffleRuby.
4
+ # This project uses the redcarpet gem which can not be installed on JRuby.
5
+ #
6
+ unless RUBY_PLATFORM == 'java' || RUBY_ENGINE == 'truffleruby'
7
+ # yard:build
8
+
9
+ require 'yard'
10
+
11
+ YARD::Rake::YardocTask.new('yard:build') do |t|
12
+ t.files = %w[lib/**/*.rb]
13
+ t.stats_options = ['--list-undoc']
14
+ end
15
+
16
+ CLEAN << '.yardoc'
17
+ CLEAN << 'doc'
18
+
19
+ # yard:audit
20
+
21
+ desc 'Run yardstick to show missing YARD doc elements'
22
+ task :'yard:audit' do
23
+ sh "yardstick 'lib/**/*.rb'"
24
+ end
25
+
26
+ # yard:coverage
27
+
28
+ require 'yardstick/rake/verify'
29
+
30
+ Yardstick::Rake::Verify.new(:'yard:coverage') do |verify|
31
+ verify.threshold = 100
32
+ verify.require_exact_threshold = false
33
+ end
34
+
35
+ # yard
36
+
37
+ desc 'Run YARD documentation tasks (build, coverage)'
38
+ task yard: %i[yard:build yard:audit yard:coverage]
39
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ version = File.read(File.expand_path('lib/yard_example_runner/version.rb', __dir__)).match(/VERSION = ['"](.*?)['"]/)[1]
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'yard_example_runner'
7
+ spec.summary = 'A YARD plugin that executes @example tag code as tests'
8
+ spec.description = 'yard_example_runner parses @example tags from YARD documentation and ' \
9
+ 'executes them as tests, ensuring code examples remain accurate ' \
10
+ 'and serve as a living, executable specification.'
11
+ spec.author = 'James Couball'
12
+ spec.email = 'jcouball@yahoo.com'
13
+ spec.homepage = 'https://github.com/main-branch/yard_example_runner'
14
+ spec.license = 'MIT'
15
+ spec.version = version
16
+
17
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
19
+ end
20
+
21
+ spec.metadata['homepage_uri'] = spec.homepage
22
+ spec.metadata['source_code_uri'] = spec.homepage
23
+ spec.metadata['changelog_uri'] = "https://rubydoc.info/gems/#{spec.name}/#{spec.version}/file/CHANGELOG.md"
24
+ spec.metadata['documentation_uri'] = "https://rubydoc.info/gems/#{spec.name}/#{spec.version}"
25
+ spec.metadata['rubygems_mfa_required'] = 'true'
26
+
27
+ spec.require_paths = ['lib']
28
+ spec.required_ruby_version = '>= 3.3.0'
29
+
30
+ spec.add_dependency 'minitest', '~> 6.0'
31
+ spec.add_dependency 'yard', '~> 0.9'
32
+
33
+ spec.add_development_dependency 'aruba', '~> 2.3'
34
+ spec.add_development_dependency 'main_branch_shared_rubocop_config', '~> 0.1'
35
+ spec.add_development_dependency 'minitest-matchers_vaccine', '~> 1.1'
36
+ spec.add_development_dependency 'rake', '~> 13.0'
37
+ spec.add_development_dependency 'redcarpet', '~> 3.6'
38
+ spec.add_development_dependency 'rspec-expectations', '~> 3.13'
39
+ spec.add_development_dependency 'rubocop', '~> 1.84'
40
+ spec.add_development_dependency 'ruby-lsp', '~> 0.26'
41
+ spec.add_development_dependency 'simplecov', '~> 0.22'
42
+ spec.add_development_dependency 'yardstick', '~> 0.9'
43
+ end
metadata ADDED
@@ -0,0 +1,251 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yard_example_runner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James Couball
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: minitest
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '6.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '6.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: yard
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.9'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.9'
40
+ - !ruby/object:Gem::Dependency
41
+ name: aruba
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '2.3'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.3'
54
+ - !ruby/object:Gem::Dependency
55
+ name: main_branch_shared_rubocop_config
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.1'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.1'
68
+ - !ruby/object:Gem::Dependency
69
+ name: minitest-matchers_vaccine
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.1'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.1'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rake
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '13.0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '13.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: redcarpet
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.6'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.6'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec-expectations
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.13'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '3.13'
124
+ - !ruby/object:Gem::Dependency
125
+ name: rubocop
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '1.84'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '1.84'
138
+ - !ruby/object:Gem::Dependency
139
+ name: ruby-lsp
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '0.26'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '0.26'
152
+ - !ruby/object:Gem::Dependency
153
+ name: simplecov
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '0.22'
159
+ type: :development
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '0.22'
166
+ - !ruby/object:Gem::Dependency
167
+ name: yardstick
168
+ requirement: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - "~>"
171
+ - !ruby/object:Gem::Version
172
+ version: '0.9'
173
+ type: :development
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '0.9'
180
+ description: yard_example_runner parses @example tags from YARD documentation and
181
+ executes them as tests, ensuring code examples remain accurate and serve as a living,
182
+ executable specification.
183
+ email: jcouball@yahoo.com
184
+ executables: []
185
+ extensions: []
186
+ extra_rdoc_files: []
187
+ files:
188
+ - ".commitlintrc.yml"
189
+ - ".github/workflows/continuous-integration.yml"
190
+ - ".github/workflows/enforce_conventional_commits.yml"
191
+ - ".github/workflows/release.yml"
192
+ - ".gitignore"
193
+ - ".husky/commit-msg"
194
+ - ".markdownlint.yml"
195
+ - ".release-please-config.json"
196
+ - ".release-please-manifest.json"
197
+ - ".rubocop.yml"
198
+ - AI_POLICY.md
199
+ - CHANGELOG.md
200
+ - CODE_OF_CONDUCT.md
201
+ - CONTRIBUTING.md
202
+ - GOVERNANCE.md
203
+ - Gemfile
204
+ - LICENSE.txt
205
+ - MAINTAINERS.md
206
+ - README.md
207
+ - Rakefile
208
+ - bin/setup
209
+ - lib/yard/cli/run_examples.rb
210
+ - lib/yard_example_runner.rb
211
+ - lib/yard_example_runner/example.rb
212
+ - lib/yard_example_runner/example/comparison.rb
213
+ - lib/yard_example_runner/example/constant_sandbox.rb
214
+ - lib/yard_example_runner/example/evaluator.rb
215
+ - lib/yard_example_runner/expectation.rb
216
+ - lib/yard_example_runner/rake.rb
217
+ - lib/yard_example_runner/version.rb
218
+ - package.json
219
+ - rake_tasks/cucumber.rake
220
+ - rake_tasks/gem_tasks.rake
221
+ - rake_tasks/markdownlint.rake
222
+ - rake_tasks/rubocop.rake
223
+ - rake_tasks/yard.rake
224
+ - yard_example_runner.gemspec
225
+ homepage: https://github.com/main-branch/yard_example_runner
226
+ licenses:
227
+ - MIT
228
+ metadata:
229
+ homepage_uri: https://github.com/main-branch/yard_example_runner
230
+ source_code_uri: https://github.com/main-branch/yard_example_runner
231
+ changelog_uri: https://rubydoc.info/gems/yard_example_runner/0.1.0/file/CHANGELOG.md
232
+ documentation_uri: https://rubydoc.info/gems/yard_example_runner/0.1.0
233
+ rubygems_mfa_required: 'true'
234
+ rdoc_options: []
235
+ require_paths:
236
+ - lib
237
+ required_ruby_version: !ruby/object:Gem::Requirement
238
+ requirements:
239
+ - - ">="
240
+ - !ruby/object:Gem::Version
241
+ version: 3.3.0
242
+ required_rubygems_version: !ruby/object:Gem::Requirement
243
+ requirements:
244
+ - - ">="
245
+ - !ruby/object:Gem::Version
246
+ version: '0'
247
+ requirements: []
248
+ rubygems_version: 4.0.3
249
+ specification_version: 4
250
+ summary: A YARD plugin that executes @example tag code as tests
251
+ test_files: []