nrser-rash 0.2.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 +7 -0
- data/.gitignore +104 -0
- data/.gitmodules +4 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/.yardopts +7 -0
- data/Gemfile +10 -0
- data/README.md +4 -0
- data/Rakefile +6 -0
- data/bash/source-profile.sh +17 -0
- data/dev/bin/.gitkeep +0 -0
- data/dev/bin/console +33 -0
- data/dev/bin/rake +3 -0
- data/dev/bin/rash +16 -0
- data/dev/bin/rspec +3 -0
- data/dev/ref/autocomplete.rb +62 -0
- data/dev/scratch/apps.AppleScript +14 -0
- data/dev/scratch/blocks.rb +232 -0
- data/dev/scratch/decorating_methods.rb +18 -0
- data/dev/scratch/functions.sh +80 -0
- data/dev/scratch/if.sh +16 -0
- data/dev/scratch/inc.rb +3 -0
- data/dev/scratch/inheriting_env/main.rb +44 -0
- data/dev/scratch/inheriting_env/sub.rb +9 -0
- data/dev/scratch/load_main.rb +5 -0
- data/dev/scratch/load_module.rb +19 -0
- data/dev/scratch/lsregister-dump.txt +30165 -0
- data/dev/scratch/main.rb +4 -0
- data/dev/scratch/optparse.rb +43 -0
- data/dev/scratch/overridding-cd.sh +53 -0
- data/dev/scratch/path.sh +22 -0
- data/dev/scratch/pirating_methods.rb +62 -0
- data/dev/scratch/profile.sh +624 -0
- data/dev/scratch/return.sh +5 -0
- data/dev/scratch/source_rvm.sh +11 -0
- data/dev/scratch/stub-names/project/test +3 -0
- data/exe/rash +4 -0
- data/lib/nrser/rash/cli/call.rb +137 -0
- data/lib/nrser/rash/cli/help.rb +29 -0
- data/lib/nrser/rash/cli/list.rb +36 -0
- data/lib/nrser/rash/cli/run.rb +54 -0
- data/lib/nrser/rash/cli.rb +21 -0
- data/lib/nrser/rash/config.rb +172 -0
- data/lib/nrser/rash/core_ext/object.rb +55 -0
- data/lib/nrser/rash/formatters.rb +105 -0
- data/lib/nrser/rash/functions.rb +154 -0
- data/lib/nrser/rash/helpers.rb +53 -0
- data/lib/nrser/rash/testing.rb +305 -0
- data/lib/nrser/rash/util.rb +260 -0
- data/lib/nrser/rash/version.rb +17 -0
- data/lib/nrser/rash.rb +40 -0
- data/nrser-rash.gemspec +48 -0
- data/tmp/.gitkeep +0 -0
- metadata +248 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Refinements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
using NRSER
|
8
|
+
using NRSER::Types
|
9
|
+
|
10
|
+
|
11
|
+
# Definitions
|
12
|
+
# =======================================================================
|
13
|
+
|
14
|
+
module NRSER::Rash
|
15
|
+
# Users money-patch class methods into this call to expose them to Rash.
|
16
|
+
module Functions; end
|
17
|
+
|
18
|
+
# @!group Rash Function Class Methods
|
19
|
+
# ==========================================================================
|
20
|
+
|
21
|
+
def self.load_functions
|
22
|
+
path = config('FUNCTIONS').to_pn
|
23
|
+
require path
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def self.stub_function?(mod, method_name)
|
28
|
+
return false unless mod.method(method_name)
|
29
|
+
return false if method_name.to_s[0] == '_'[0]
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def self.stub_name namespace, method_name
|
35
|
+
(
|
36
|
+
(namespace.map {|s| s.downcase}) +
|
37
|
+
[method_name]
|
38
|
+
).join(config('STUB_NAMESPACE_SEPERATOR'))
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def self.submodule? obj
|
43
|
+
obj.is_a?(Module) && (not obj.is_a?(Class))
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# TODO: doesn't work. was try to prevent overriding non-rash functions
|
48
|
+
# (without some yet to be implemented way of doing so explicitly)
|
49
|
+
# 'cause this can cause accidental CHAOS with other scripts
|
50
|
+
def self.conflict? name
|
51
|
+
return false
|
52
|
+
type = `type #{ name } 2>&1`
|
53
|
+
if name == 'blah'
|
54
|
+
raise type
|
55
|
+
end
|
56
|
+
return false if $?.exitstatus != 0
|
57
|
+
return true
|
58
|
+
not type =~ /rash\ call/
|
59
|
+
end
|
60
|
+
|
61
|
+
# Stub out all the singleton methods under {NRSER::Rash::Functions}
|
62
|
+
def self.function_names
|
63
|
+
call_args = []
|
64
|
+
# method to recursivly stub singleton functions in a module
|
65
|
+
from_module = -> mod do
|
66
|
+
# when the name is split, 'Rash' and 'Functions' take up the
|
67
|
+
# first two elements, so drop those to get the namespace
|
68
|
+
# as an array of strings
|
69
|
+
namespace = mod.name.split( '::' ).drop( 3 )
|
70
|
+
# get each singleton method (`def self.*` style)
|
71
|
+
mod.singleton_methods.select {|method_name|
|
72
|
+
# throw out those that should not be stubbed
|
73
|
+
stub_function? mod, method_name
|
74
|
+
}.each do |method_name|
|
75
|
+
|
76
|
+
call_arg = if namespace.empty?
|
77
|
+
method_name.to_s
|
78
|
+
else
|
79
|
+
"#{ namespace.join('.') }.#{ method_name }"
|
80
|
+
end
|
81
|
+
|
82
|
+
call_args << call_arg.downcase
|
83
|
+
end
|
84
|
+
|
85
|
+
# descend into submodules
|
86
|
+
mod.constants.map {|name|
|
87
|
+
mod.const_get(name)
|
88
|
+
}.select {|const|
|
89
|
+
# exclude any TestCase classes
|
90
|
+
# (const.is_a? Module) && (not const < Minitest::Test)
|
91
|
+
submodule? const
|
92
|
+
}.each {|submod|
|
93
|
+
from_module.call submod
|
94
|
+
}
|
95
|
+
end # from_module
|
96
|
+
|
97
|
+
from_module.call NRSER::Rash::Functions
|
98
|
+
call_args
|
99
|
+
end # .function_names
|
100
|
+
|
101
|
+
|
102
|
+
# stub out all the singleton methods under {NRSER::Rash::Functions}
|
103
|
+
def self.function_map
|
104
|
+
results = []
|
105
|
+
# method to recursively stub singleton functions in a module
|
106
|
+
from_module = lambda do |mod|
|
107
|
+
# when the name is split, 'Rash' and 'Functions' take up the
|
108
|
+
# first two elements, so drop those to get the namespace
|
109
|
+
# as an array of strings
|
110
|
+
namespace = mod.name.split('::').drop(2)
|
111
|
+
# get each singleton method (`def self.*` style)
|
112
|
+
mod.singleton_methods.select {|method_name|
|
113
|
+
# throw out those that should not be stubbed
|
114
|
+
stub_function? mod, method_name
|
115
|
+
}.each do |method_name|
|
116
|
+
|
117
|
+
# the function name is the namespace plus the method name
|
118
|
+
# with segments seperated by `'.'`, ex:
|
119
|
+
#
|
120
|
+
# namespace = ['Nrser', Url']
|
121
|
+
# method_name = 'parse'
|
122
|
+
# function_name = 'Nrser.Url.parse'
|
123
|
+
#
|
124
|
+
# funcs << (namespace.clone << method_name)
|
125
|
+
function_name = stub_name namespace, method_name
|
126
|
+
|
127
|
+
call_arg = if namespace.empty?
|
128
|
+
method_name.to_s
|
129
|
+
else
|
130
|
+
"#{ namespace.join('.') }.#{ method_name }"
|
131
|
+
end
|
132
|
+
|
133
|
+
results << {'name' => function_name, 'sig' => call_arg}
|
134
|
+
end
|
135
|
+
|
136
|
+
# descend into submodules
|
137
|
+
mod.constants.map {|name|
|
138
|
+
mod.const_get(name)
|
139
|
+
}.select {|const|
|
140
|
+
# exclude any TestCase classes
|
141
|
+
# (const.is_a? Module) && (not const < Minitest::Test)
|
142
|
+
submodule? const
|
143
|
+
}.each {|submod|
|
144
|
+
from_module.call submod
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
from_module.call NRSER::Rash::Functions
|
149
|
+
results
|
150
|
+
end # .function_map
|
151
|
+
|
152
|
+
# @!endgroup Rash Function Class Methods
|
153
|
+
|
154
|
+
end # module NRSER::Rash
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Refinements
|
5
|
+
# =======================================================================
|
6
|
+
|
7
|
+
using NRSER
|
8
|
+
using NRSER::Types
|
9
|
+
|
10
|
+
|
11
|
+
# Definitions
|
12
|
+
# =======================================================================
|
13
|
+
|
14
|
+
# Helpful and not so helpful things.
|
15
|
+
#
|
16
|
+
module NRSER::Rash::Helpers
|
17
|
+
|
18
|
+
include SemanticLogger::Loggable
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def quote(value)
|
22
|
+
double_quote(value)
|
23
|
+
end
|
24
|
+
alias_method :q, :quote
|
25
|
+
|
26
|
+
# single-quote a string for bash
|
27
|
+
# reaplces `'` with `'\''`
|
28
|
+
def single_quote(string)
|
29
|
+
"'" + string.gsub(/'/, {"'" => "'\\''"}) + "'"
|
30
|
+
end
|
31
|
+
alias_method :sq, :single_quote
|
32
|
+
|
33
|
+
# double-quote a string for bash
|
34
|
+
# replaces `"` with `\"` and `\` with `\\`
|
35
|
+
def double_quote(string)
|
36
|
+
'"' + string.gsub(/["\\]/, {'"' => '\"', '\\' => '\\\\'}) + '"'
|
37
|
+
end
|
38
|
+
alias_method :dq, :double_quote
|
39
|
+
|
40
|
+
def block(start, finish, &body)
|
41
|
+
$stdout.block start, finish, &body
|
42
|
+
end
|
43
|
+
|
44
|
+
def user name = nil, &body
|
45
|
+
# if no name is provided, it just means 'not root'
|
46
|
+
if name.nil?
|
47
|
+
body.() if ENV['USER'] != 'root'
|
48
|
+
else
|
49
|
+
body.() if ENV['USER'] == name
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end # class << self
|
53
|
+
end # module NRSER::Rash::Helpers
|
@@ -0,0 +1,305 @@
|
|
1
|
+
require 'minitest'
|
2
|
+
|
3
|
+
module NRSER::Rash
|
4
|
+
|
5
|
+
# @!group Testing Class Methods
|
6
|
+
# ==========================================================================
|
7
|
+
|
8
|
+
# @todo
|
9
|
+
# It seems like testing doesn't work in the state I came back to it
|
10
|
+
# 2018.02.22
|
11
|
+
#
|
12
|
+
#
|
13
|
+
# runs tests declared for functions using the `_test_case` and
|
14
|
+
# `_test_functions` macros. this is hackety-hack-hackety.
|
15
|
+
#
|
16
|
+
# rational:
|
17
|
+
#
|
18
|
+
# i'm using `Test::Unit`. because it comes with the stdlib. `Test::Unit`
|
19
|
+
# looks to be based on [MiniTest][https://github.com/seattlerb/minitest],
|
20
|
+
# but i can't find great docs on using that either, and i though the
|
21
|
+
# `Test::Unit` API might be better known, so i went with that.
|
22
|
+
#
|
23
|
+
# the only way i can really find using `Test::Unit` documented is
|
24
|
+
# to `require 'test/unit'`, which runs all declared `Test::Unit::TestCase`
|
25
|
+
# subclasses, reading options off the command line and spitting results
|
26
|
+
# back to `STDOUT`.
|
27
|
+
#
|
28
|
+
# there is an optional `--name <pattern>` arg that you can supply on the
|
29
|
+
# command line when invoking a script with a `require 'test/unit' line
|
30
|
+
# in it, but it seems like it only matches against method names, not
|
31
|
+
# `TestCase` subclasses or anything. under this assumption, the necessary
|
32
|
+
# pattern would need to be a part of all test method names. and i don't
|
33
|
+
# really want a ton of method names like `test_project_dir_name_space_sub`
|
34
|
+
# so that i can turn `rash test Project.dir_name` into a pattern that
|
35
|
+
# runs the {NRSER::Rash::Functions::Project.dir_name} tests.
|
36
|
+
#
|
37
|
+
# the hack:
|
38
|
+
#
|
39
|
+
# this gets around it by providing macros that will dynamically define
|
40
|
+
# `Test::Unit::TestCase` subclasses if and only if those tests are being
|
41
|
+
# run.
|
42
|
+
#
|
43
|
+
# NOTE: why does this start with an '_'?
|
44
|
+
def self._test_function(module_or_function_name)
|
45
|
+
# if the *first* arg to `rash test` is `--all`, then all test will be run,
|
46
|
+
# which is done by supplying an empty `module_or_function_name` to
|
47
|
+
# `Testing.start`.
|
48
|
+
#
|
49
|
+
# TODO: I just realized that it's currently impossible to test all the
|
50
|
+
# functions defined in {NRSER::Rash::Functions} without testing all
|
51
|
+
# the submodules as well. ugh. solutions include requiring an
|
52
|
+
# explicit (never finished I guess...)
|
53
|
+
#
|
54
|
+
#
|
55
|
+
if module_or_function_name == '--all'
|
56
|
+
module_or_function_name = ''
|
57
|
+
end
|
58
|
+
NRSER::Rash::Testing.start module_or_function_name
|
59
|
+
# going to need the functions loaded to find it
|
60
|
+
load_functions
|
61
|
+
if NRSER::Rash::Testing._test_cases.length == 0
|
62
|
+
raise NRSER::Rash::Testing::NoTestCasesError.new(module_or_function_name)
|
63
|
+
end
|
64
|
+
require 'minitest/autorun'
|
65
|
+
end
|
66
|
+
end # module NRSER::Rash
|
67
|
+
|
68
|
+
# @!endgroup Testing Class Methods
|
69
|
+
|
70
|
+
|
71
|
+
# @todo
|
72
|
+
# It seems like testing doesn't work in the state I came back to it
|
73
|
+
# 2018.02.22
|
74
|
+
#
|
75
|
+
module NRSER::Rash::Testing
|
76
|
+
class << self
|
77
|
+
attr_accessor :module_or_function_name
|
78
|
+
attr_accessor :_test_cases
|
79
|
+
attr_accessor :ref_path
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.test
|
83
|
+
NRSER::Rash.logger.info "self: #{self.inspect}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.start(module_or_function_name)
|
87
|
+
|
88
|
+
define_test_class
|
89
|
+
|
90
|
+
self.module_or_function_name = module_or_function_name
|
91
|
+
self.ref_path = NRSER::Rash.ref_path(module_or_function_name)
|
92
|
+
self._test_cases = []
|
93
|
+
end
|
94
|
+
|
95
|
+
# used to figure out if we're testing
|
96
|
+
def self.testing?
|
97
|
+
!!module_or_function_name
|
98
|
+
end
|
99
|
+
|
100
|
+
# raised when filtering byt the function name doens't produce any
|
101
|
+
# test cases
|
102
|
+
class NoTestCasesError < StandardError
|
103
|
+
def initialize(name)
|
104
|
+
super "no test cases were found for '#{ name }'."
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class FunctionTestCase < ::Minitest::Test
|
109
|
+
class Raises
|
110
|
+
attr_reader :cls, :msg
|
111
|
+
|
112
|
+
def initialize cls, msg = nil
|
113
|
+
@cls = cls
|
114
|
+
@msg = msg
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def raises cls, msg = nil
|
119
|
+
Raises.new cls, msg
|
120
|
+
end
|
121
|
+
|
122
|
+
def assert_map(hash)
|
123
|
+
hash.each do |input, output|
|
124
|
+
input = [input] unless input.is_a?(Array)
|
125
|
+
# allow mapping to an Exception class as an assert_raise
|
126
|
+
if output.is_a?(Raises)
|
127
|
+
if output.msg.nil?
|
128
|
+
assert_raise output.cls do
|
129
|
+
apply_target *input
|
130
|
+
end
|
131
|
+
else
|
132
|
+
assert_raise_with_message(output.cls, output.msg) do
|
133
|
+
apply_target *input
|
134
|
+
end
|
135
|
+
end
|
136
|
+
else
|
137
|
+
assert_equal output, apply_target(*input)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# this was added sometime after 1.9.3, backport:
|
143
|
+
def assert_raise_with_message(exception, expected, msg = nil, &block)
|
144
|
+
case expected
|
145
|
+
when String
|
146
|
+
assert = :assert_equal
|
147
|
+
when Regexp
|
148
|
+
assert = :assert_match
|
149
|
+
else
|
150
|
+
raise TypeError, "Expected #{expected.inspect} to be a kind of String or Regexp, not #{expected.class}"
|
151
|
+
end
|
152
|
+
|
153
|
+
ex = assert_raise(exception, *msg) {yield}
|
154
|
+
msg = message(msg, "") {"Expected Exception(#{exception}) was raised, but the message doesn't match"}
|
155
|
+
|
156
|
+
if assert == :assert_equal
|
157
|
+
assert_equal(expected, ex.message, msg)
|
158
|
+
else
|
159
|
+
msg = message(msg) { "Expected #{mu_pp expected} to match #{mu_pp ex.message}" }
|
160
|
+
assert expected =~ ex.message, msg
|
161
|
+
block.binding.eval("proc{|_|$~=_}").call($~)
|
162
|
+
end
|
163
|
+
ex
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# create and run a `Minitest::Test` with `&block` as the body,
|
168
|
+
# supplying `target_method` as an instance method under it's name
|
169
|
+
# and also the name 'target_method'
|
170
|
+
def self.test_case(target_method, &block)
|
171
|
+
# bail out if we're not in a testing state. this prevents the code
|
172
|
+
# from going any further for other commands like `profile` and `call`.
|
173
|
+
return unless NRSER::Rash::Testing.testing?
|
174
|
+
|
175
|
+
method_name = target_method.name.to_s
|
176
|
+
|
177
|
+
# since we're testing, `Testing.pattern` will be a string the user
|
178
|
+
# supplied on the command line, like `Project.dir_name`. we're going
|
179
|
+
# to compare it to the method path we're being asked to define
|
180
|
+
# the test case for to see if we should acutally create the
|
181
|
+
# `Minitest::Test` class.
|
182
|
+
method_ref_path = NRSER::Rash.ref_path(target_method.receiver.name,
|
183
|
+
target_method.name.to_s)[2..-1]
|
184
|
+
|
185
|
+
# go through each segment in the ref path we're testing and bail if
|
186
|
+
# it doesn't match the coresponding segment in the method's ref path.
|
187
|
+
#
|
188
|
+
# this only goes up until the testing ref path runs out, which allows
|
189
|
+
# the user to specify something like `Url.Parse` to test all the
|
190
|
+
# functions under the `NRSER::Rash::Functions::Url::Parse` module.
|
191
|
+
Testing.ref_path.each_with_index do |segment, index|
|
192
|
+
return unless segment == method_ref_path[index]
|
193
|
+
end
|
194
|
+
|
195
|
+
# if we made it to this point, we should be testing the function and
|
196
|
+
# will define the `Test::Unit` subclass:
|
197
|
+
_test_case = Class.new NRSER::Rash::Testing::FunctionTestCase do
|
198
|
+
|
199
|
+
# allow easy access to the target method inside the test methods
|
200
|
+
# by defining a method with the same name that points
|
201
|
+
# to the target method
|
202
|
+
define_method method_name, &target_method
|
203
|
+
|
204
|
+
# the proxy method should be private so that functions that
|
205
|
+
# start with `'test'` aren't run by `Test::Unit`
|
206
|
+
private method_name
|
207
|
+
|
208
|
+
# also define a version named `apply_target` to provide a
|
209
|
+
# shortcut for programtic access in helpers like
|
210
|
+
# `FunctionTestCase.assert_map` and what not.
|
211
|
+
#
|
212
|
+
# NOTE: i did this instead of just using `self.class.target_method`
|
213
|
+
# as defined below because i wanted the method to be exactly
|
214
|
+
# the same as when calling with the previous alias. i might
|
215
|
+
# remove it, not sure. it seems redundant.
|
216
|
+
define_method :apply_target, &target_method
|
217
|
+
|
218
|
+
# and include a direct reference the target method in a class
|
219
|
+
# instance variable with an attribute reader so it's accessible
|
220
|
+
# in case it's needed at some point (it's not at the moment).
|
221
|
+
#
|
222
|
+
# it can be accessed from inside `FunctionTestCase` subclasses like:
|
223
|
+
#
|
224
|
+
# self.class.target_method
|
225
|
+
#
|
226
|
+
@target_method = target_method
|
227
|
+
class << self
|
228
|
+
attr_reader :target_method
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# i ran into some "warning: class variable access from toplevel" shit
|
233
|
+
# at some point, and this was a part of fixing it. though it no longer
|
234
|
+
# seems necessary, i'm going to leave it for a moment:
|
235
|
+
# _test_case.instance_eval do
|
236
|
+
# @test_method = test_method
|
237
|
+
# end
|
238
|
+
|
239
|
+
# add the user-supplied methods
|
240
|
+
_test_case.class_eval &block
|
241
|
+
|
242
|
+
# programtically create a name for the class and use that to create
|
243
|
+
# a constant referencing it in the invoking module, which causes the
|
244
|
+
# class to assume that name and module as far as it's `name` method
|
245
|
+
# and printing and such, which is nice for the unit test output.
|
246
|
+
#
|
247
|
+
# names are created by appending the `method_name` to 'Test_', with
|
248
|
+
# '!' converted to '_bang' and '?' converted to '_q' (since constants
|
249
|
+
# can't have '!' or '?' in them).
|
250
|
+
#
|
251
|
+
# example:
|
252
|
+
#
|
253
|
+
# say you had a module like
|
254
|
+
#
|
255
|
+
# module NRSER::Rash::Functions::SomeNamespace
|
256
|
+
# extend NRSER::Rash::Testing::Extensions
|
257
|
+
#
|
258
|
+
# def self.some_function
|
259
|
+
# "hooray!"
|
260
|
+
# end
|
261
|
+
#
|
262
|
+
# _test_case :some_function do
|
263
|
+
# def test_some_function
|
264
|
+
# assert_equal some_function, "horray!"
|
265
|
+
# end
|
266
|
+
# end
|
267
|
+
# end
|
268
|
+
#
|
269
|
+
# then you would get a `Minitest::Test` subclass named
|
270
|
+
#
|
271
|
+
# NRSER::Rash::Functions::SomeNamespace::Test_some_function
|
272
|
+
#
|
273
|
+
# which seems reasonable enough.
|
274
|
+
class_name = "Test_" +
|
275
|
+
method_name.to_s.gsub('!', '_bang').gsub('?', '_q')
|
276
|
+
const_set class_name, _test_case
|
277
|
+
|
278
|
+
# and finally, add the class to the `_test_cases` array, which allows
|
279
|
+
# us to see what classes were defined after the modules are loaded.
|
280
|
+
NRSER::Rash::Testing._test_cases << _test_case
|
281
|
+
end
|
282
|
+
|
283
|
+
# create a `Minitest::Test` subclass with a single test method
|
284
|
+
# for `target_method` with `&block` as the body.
|
285
|
+
def self.test_function(target_method, &block)
|
286
|
+
test_case target_method do
|
287
|
+
define_method "test_#{ target_method.name }", &block
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def self.temp_env hash, &block
|
292
|
+
old = Hash[hash.keys.map {|key| ENV[key] }]
|
293
|
+
begin
|
294
|
+
hash.each do |key, value|
|
295
|
+
ENV[key] = value
|
296
|
+
end
|
297
|
+
block.()
|
298
|
+
ensure
|
299
|
+
old.each do |key, value|
|
300
|
+
ENV[key] = value
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
end # NRSER::Rash::Testing
|