micro-rb 0.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rubocop.yml +1399 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +5 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +11 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +204 -0
  11. data/Rakefile +12 -0
  12. data/bin/console +16 -0
  13. data/bin/microrb +7 -0
  14. data/bin/setup +8 -0
  15. data/lib/micro/cli.rb +69 -0
  16. data/lib/micro/configuration.rb +34 -0
  17. data/lib/micro/examples/proto/sum.proto +12 -0
  18. data/lib/micro/examples/proto/sum_pb.rb +21 -0
  19. data/lib/micro/examples/sum.rb +22 -0
  20. data/lib/micro/handler.rb +63 -0
  21. data/lib/micro/handler_manager.rb +60 -0
  22. data/lib/micro/handlers/debug.rb +26 -0
  23. data/lib/micro/project_generator.rb +75 -0
  24. data/lib/micro/proto/debug.proto +10 -0
  25. data/lib/micro/proto/debug_pb.rb +19 -0
  26. data/lib/micro/servers/error.rb +58 -0
  27. data/lib/micro/servers/web.rb +162 -0
  28. data/lib/micro/sidecar/base.rb +26 -0
  29. data/lib/micro/sidecar/call.rb +18 -0
  30. data/lib/micro/sidecar/register.rb +18 -0
  31. data/lib/micro/version.rb +6 -0
  32. data/lib/micro-rb.rb +4 -0
  33. data/lib/microrb.rb +25 -0
  34. data/micro-rb.gemspec +37 -0
  35. data/registry.png +0 -0
  36. data/sum.png +0 -0
  37. data/templates/Dockerfile +3 -0
  38. data/templates/Gemfile +18 -0
  39. data/templates/LICENSE +21 -0
  40. data/templates/README.md +17 -0
  41. data/templates/Rakefile +9 -0
  42. data/templates/bin/app +17 -0
  43. data/templates/lib/app/handlers/example_handler.rb +16 -0
  44. data/templates/lib/app/proto/sum.proto +12 -0
  45. data/templates/lib/app/proto/sum_pb.rb +21 -0
  46. data/templates/lib/app/version.rb +4 -0
  47. data/templates/lib/app.rb +14 -0
  48. data/templates/test/app_test.rb +11 -0
  49. data/templates/test/test_helper.rb +9 -0
  50. metadata +277 -0
@@ -0,0 +1,75 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'active_support/core_ext/string/inflections'
5
+ require 'fileutils'
6
+ require 'erb'
7
+
8
+ module MicroRb
9
+ class ProjectGenerator
10
+ attr_reader :name, :class_name, :username,
11
+ :year, :encryption, :active_record, :engine
12
+
13
+ def initialize(name, encryption, active_record)
14
+ @active_record = active_record
15
+ @class_name = name.classify
16
+ @encryption = encryption
17
+ @username = ENV['USERNAME'] || ENV['USER']
18
+ @name = name
19
+ @year = Time.new.year
20
+ @engine = RUBY_ENGINE == 'jruby' ? 'activerecord-jdbcmysql-adapter' : 'mysql2'
21
+ end
22
+
23
+ def create!
24
+ move_files
25
+ render_templates
26
+ install
27
+ end
28
+
29
+ private
30
+
31
+ def move_files
32
+ template_path = File.expand_path('../../../templates', __FILE__)
33
+
34
+ FileUtils.cp_r(template_path, name)
35
+ FileUtils.mv File.join(name, 'lib', 'app'), File.join(name, 'lib', name)
36
+ FileUtils.mv File.join(name, 'lib', 'app.rb'), File.join(name, 'lib', "#{name}.rb")
37
+ FileUtils.mv File.join(name, 'test', 'app_test.rb'),
38
+ File.join(name, 'test', "#{name}_test.rb")
39
+ FileUtils.mv File.join(name, 'bin', 'app'), File.join(name, 'bin', name)
40
+ FileUtils.chmod 'u=wrx', File.join(name, 'bin', name)
41
+ end
42
+
43
+ def render_templates
44
+ [
45
+ File.join(name, 'bin', name),
46
+ File.join(name, 'lib', "#{name}.rb"),
47
+ File.join(name, 'lib', name, 'version.rb'),
48
+ File.join(name, 'lib', name, 'handlers', 'example_handler.rb'),
49
+ File.join(name, 'lib', name, 'proto', 'sum_pb.rb'),
50
+ File.join(name, 'lib', name, 'proto', 'sum.proto'),
51
+ File.join(name, 'test', "#{name}_test.rb"),
52
+ File.join(name, 'README.md'),
53
+ File.join(name, 'LICENSE'),
54
+ File.join(name, 'Gemfile'),
55
+ File.join(name, 'Dockerfile')
56
+ ].each { |file| render_template(file, binding) }
57
+ end
58
+
59
+ def install
60
+ Dir.chdir(name) do
61
+ Bundler.with_clean_env do
62
+ system('bundle')
63
+ end
64
+ end
65
+ end
66
+
67
+ def render_template(template, context)
68
+ t = File.read(template)
69
+
70
+ File.open(template, 'w') do |f|
71
+ f << ERB.new(t, nil, '-').result(context)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,10 @@
1
+ syntax = "proto3";
2
+
3
+ package micro_rb.debug;
4
+
5
+ message Request {}
6
+
7
+ message Response {
8
+ // default: ok
9
+ string status = 1;
10
+ }
@@ -0,0 +1,19 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: debug.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message 'micro_rb.debug.Request' do
8
+ end
9
+ add_message 'micro_rb.debug.Response' do
10
+ optional :status, :string, 1
11
+ end
12
+ end
13
+
14
+ module MicroRb
15
+ module Debug
16
+ Request = Google::Protobuf::DescriptorPool.generated_pool.lookup('micro_rb.debug.Request').msgclass
17
+ Response = Google::Protobuf::DescriptorPool.generated_pool.lookup('micro_rb.debug.Response').msgclass
18
+ end
19
+ end
@@ -0,0 +1,58 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module MicroRb
5
+ module Servers
6
+ class Error < StandardError
7
+ attr_accessor :code, :message
8
+
9
+ def initialize(code, message)
10
+ self.code = code
11
+ self.message = message
12
+
13
+ super(message)
14
+ end
15
+
16
+ def to_h
17
+ { code: code, message: message }
18
+ end
19
+
20
+ class ParseError < Error
21
+ def initialize
22
+ super(-32_700, 'Invalid JSON was received by the server. '\
23
+ 'An error occurred on the server while parsing the JSON text.')
24
+ end
25
+ end
26
+
27
+ class InvalidParams < Error
28
+ def initialize
29
+ super(-32_602, 'Invalid method parameter(s).')
30
+ end
31
+ end
32
+
33
+ class ServerError < Error
34
+ def initialize(code, message)
35
+ super(code, message)
36
+ end
37
+ end
38
+
39
+ class InvalidRequest < Error
40
+ def initialize
41
+ super(-32_600, 'The JSON sent is not a valid Request object.')
42
+ end
43
+ end
44
+
45
+ class InternalError < Error
46
+ def initialize(e)
47
+ super(-32_603, "Internal server error: #{e}")
48
+ end
49
+ end
50
+
51
+ class MethodNotFound < Error
52
+ def initialize(method)
53
+ super(-32_601, "Method '#{method}' not found.")
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,162 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'rack'
5
+ require 'rack/request'
6
+ require 'rack/response'
7
+ require 'multi_json'
8
+
9
+ module MicroRb
10
+ module Servers
11
+ class Web
12
+ attr_accessor :host, :port, :show_errors, :debug, :metadata, :version
13
+ attr_accessor :handler_manager, :name, :node_id, :server
14
+
15
+ REQUIRED_TYPES = { method: [String], params: [Hash, Array],
16
+ id: [String, Integer, NilClass] }.freeze
17
+
18
+ REQUIRED_KEYS = ['method'].freeze
19
+
20
+ def initialize(name, opts = {})
21
+ self.port = opts.delete(:port) || 3000
22
+ self.host = opts.delete(:host) || '0.0.0.0'
23
+ self.metadata = opts.delete(:metadata) || {}
24
+ self.version = opts.delete(:version) || '0.0.1'
25
+ self.debug = opts.delete(:debug)
26
+ self.name = name
27
+ self.node_id = "#{name}-#{SecureRandom.uuid}"
28
+ self.handler_manager = MicroRb::HandlerManager.new
29
+
30
+ server_opts = opts.merge(Host: host, Port: port, app: self)
31
+ self.server = Rack::Server.new(server_opts)
32
+ end
33
+
34
+ def add_handler(handler)
35
+ handler_manager.add_handler(handler)
36
+ end
37
+
38
+ def start!
39
+ # Register the debug handler. This is kinda poor.
40
+ add_handler(MicroRb::Handlers::Debug.new)
41
+
42
+ # Value will raise an error on anything not 2XX
43
+ MicroRb::Sidecar::Register.notify(self).response.value
44
+
45
+ if debug
46
+ MicroRb.logger
47
+ .debug("Registered #{name}:#{host}:#{port} with sidecar.")
48
+ end
49
+
50
+ add_finalizer_hook!
51
+ server.start
52
+ rescue Net::HTTPFatalError => e
53
+ msg = "Sidecar error: #{e.message}"
54
+ MicroRb.logger.warn(msg)
55
+
56
+ raise MicroRb::Servers::Error::ServerError.new(-32_000, msg)
57
+ end
58
+
59
+ def to_h
60
+ {
61
+ version: version,
62
+ metadata: metadata,
63
+ name: name,
64
+ nodes: [{ id: node_id, address: host, port: port }],
65
+ endpoints: handler_manager.endpoints
66
+ }
67
+ end
68
+
69
+ def to_json
70
+ to_h.to_json
71
+ end
72
+
73
+ #
74
+ # Entry point for Rack
75
+ #
76
+ def call(env)
77
+ req = Rack::Request.new(env)
78
+ resp = Rack::Response.new
79
+
80
+ return resp.finish unless req.post?
81
+
82
+ resp.write process(req.body.read)
83
+ resp.finish
84
+ end
85
+
86
+ def process(content)
87
+ response = handle_request(content)
88
+
89
+ MultiJson.encode(response)
90
+ end
91
+
92
+ def create_response(request)
93
+ method = request['method'].strip.to_sym
94
+ params = request['params'].map(&:symbolize_keys!)
95
+
96
+ unless handler_manager.rpc_method?(method)
97
+ return error_response(Error::MethodNotFound.new(method), request)
98
+ end
99
+
100
+ rpc_method = handler_manager.rpc_method(method)
101
+ response = rpc_method.call(request: handler_manager.rpc_method_request(method, params),
102
+ response: handler_manager.rpc_method_response(method))
103
+
104
+ success_response(request, response)
105
+ end
106
+
107
+ def handle_request(request)
108
+ request = parse_request(request)
109
+ response = nil
110
+
111
+ begin
112
+ response = create_response(request) if valid_request?(request)
113
+ response ||= error_response(Error::InvalidRequest.new, request)
114
+ rescue MultiJson::ParseError => e
115
+ MicroRb.logger.warn(e)
116
+ response = error_response(Error::ParseError.new)
117
+ rescue StandardError => e
118
+ MicroRb.logger.warn(e)
119
+ response = error_response(Error::InternalError.new(e), request)
120
+ end
121
+
122
+ response
123
+ end
124
+
125
+ private
126
+
127
+ def valid_request?(request)
128
+ return false unless request.is_a?(Hash)
129
+
130
+ REQUIRED_KEYS.each do |key|
131
+ return false unless request.key?(key)
132
+ end
133
+
134
+ REQUIRED_TYPES.each do |key, types|
135
+ return false if request.key?(key) &&
136
+ types.none? { |type| request[key].is_a?(type) }
137
+ end
138
+
139
+ true
140
+ end
141
+
142
+ def success_response(request, result)
143
+ { result: result, id: request['id'] }
144
+ end
145
+
146
+ def error_response(error, request = {})
147
+ { error: error.to_h, id: request['id'] }
148
+ end
149
+
150
+ def add_finalizer_hook!
151
+ at_exit do
152
+ MicroRb.logger.debug("Shutting down #{name}:#{host}:#{port}") if debug
153
+ MicroRb::Sidecar::Register.remove(self)
154
+ end
155
+ end
156
+
157
+ def parse_request(request)
158
+ MultiJson.decode(request)
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'httparty'
5
+
6
+ module MicroRb
7
+ module Sidecar
8
+ module Base
9
+ extend ActiveSupport::Concern
10
+
11
+ CONTENT_TYPE = 'application/json'
12
+
13
+ included do
14
+ include HTTParty
15
+
16
+ def self.options(body)
17
+ { body: body.to_json, headers: { 'Content-Type' => CONTENT_TYPE } }
18
+ end
19
+
20
+ def self.registry_uri
21
+ MicroRb::Configuration.instance.sidecar_registry_uri
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module MicroRb
5
+ module Sidecar
6
+ class Call
7
+ include MicroRb::Sidecar::Base
8
+
9
+ def self.rpc(path, request)
10
+ post(path, options(request))
11
+ end
12
+
13
+ def self.http(path, request)
14
+ post(path, query: request)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module MicroRb
5
+ module Sidecar
6
+ class Register
7
+ include MicroRb::Sidecar::Base
8
+
9
+ def self.notify(service)
10
+ post(registry_uri, options(service))
11
+ end
12
+
13
+ def self.remove(service)
14
+ delete(registry_uri, options(service))
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,6 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module MicroRb
5
+ VERSION = '0.1.0.rc1'
6
+ end
data/lib/micro-rb.rb ADDED
@@ -0,0 +1,4 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'microrb'
data/lib/microrb.rb ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'active_support/all'
6
+ require 'semantic_logger'
7
+
8
+ module MicroRb
9
+ include SemanticLogger::Loggable
10
+
11
+ def self.env
12
+ ActiveSupport::StringInquirer.new(ENV['MICRO_ENV'] || 'development')
13
+ end
14
+ end
15
+
16
+ require 'micro/version'
17
+ require 'micro/configuration'
18
+ require 'micro/sidecar/base'
19
+ require 'micro/sidecar/register'
20
+ require 'micro/sidecar/call'
21
+ require 'micro/handler'
22
+ require 'micro/handler_manager'
23
+ require 'micro/servers/web'
24
+ require 'micro/servers/error'
25
+ require 'micro/handlers/debug'
data/micro-rb.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'micro/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'micro-rb'
9
+ spec.version = MicroRb::VERSION
10
+ spec.authors = ['Andrew Medeiros']
11
+ spec.email = ['andrew@amedeiros.com']
12
+
13
+ spec.summary = 'Write micro services in Ruby for the Micro framework'
14
+ spec.homepage = 'https://github.com/amedeiros/micro-rb'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+
21
+ spec.bindir = 'bin'
22
+ spec.executables = ['microrb']
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.14'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'minitest', '~> 5.0'
28
+ spec.add_development_dependency 'minitest-reporters', '~> 1.1'
29
+ spec.add_development_dependency 'shoulda', '~> 3.5'
30
+
31
+ spec.add_runtime_dependency 'activesupport', '~> 5.1', '>= 5.1.0'
32
+ spec.add_runtime_dependency 'httparty', '~> 0.14.0'
33
+ spec.add_runtime_dependency 'multi_json', '~> 1.12', '>= 1.12.1'
34
+ spec.add_runtime_dependency 'rack', '~> 1.6', '>= 1.6.5'
35
+ spec.add_runtime_dependency 'semantic_logger', '~> 4.0', '>= 4.0.0'
36
+ spec.add_runtime_dependency 'google-protobuf', '~> 3.3', '>= 3.3.0'
37
+ end
data/registry.png ADDED
Binary file
data/sum.png ADDED
Binary file
@@ -0,0 +1,3 @@
1
+ FROM alpine:3.2
2
+ ADD <%= @name %>-srv /<%= @name %>-srv
3
+ ENTRYPOINT [ "/<%= @name %>-srv" ]
data/templates/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rake'
4
+
5
+ gem 'bundler'
6
+ gem 'micro-rb'
7
+ <% if @encryption %>
8
+ gem 'symmetric-encryption'
9
+ <%end%>
10
+ <% if @active_record %>
11
+ gem 'activerecord'
12
+ gem <%= "'#{@engine}'" %>
13
+ <% end %>
14
+
15
+ group :test do
16
+ gem 'minitest'
17
+ gem 'minitest-reporters'
18
+ end
data/templates/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) <%= @year %> <%= @username %>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ # <%= @name %>
2
+
3
+ This readme was generated by MircoRb.
4
+
5
+ ## Installation
6
+
7
+ ## Usage
8
+
9
+ ## Contributing
10
+
11
+ ## Changelog
12
+
13
+ ### Version 0.0.1
14
+
15
+ ## License
16
+
17
+ See LICENSE
@@ -0,0 +1,9 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ t.test_files = FileList['test/*_test.rb']
6
+ t.verbose = true
7
+ end
8
+
9
+ task default: :test
data/templates/bin/app ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+ require '<%= @name %>'
5
+ <% if @active_record %>
6
+ # Change the following to reflect your database settings
7
+ ActiveRecord::Base.establish_connection(
8
+ adapter: <%= "'#{@engine}'" %>,
9
+ host: ENV[:DB_HOST],
10
+ database: ENV[:DB_NAME],
11
+ username: ENV[:DB_USERNAME],
12
+ password: ENV[:DB_PASSWORD]
13
+ )
14
+ <% end %>
15
+ server = MicroRb::Servers::Web.new(:example_service, debug: true)
16
+ server.add_handler <%= @class_name %>::ExampleHandler.new
17
+ server.start!
@@ -0,0 +1,16 @@
1
+ require_relative '../proto/sum_pb'
2
+
3
+ module <%= @class_name %>
4
+ # Example MicroRb handler
5
+ class ExampleHandler
6
+ include MicroRb::Handler
7
+ include <%= @class_name %>::SumHandler
8
+ handler name: :example, metadata: { hello: 'Micro-Rb' }, rpc_method: :sum
9
+
10
+ def sum(request: Request.new, response: Response.new)
11
+ response.total = request.a + request.b
12
+
13
+ response
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ syntax = "proto3";
2
+
3
+ package <%= @name %>.sum_handler;
4
+
5
+ message Request {
6
+ int32 a = 1;
7
+ int32 b = 2;
8
+ }
9
+
10
+ message Response {
11
+ int32 total = 1;
12
+ }
@@ -0,0 +1,21 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: sum.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message '<%= @name %>.sum_handler.Request' do
8
+ optional :a, :int32, 1
9
+ optional :b, :int32, 2
10
+ end
11
+ add_message '<%= @name %>.sum_handler.Response' do
12
+ optional :total, :int32, 1
13
+ end
14
+ end
15
+
16
+ module <%= @class_name %>
17
+ module SumHandler
18
+ Request = Google::Protobuf::DescriptorPool.generated_pool.lookup('<%= @name %>.sum_handler.Request').msgclass
19
+ Response = Google::Protobuf::DescriptorPool.generated_pool.lookup('<%= @name %>.sum_handler.Response').msgclass
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+
2
+ module <%= @class_name %>
3
+ VERSION = '0.0.1'
4
+ end
@@ -0,0 +1,14 @@
1
+ # Load Bundler and load all your gems
2
+ require 'bundler/setup'
3
+
4
+ # Explicitly load any gems you need.
5
+ require 'microrb'
6
+ require '<%= @name %>/version'
7
+ require '<%= @name %>/handlers/example_handler'
8
+
9
+ module <%= @class_name %>
10
+ # Your code goes here...
11
+ # Good place for your main application logic if this is a library.
12
+
13
+ # be sure to create unit tests for them too.
14
+ end
@@ -0,0 +1,11 @@
1
+ require 'test_helper'
2
+
3
+ require '<%= @name %>'
4
+
5
+ class <%= @class_name %>Test < Minitest::Test
6
+
7
+ def test_it_does_something_useful
8
+ assert false
9
+ end
10
+
11
+ end
@@ -0,0 +1,9 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ # Your tests should require this file which sets up the test harness.
5
+ require 'minitest/autorun'
6
+ require 'minitest/reporters'
7
+
8
+ reporter_options = { color: true }
9
+ Minitest::Reporters.use! [Minitest::Reporters::DefaultReporter.new(reporter_options)]