nrser-rash 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|