fun_with_gems 0.0.2 → 0.0.8
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 +5 -13
- data/.document +5 -0
- data/CHANGELOG.markdown +29 -0
- data/Gemfile +6 -11
- data/README.rdoc +125 -1
- data/ROADMAP.md +6 -0
- data/Rakefile +15 -46
- data/VERSION +1 -1
- data/lib/fun_with/gems/api_extender.rb +46 -0
- data/lib/fun_with/gems/configuration_installer.rb +86 -0
- data/lib/fun_with/gems/constant_builder.rb +36 -0
- data/lib/fun_with/gems/core_extender.rb +65 -0
- data/lib/fun_with/gems/core_extensions/module.rb +9 -3
- data/lib/fun_with/gems/fun_gem_api.rb +62 -3
- data/lib/fun_with/gems/gem_api.rb +78 -47
- data/lib/fun_with/gems/inclusionizer.rb +34 -0
- data/lib/fun_with/gems/library_requirer.rb +54 -0
- data/lib/fun_with/gems/rake_class_methods.rb +111 -0
- data/lib/fun_with/gems/rakefile.rb +114 -0
- data/lib/fun_with/gems/root_setter.rb +19 -0
- data/lib/fun_with/gems/test_case_extender.rb +27 -0
- data/lib/fun_with/gems/testing/assertions.rb +22 -0
- data/lib/fun_with/gems/testing/gem_to_test_methods.rb +37 -0
- data/lib/fun_with/gems/testing/test_case_extensions.rb +39 -0
- data/lib/fun_with/gems/testing/test_results.rb +40 -0
- data/lib/fun_with/gems/testing/test_setup.rb +22 -0
- data/lib/fun_with/gems/testing/test_suite_runner.rb +28 -0
- data/lib/fun_with/gems/testing/validator.rb +52 -0
- data/lib/fun_with/gems/versionizer.rb +41 -0
- data/lib/fun_with_gems.rb +15 -14
- data/lib/tasks/fun_with/gems/publish.rake +8 -0
- data/lib/tasks/fun_with/gems/validate.rake +28 -0
- data/tasks/empty/empty.rake +6 -0
- data/tasks/empty/environment.rake +7 -0
- data/test/assertions.rb +15 -0
- data/test/data/test_gems/array_inherits_enumerable/VERSION +1 -0
- data/test/data/test_gems/array_inherits_enumerable/lib/array_inherits_enumerable/core_extensions/comparable.rb +9 -0
- data/test/data/test_gems/array_inherits_enumerable/lib/array_inherits_enumerable/core_extensions/enumerable.rb +10 -0
- data/test/data/test_gems/array_inherits_enumerable/lib/array_inherits_enumerable/core_extensions/numeric.rb +22 -0
- data/test/data/test_gems/array_inherits_enumerable/lib/array_inherits_enumerable.rb +1 -0
- data/test/data/test_gems/fun_with_llamas/lib/fun_with/llamas/gem_api.rb +10 -0
- data/test/data/test_gems/fun_with_llamas/lib/fun_with/llamas/llama.rb +40 -0
- data/test/data/test_gems/fun_with_llamas/lib/fun_with/llamas/trainer.rb +15 -0
- data/test/data/test_gems/integer_magic/VERSION +1 -0
- data/test/data/test_gems/integer_magic/config/gem_config.rb +4 -0
- data/test/data/test_gems/integer_magic/lib/integer_magic/core_extensions/integer.rb +28 -0
- data/test/data/test_gems/integer_magic/lib/integer_magic/core_extensions/numeric.rb +13 -0
- data/test/data/test_gems/integer_magic/lib/integer_magic.rb +1 -0
- data/test/helper.rb +9 -38
- data/test/test_core_extensions.rb +10 -0
- data/test/test_fun_with_gems.rb +9 -16
- data/test/test_library_requirer.rb +13 -0
- data/test/test_the_test_case.rb +24 -0
- data/test/test_the_test_gems.rb +152 -0
- metadata +123 -40
- data/lib/fun_with/gems/mechanic.rb +0 -27
- data/lib/fun_with/gems/validator.rb +0 -69
- data/test/test_gem/lib/fun_with/llamas/llama.rb +0 -9
- data/test/test_gem/lib/fun_with/llamas/trainer.rb +0 -9
- /data/test/{test_gem → data/test_gems/fun_with_llamas}/VERSION +0 -0
- /data/test/{test_gem → data/test_gems/fun_with_llamas}/lib/fun_with_llamas.rb +0 -0
|
@@ -9,74 +9,105 @@ module FunWith
|
|
|
9
9
|
#
|
|
10
10
|
# Configurable options:
|
|
11
11
|
# While all these things are handled by default, some things can be overridden
|
|
12
|
-
# :main_lib_file => use a different filepath to calculate the root
|
|
13
|
-
#
|
|
14
12
|
# :root => or render :main_lib_file moot by declaring a different root.
|
|
15
13
|
#
|
|
16
14
|
# :version => Declare a different version string for the gem.
|
|
17
15
|
#
|
|
18
16
|
# :require => false (avoids requiring the default lib/fun_with dir.)
|
|
19
17
|
# :require => filepath or array of filepaths (require these things instead (note: not in addition to))
|
|
18
|
+
# :core_extensions => false (don't autoload Gem::CoreExtension modules)
|
|
19
|
+
# (note that it still checks to see if the module's already been included)
|
|
20
|
+
#
|
|
21
|
+
# :main_lib_file => use a different filepath to calculate the root (defaults to <GEM_ROOT>/)
|
|
22
|
+
# :configuration => nil (tries to load configuration from <GEM_ROOT>/config/gem_config.rb, if such a file exists)
|
|
23
|
+
# (String) --> assumes it's been given a filename
|
|
24
|
+
# (Hash) --> converts to a FunWith::Configurations::Config
|
|
25
|
+
# (Config) --> uses as the configuration
|
|
26
|
+
# :skip --> don't bother installing a configuration
|
|
27
|
+
#
|
|
28
|
+
# If successful, the configuration will be accessible from <GEM_CONST>.config
|
|
20
29
|
def make_gem_fun( gem_const, opts = {} )
|
|
21
30
|
@caller_file = caller.first.gsub(/:\d+:.*/,'').fwf_filepath
|
|
22
31
|
@opts = opts
|
|
23
|
-
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@gem_const = build_gem_const( gem_const )
|
|
24
36
|
@gem_const.extend( FunGemAPI )
|
|
25
|
-
set_gem_root
|
|
26
|
-
set_gem_version
|
|
27
|
-
|
|
37
|
+
set_gem_root unless @opts[:set_root] == false
|
|
38
|
+
set_gem_version unless @opts[:set_version] == false
|
|
39
|
+
@gem_const.gem_verbose = opts[:verbose]
|
|
40
|
+
|
|
41
|
+
# false to skip requiring entirely
|
|
42
|
+
# an array to load both
|
|
43
|
+
require_libs unless @opts[:require] == false
|
|
44
|
+
|
|
45
|
+
extend_constant_with_gem_api unless @opts[:gem_api] == false
|
|
46
|
+
|
|
47
|
+
@gem_const.load_external_tasks # Nothing happens unless 'rake' gem is active
|
|
48
|
+
|
|
49
|
+
include_core_extensions unless @opts[:core_extensions] == false
|
|
50
|
+
|
|
51
|
+
# GemName.config.{configuration_settings} if applicable
|
|
52
|
+
# Only runs if "fun_with_configurations" is required prior to
|
|
53
|
+
# calling files. Really starting to wonder about that. Should fwc
|
|
54
|
+
# stop depending on
|
|
55
|
+
install_gem_configuration unless @opts[:configuration] == :skip
|
|
56
|
+
|
|
57
|
+
extend_test_case
|
|
58
|
+
|
|
59
|
+
@gem_const
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def inclusionize( base )
|
|
63
|
+
FunWith::Gems::Inclusionizer.inclusionize( base )
|
|
28
64
|
end
|
|
29
65
|
|
|
30
66
|
protected
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
if gem_const.is_a?( String )
|
|
34
|
-
#create the module
|
|
35
|
-
const = Object
|
|
36
|
-
full_const_name = ""
|
|
37
|
-
gem_const.split("::").each do |module_name|
|
|
38
|
-
full_const_name << "::" unless full_const_name.fwf_blank?
|
|
39
|
-
full_const_name << module_name
|
|
40
|
-
|
|
41
|
-
if eval( "defined?(#{full_const_name})")
|
|
42
|
-
const = eval( full_const_name )
|
|
43
|
-
else
|
|
44
|
-
const = const.const_set( module_name, Module.new )
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
@gem_const = eval( gem_const )
|
|
49
|
-
else
|
|
50
|
-
@gem_const = gem_const
|
|
51
|
-
end
|
|
67
|
+
def build_gem_const( gem_const )
|
|
68
|
+
ConstantBuilder.build_constant( gem_const )
|
|
52
69
|
end
|
|
53
70
|
|
|
54
71
|
def set_gem_root
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
# Hence, the "make_gem_fun()" directive should be called in the lib/gem_name.rb file.
|
|
58
|
-
main_lib_file = @opts[:main_lib_file] || @caller_file
|
|
59
|
-
root = @opts[:root] || main_lib_file.fwf_filepath.expand.dirname.up
|
|
60
|
-
|
|
61
|
-
Files::RootPath.rootify( @gem_const, root )
|
|
72
|
+
RootSetter.set_root( @gem_const, @caller_file, @opts )
|
|
62
73
|
end
|
|
63
|
-
|
|
74
|
+
|
|
64
75
|
def set_gem_version
|
|
65
|
-
|
|
66
|
-
if @opts[:version]
|
|
67
|
-
VersionStrings.versionize( @gem_const, @opts[:version] )
|
|
68
|
-
else
|
|
69
|
-
VersionStrings.versionize( @gem_const )
|
|
70
|
-
end
|
|
76
|
+
Versionizer.versionize( @gem_const, @opts[:version] )
|
|
71
77
|
end
|
|
72
78
|
|
|
73
79
|
def require_libs
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
opts = just_options( @opts, :require, :main_lib_file ).merge( :caller => @caller_file )
|
|
81
|
+
LibraryRequirer.require( @gem_const, opts )
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def extend_constant_with_gem_api
|
|
85
|
+
ApiExtender.extend_with_api( @gem_const )
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Files in <GEM_ROOT>/lib/core_extensions get included in their corresponding core class?
|
|
89
|
+
def include_core_extensions
|
|
90
|
+
CoreExtender.extend_core( @gem_const )
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Install a configuration given as an argument,
|
|
94
|
+
# or install the default config/gem_config.rb if such a file exists
|
|
95
|
+
def install_gem_configuration
|
|
96
|
+
opts = just_options( @opts, :configuration )
|
|
97
|
+
ConfigurationInstaller.install_configuration( @gem_const, opts )
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @gem_const::Testing::TestCaseExtensions should already be loaded
|
|
101
|
+
# if it exists. Uses it to extend FunWith::Testing::TestCase
|
|
102
|
+
def extend_test_case
|
|
103
|
+
TestCaseExtender.extend_test_case( @gem_const )
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
protected
|
|
107
|
+
def just_options( opts, *args )
|
|
108
|
+
{}.tap do |return_opts|
|
|
109
|
+
for arg in args
|
|
110
|
+
return_opts[arg] = opts[arg].dup if opts.has_key?( arg )
|
|
80
111
|
end
|
|
81
112
|
end
|
|
82
113
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
module Inclusionizer
|
|
4
|
+
def self.inclusionize( base )
|
|
5
|
+
base.send( :include, self )
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.included( base )
|
|
9
|
+
# overwrite the base class's self.included()
|
|
10
|
+
base.send( :extend, self::SelfIncludedMethod )
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module SelfIncludedMethod
|
|
14
|
+
def included( base )
|
|
15
|
+
__self = self
|
|
16
|
+
|
|
17
|
+
if base.is_a?(Module)
|
|
18
|
+
base.module_eval do
|
|
19
|
+
extend __self::ClassMethods if defined?( __self::ClassMethods )
|
|
20
|
+
include __self::InstanceMethods if defined?( __self::InstanceMethods )
|
|
21
|
+
include __self::Constants if defined?( __self::Constants )
|
|
22
|
+
end
|
|
23
|
+
elsif base.is_a?(Class)
|
|
24
|
+
base.class_eval do
|
|
25
|
+
extend __self::ClassMethods if defined?( __self::ClassMethods )
|
|
26
|
+
include __self::InstanceMethods if defined?( __self::InstanceMethods )
|
|
27
|
+
include __self::Constants if defined?( __self::Constants )
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Create new modules if necessary.
|
|
2
|
+
module FunWith
|
|
3
|
+
module Gems
|
|
4
|
+
class LibraryRequirer
|
|
5
|
+
def self.require( *args, &block )
|
|
6
|
+
self.new.require( *args, &block )
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def require( const, opts )
|
|
10
|
+
caller_file = opts[:caller] || guess_caller_file_name( const )
|
|
11
|
+
files_to_require = const.root( "lib" ).glob(:all, :recursive => false) - [ caller_file ]
|
|
12
|
+
files_to_require.flatten!
|
|
13
|
+
|
|
14
|
+
for file in files_to_require
|
|
15
|
+
file.requir
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def guess_caller_file( const )
|
|
20
|
+
if const.respond_to?(:root)
|
|
21
|
+
const_name = constant_name_to_filename( const.name )
|
|
22
|
+
"lib/" + const_name
|
|
23
|
+
else
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# We're guessing. It doesn't have to be perfect, but perfect 99% of the time would be nice
|
|
29
|
+
def constant_name_to_filename( cname )
|
|
30
|
+
cname.split("::").map{ |chunk|
|
|
31
|
+
buffer = []
|
|
32
|
+
chunk.length.times do |i|
|
|
33
|
+
char = chunk[i]
|
|
34
|
+
next_char = chunk[i+1] || :eof
|
|
35
|
+
|
|
36
|
+
cap_letter = char == char.upcase
|
|
37
|
+
next_cap_letter = next_char == next_char.upcase
|
|
38
|
+
|
|
39
|
+
if cap_letter && ! next_cap_letter && i > 0
|
|
40
|
+
buffer << "_"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
buffer << char
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# chunk.gsub( /(.)([A-Z])/ ){ $1 + "_" + $2 }.downcase
|
|
47
|
+
buffer.join("").downcase
|
|
48
|
+
|
|
49
|
+
}.join("/") + ".rb"
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
module RakeClassMethods
|
|
4
|
+
attr_accessor :gem
|
|
5
|
+
|
|
6
|
+
def setup this_gem, rake_main
|
|
7
|
+
set_gem this_gem
|
|
8
|
+
set_rake_main rake_main
|
|
9
|
+
run_bundler_setup
|
|
10
|
+
|
|
11
|
+
# Internal tasks are set up in the Rakefile.
|
|
12
|
+
# External tasks (visible to the gems that depend on your fungem) are setup during the normal gem setup, if the 'rake' gem is present.
|
|
13
|
+
get_gem.load_internal_tasks
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def set_gem g
|
|
17
|
+
@gem = g
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def get_gem
|
|
21
|
+
@gem
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def set_rake_main m
|
|
25
|
+
@rake_main = m
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def run_bundler_setup
|
|
29
|
+
all_requirements
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
Bundler.setup(:default, :development)
|
|
33
|
+
rescue Bundler::BundlerError => e
|
|
34
|
+
$stderr.puts e.message
|
|
35
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
|
36
|
+
exit e.status_code
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def specification &block
|
|
41
|
+
Juwelier::Tasks.new do |gem|
|
|
42
|
+
yield gem
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def setup_gem_boilerplate
|
|
47
|
+
run_in_rakefile do
|
|
48
|
+
Juwelier::RubygemsDotOrgTasks.new
|
|
49
|
+
|
|
50
|
+
Rake::TestTask.new(:test) do |test|
|
|
51
|
+
test.libs << 'lib' << 'test'
|
|
52
|
+
test.pattern = 'test/**/test_*.rb'
|
|
53
|
+
test.verbose = true
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
desc "Code coverage detail"
|
|
57
|
+
task :simplecov do
|
|
58
|
+
ENV['COVERAGE'] = "true"
|
|
59
|
+
Rake::Task['test'].execute
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
task :default => :test
|
|
63
|
+
|
|
64
|
+
Rake::RDocTask.new do |rdoc|
|
|
65
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
|
66
|
+
|
|
67
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
68
|
+
rdoc.title = "fun_with_gems #{version}"
|
|
69
|
+
rdoc.rdoc_files.include('README*')
|
|
70
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def all_requirements
|
|
76
|
+
run_in_rakefile do
|
|
77
|
+
require 'rake'
|
|
78
|
+
require 'juwelier'
|
|
79
|
+
require 'rdoc/task'
|
|
80
|
+
require 'rake/testtask'
|
|
81
|
+
require 'bundler'
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def run_in_rakefile &block
|
|
86
|
+
if @rake_main.nil?
|
|
87
|
+
raise "Did you forget the line FunWith::Gems::Rakefile.set_rake_main by any chance?"
|
|
88
|
+
elsif ! block_given?
|
|
89
|
+
raise ArgumentError.new("Block must be given")
|
|
90
|
+
else
|
|
91
|
+
@rake_main.instance_eval( &block )
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def gem_files( *args, &block )
|
|
96
|
+
Dir.glob( File.join( ".", "lib", "**", "*.rb" ) ) +
|
|
97
|
+
Dir.glob( File.join( ".", "test", "**", "*.*" ) ) +
|
|
98
|
+
[ "Gemfile",
|
|
99
|
+
"Rakefile",
|
|
100
|
+
"LICENSE.txt",
|
|
101
|
+
"README.rdoc",
|
|
102
|
+
"VERSION"
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
module Rakefile
|
|
4
|
+
attr_accessor :gem
|
|
5
|
+
|
|
6
|
+
def rakefile_setup this_gem # , rake_main
|
|
7
|
+
self.gem = this_gem
|
|
8
|
+
|
|
9
|
+
# set_rake_main rake_main
|
|
10
|
+
run_bundler_setup
|
|
11
|
+
|
|
12
|
+
# Internal tasks are set up in the Rakefile.
|
|
13
|
+
# External tasks (visible to the gems that depend on your fungem) are setup during the normal gem setup, if the 'rake' gem is present.
|
|
14
|
+
self.gem.load_internal_tasks
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# def set_rake_main m
|
|
18
|
+
# @rake_main = m
|
|
19
|
+
# end
|
|
20
|
+
|
|
21
|
+
def run_bundler_setup
|
|
22
|
+
all_requirements
|
|
23
|
+
|
|
24
|
+
begin
|
|
25
|
+
Bundler.setup(:default, :development)
|
|
26
|
+
rescue Bundler::BundlerError => e
|
|
27
|
+
$stderr.puts e.message
|
|
28
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
|
29
|
+
exit e.status_code
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def gem_specification &block
|
|
34
|
+
Juwelier::Tasks.new do |gem|
|
|
35
|
+
yield gem
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def setup_gem_boilerplate
|
|
41
|
+
# run_in_rakefile do
|
|
42
|
+
Juwelier::RubygemsDotOrgTasks.new
|
|
43
|
+
|
|
44
|
+
Rake::TestTask.new(:test) do |test|
|
|
45
|
+
test.libs << 'lib' << 'test'
|
|
46
|
+
test.pattern = 'test/**/test_*.rb'
|
|
47
|
+
test.verbose = true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
desc "Code coverage detail"
|
|
51
|
+
task :simplecov do
|
|
52
|
+
ENV['COVERAGE'] = "true"
|
|
53
|
+
Rake::Task['test'].execute
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
task :default => :test
|
|
57
|
+
|
|
58
|
+
Rake::RDocTask.new do |rdoc|
|
|
59
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
|
60
|
+
|
|
61
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
62
|
+
rdoc.title = "fun_with_gems #{version}"
|
|
63
|
+
rdoc.rdoc_files.include('README*')
|
|
64
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
65
|
+
end
|
|
66
|
+
# end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def all_requirements
|
|
70
|
+
# run_in_rakefile do
|
|
71
|
+
require 'rake'
|
|
72
|
+
require 'juwelier'
|
|
73
|
+
|
|
74
|
+
begin
|
|
75
|
+
require 'rdoc/task'
|
|
76
|
+
rescue ArgumentError
|
|
77
|
+
# warn( "what's up with this error when loading RDoc?" )
|
|
78
|
+
require 'rdoc'
|
|
79
|
+
require 'rdoc/task'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
require 'rake/testtask'
|
|
83
|
+
require 'bundler'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def add_specification_files( gem_specification, *args )
|
|
88
|
+
root = "".fwf_filepath
|
|
89
|
+
|
|
90
|
+
for arg in args
|
|
91
|
+
case arg
|
|
92
|
+
when :default
|
|
93
|
+
files = []
|
|
94
|
+
files += root.join( :bin ).glob
|
|
95
|
+
files += root.join( :config ).glob
|
|
96
|
+
files += root.join( :examples ).glob
|
|
97
|
+
files += [ "Gemfile", "Rakefile", "VERSION" ]
|
|
98
|
+
files += root.join( :lib ).glob( :all, :ext => :rb )
|
|
99
|
+
files += root.join( :lib ).glob( :all, :ext => :rake )
|
|
100
|
+
files += root.join( :test ).glob
|
|
101
|
+
files += root.entries.select{|p| p.path =~ /^LICENSE\./ }
|
|
102
|
+
files += root.entries.select{|p| p.path =~ /^CHANGELOG\./ }
|
|
103
|
+
files += root.entries.select{|p| p.path =~ /^README\./ }
|
|
104
|
+
files += root.entries.select{|p| p.path =~ /^CODE_OF_CONDUCT\./ }
|
|
105
|
+
|
|
106
|
+
gem_specification.files += files.flatten.compact
|
|
107
|
+
else
|
|
108
|
+
gem_specification.files += root.glob( arg )
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
class RootSetter
|
|
4
|
+
def self.set_root( *args, &block )
|
|
5
|
+
self.new.set_root( *args, &block )
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def set_root( gem_const, caller_file, opts = {} )
|
|
9
|
+
# Hence, the "make_gem_fun()" directive should be called in the lib/gem_name.rb file.
|
|
10
|
+
main_lib_file = opts[:main_lib_file] || caller_file
|
|
11
|
+
root = opts.fetch(:root){ main_lib_file.fwf_filepath.expand.dirname.up }
|
|
12
|
+
|
|
13
|
+
Files::RootPath.rootify( gem_const, root )
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
# If the gem has a ::Testing::TestCaseExtensions module, (<GEM_ROOT>/lib/<GEM_NAME>/testing/test_case_extensions.rb)
|
|
4
|
+
# include the module in FunWith::Testing::TestCase
|
|
5
|
+
#
|
|
6
|
+
# Best practice: reserve the TestCaseExtensions module for methods that you want to be available to any gem that
|
|
7
|
+
# includes the gem being extended.
|
|
8
|
+
class TestCaseExtender
|
|
9
|
+
def self.extend_test_case( *args, &block )
|
|
10
|
+
self.new.extend_test_case( *args, &block )
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# If the caller doesn't specify a class to be extended,
|
|
14
|
+
# assumes the target is FunWith::Testing::TestCase
|
|
15
|
+
def extend_test_case( gem_const, test_case_class = nil )
|
|
16
|
+
if test_case_class.nil?
|
|
17
|
+
return false unless defined?( FunWith::Testing::TestCase )
|
|
18
|
+
test_case_class = FunWith::Testing::TestCase
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if defined?( gem_const::Testing::TestCaseExtensions )
|
|
22
|
+
test_case_class.extend( gem_const::Testing::TestCaseExtensions )
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
module Testing
|
|
4
|
+
module Assertions
|
|
5
|
+
# Puts a gem through its paces
|
|
6
|
+
def assert_gem_is_fine( gem )
|
|
7
|
+
flunk
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def assert_fun_gem( gem )
|
|
11
|
+
assert_kind_of( Module, gem )
|
|
12
|
+
assert_respond_to gem, :is_fun_gem?
|
|
13
|
+
assert gem.is_fun_gem?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def assert_version( gem, version )
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
module Testing
|
|
4
|
+
module GemToTestMethods
|
|
5
|
+
# TODO: should use Inclusionizer?
|
|
6
|
+
def self.included( klass )
|
|
7
|
+
klass.extend( ClassMethods )
|
|
8
|
+
klass.extend( Constants )
|
|
9
|
+
klass.send( :include, InstanceMethods )
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
module ClassMethods
|
|
14
|
+
# What FunWith::Gems - derived gem is being tested? check as far up the class tree as needed.
|
|
15
|
+
def gem_to_test
|
|
16
|
+
@gem_to_test ||= nil
|
|
17
|
+
rval = @gem_to_test
|
|
18
|
+
rval = self.superclass.gem_to_test if !rval && self.superclass.respond_to?( :gem_to_test )
|
|
19
|
+
rval
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attr_writer :gem_to_test
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module InstanceMethods
|
|
26
|
+
def gem_to_test
|
|
27
|
+
self.class.gem_to_test
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
module Constants
|
|
32
|
+
GEM_TO_TEST_METHODS_LOADED = true
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
module Testing
|
|
4
|
+
# Extensions to the FunWith::Testing::TestCase class.
|
|
5
|
+
module TestCaseExtensions
|
|
6
|
+
# config options
|
|
7
|
+
# :factory_bot => true : load FactoryBot factory definitions from the places FactoryBot expects them to live.
|
|
8
|
+
# :include => true : include the namespace of the gem being tested.
|
|
9
|
+
def make_testing_fun( testable_gem, config = {} )
|
|
10
|
+
include GemToTestMethods
|
|
11
|
+
install_basic_assertions # The assertions included by FunWith::Testing
|
|
12
|
+
install_gem_assertions # The assertions included by FunWith::Gems
|
|
13
|
+
install_yet_more_assertions( testable_gem )
|
|
14
|
+
|
|
15
|
+
self.gem_to_test = testable_gem
|
|
16
|
+
|
|
17
|
+
self.add_factorybot_support if config[:factory_bot] == true
|
|
18
|
+
self.send( :include, self.gem_to_test ) if config[:include] == true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def install_gem_assertions
|
|
22
|
+
include FunWith::Gems::Testing::Assertions
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def install_yet_more_assertions( testable_gem )
|
|
26
|
+
if testable_gem.respond_to?( :root )
|
|
27
|
+
f = testable_gem.root( :test, "assertions.rb" )
|
|
28
|
+
|
|
29
|
+
require f if f.file?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if defined?( testable_gem::Testing::Assertions )
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
module Testing
|
|
4
|
+
class TestResults
|
|
5
|
+
TEST_SUITE_DATA_REGEX = /(?<tests>\d+) (?:tests|runs), (?<assertions>\d+) assertions, (?<failures>\d+) failures, (?<errors>\d+) errors, (?<skips>\d+) skips/
|
|
6
|
+
|
|
7
|
+
attr_accessor :output, :test_results_found, :gem_const, :fail_count
|
|
8
|
+
|
|
9
|
+
def initialize g
|
|
10
|
+
self.gem_const = g
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def passed?
|
|
14
|
+
self.scan_test_results
|
|
15
|
+
self.test_results_found? && no_failures_or_errors?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_results_found?
|
|
19
|
+
self.test_results_found
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def no_failures_or_errors?
|
|
23
|
+
fail_count == 0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def scan_test_results
|
|
27
|
+
raise "No output to scan!" if self.output.nil?
|
|
28
|
+
|
|
29
|
+
if m = self.output.match( TEST_SUITE_DATA_REGEX )
|
|
30
|
+
self.test_results_found = true
|
|
31
|
+
self.fail_count = m[:failures].to_i + m[:errors].to_i
|
|
32
|
+
else
|
|
33
|
+
self.fail_count = -1
|
|
34
|
+
self.test_results_found = false
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module FunWith
|
|
2
|
+
module Gems
|
|
3
|
+
module Testing
|
|
4
|
+
class TestSetup
|
|
5
|
+
def self.setup( gem )
|
|
6
|
+
gem.gem_test_mode = true
|
|
7
|
+
require_test_libs( gem )
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.require_test_libs( gem )
|
|
11
|
+
return false unless gem.respond_to?(:root)
|
|
12
|
+
groot = gem.root
|
|
13
|
+
return false unless groot.is_a?( FunWith::Files::FilePath )
|
|
14
|
+
|
|
15
|
+
test_lib_dir = groot / :test / :lib
|
|
16
|
+
test_lib_dir.requir if test_lib_dir.directory?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|