specimen 0.0.1.alpha.b → 0.0.3.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -19
  3. data/VERSION +1 -1
  4. data/bin/specimen +2 -2
  5. data/lib/specimen/cli.rb +6 -20
  6. data/lib/specimen/command/base.rb +35 -0
  7. data/lib/specimen/command/base_group.rb +35 -0
  8. data/lib/specimen/command/exec_command_builder.rb +45 -0
  9. data/lib/specimen/command/runner/cukes_runner.rb +26 -0
  10. data/lib/specimen/command/runner/exec_runner.rb +37 -0
  11. data/lib/specimen/command/runner/path_runner.rb +24 -0
  12. data/lib/specimen/command/runner/specs_runner.rb +25 -0
  13. data/lib/specimen/command/test_runner.rb +58 -0
  14. data/lib/specimen/command.rb +207 -0
  15. data/lib/specimen/commands/cukes/cukes_command.rb +9 -0
  16. data/lib/specimen/commands/exec/exec_command.rb +9 -0
  17. data/lib/specimen/commands/gem_help/USAGE +14 -0
  18. data/lib/specimen/commands/gem_help/gem_help_command.rb +23 -0
  19. data/lib/specimen/commands/init/USAGE +38 -0
  20. data/lib/specimen/commands/init/init_command.rb +49 -0
  21. data/lib/specimen/commands/specs/specs_command.rb +9 -0
  22. data/lib/specimen/extensions/ruby/hash.rb +1 -0
  23. data/lib/specimen/generator/configs/specimen_project_config.rb +122 -0
  24. data/lib/specimen/generator/cucumber/cucumber_project_generator.rb +28 -0
  25. data/lib/specimen/generator/cucumber/templates/config/cucumber.yml.tt +1 -0
  26. data/lib/specimen/generator/cucumber/templates/features/examples/add_numbers.feature.tt +9 -0
  27. data/lib/specimen/generator/cucumber/templates/features/support/env.rb.tt +0 -0
  28. data/lib/specimen/generator/file_by_template.rb +6 -4
  29. data/lib/specimen/generator/generator_base.rb +9 -0
  30. data/lib/specimen/generator/project/project_root_generator.rb +31 -0
  31. data/lib/specimen/generator/project/specimen_project_generator.rb +25 -0
  32. data/lib/specimen/generator/project/templates/root/.gitignore.tt +4 -0
  33. data/lib/specimen/generator/project/templates/root/config/specimen.yml.tt +38 -0
  34. data/lib/specimen/generator/project_generator_base.rb +34 -0
  35. data/lib/specimen/generator/rspec/rspec_project_generator.rb +28 -0
  36. data/lib/specimen/generator/rspec/templates/config/.rspec.tt +5 -0
  37. data/lib/specimen/generator/rspec/templates/spec/examples/example_spec.rb.tt +13 -0
  38. data/lib/specimen/generator/rspec/templates/spec/spec_helper.rb.tt +15 -0
  39. data/lib/specimen/generator.rb +8 -1
  40. data/lib/specimen/runtime/yml_parser.rb +47 -0
  41. data/lib/specimen/runtime.rb +84 -0
  42. data/lib/specimen/version.rb +4 -6
  43. data/lib/specimen.rb +12 -3
  44. metadata +114 -13
  45. data/lib/specimen/cli/default_command.rb +0 -37
  46. data/lib/specimen/generator/specimen_project.rb +0 -73
  47. data/lib/specimen/generator/specimen_project_config.rb +0 -54
  48. data/lib/specimen/generator/templates/specimen/specimen.yml.tt +0 -1
  49. /data/lib/specimen/generator/{templates/gemrc.tt → project/templates/root/.gemrc.tt} +0 -0
  50. /data/lib/specimen/generator/{templates/rbenv-gemsets.tt → project/templates/root/.rbenv-gemsets.tt} +0 -0
  51. /data/lib/specimen/generator/{templates/rubocop.yml.tt → project/templates/root/.rubocop.yml.tt} +0 -0
  52. /data/lib/specimen/generator/{templates → project/templates/root}/Gemfile.tt +0 -0
  53. /data/lib/specimen/generator/{templates → project/templates/root}/README.md.tt +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '091d4e836ac67953118af5d330c4254d7e29716b7cb3e2756369b45a0ba74a88'
4
- data.tar.gz: 69249e8db11054399bbc70c2fdee9163b9cbac769ae79ed55182c61f4083448a
3
+ metadata.gz: 7c0a28521622f9720868bc538c48567cd6ee1b290dc0939572d0af33d2ef2ecf
4
+ data.tar.gz: 6d7042ab4f3bd81237694a93ddd7641772a2381597a3185ea258b536616de895
5
5
  SHA512:
6
- metadata.gz: 83f173e5ecfe205b8581e18851aed9de5e0e19f52c995790f53af3316d7e16238d8ff02104339c360caf0db07916347c157664c955522bc89b6ad2a6c28dbcbe
7
- data.tar.gz: 0ab049182afb589bfe054d0325114cd0d3536c4ec9990df0e222bfd5ef8713e93b2e901dbf2ae534794e9fda09d5bd4a42a87e778d8142346ea6f1bd50d817fc
6
+ metadata.gz: 1c53ce47754279e09e849511566fe515d1ed64842653f24beb631a430e77b855249a51a6eee1b7a83b2197be888a8487d97f355028e827e7ac776a87f78aed7f
7
+ data.tar.gz: aa5615ac6bf581885ae77d4c0321cf0a3473489b25b096684c307817bee0fe406c27bb584aab04a36b7d84bcf236c6a14948b510f7f12c06a9fbb1a5b601bc7a
data/README.md CHANGED
@@ -8,36 +8,77 @@ will help me with:
8
8
  - provide a Rails like templating approach in terms of _convention over configuration_ to provide a maintainable base for
9
9
  API or UI tests using RSpec and/or Cucumber.
10
10
 
11
+ ## specimen commands
11
12
 
12
- **Beware**
13
+ ```shell
14
+ ❯ specimen
15
+ Usage:
16
+ specimen COMMAND [options]
13
17
 
14
- At the point of writing the README and setting the repo to public, the gem does not do much yet so the current functionality
15
- is minimal, not optimized and not tested :). Hopefully that will change in the future.
18
+ You must specify a command:
16
19
 
17
- ```shell
18
- # install Specimen gem
19
- $> gem install specimen
20
+ init Initialize a new specimen project
21
+ cukes Run Cucumber tests (WIP)
22
+ specs Run RSpec tests (WIP)
23
+ exec Run tests via a config file (WIP)
20
24
 
21
- # creates a new project relative to the current working directory. Will ask for a project name.
22
- $> specimen init
25
+ All commands can be run with -h (or --help) for more information.
26
+ ```
23
27
 
24
- # creates a new project 'foobar' relative to the current working directory.
25
- # Inside /foobar you will find the default dir structures for Cucumber and RSpec tests and a few more files
26
- $> specimen init -n foobar
28
+ ### specimen init
27
29
 
28
- # look at the command help
29
- $> specimen help init
30
+ ```shell
31
+ specimen init -h
30
32
  Usage:
31
- specimen init
33
+ specimen init --name=NAME [options] # Create a new specimen project which will generate following dirs and files
34
+
35
+ * default directories /config, /lib, /tmp
36
+ * default directories (/features/..) and files for cucumber unless --skip-cucumber
37
+ * default directories (/spec/..) and files for RSpec unless --skip-rspec
38
+ * root path files:
39
+ * .gemrc
40
+ * .gitignore
41
+ * .rspec (unless --skip-rspec)
42
+ * .rubocop.yml
43
+ * cucumber.yml (unless --skip-cucumber)
44
+ * Gemfile (based on the used options)
45
+ * README.md
46
+ * specimen.yml (default configuration file for the specimen gem
32
47
 
33
48
  Options:
34
- --name, -n, [--project-name=PROJECT_NAME]
35
- [--api-only], [--no-api-only], [--skip-api-only] # Default: false
36
- [--cucumber], [--no-cucumber], [--skip-cucumber] # Default: true
49
+ -n, [--name=NAME] # required: true
50
+ The name of your project and installation path relative to your current PWD
51
+
52
+ [--ui-driver=UI_DRIVER] # Default: 'watir'
53
+ Valid options are:
54
+ * watir
55
+ * selenium
56
+ * selenium-webdriver
57
+
58
+ [--skip-ui] # Default: false
59
+ Don´t add selenium or watir gem to your Gemfile
60
+
61
+ [--skip-cucumber] # Default: false
62
+ No cucumber gems will be added to your Gemfile.
63
+ Creation of cucumber directories and files will be skipped.
64
+
65
+ [--skip-rspec] # Default: false
66
+ RSpec will still be in your Gemfile (as it´s matchers are used for cucumber)
67
+ but no RSpec directories and files will be generated
37
68
  ```
38
69
 
70
+ ### specimen cukes
71
+
72
+ TBD
73
+
74
+ ### specimen specs
75
+
76
+ TBD
77
+
78
+ ### specimen exec
79
+
80
+ TBD
39
81
 
40
82
  ### Known issues
41
83
 
42
- - tests are missing
43
- - generated Gemfile contains Watir and Selenium webdriver, it should be only one of them.
84
+ - tests are missing
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1.alpha.b
1
+ 0.0.3.alpha
data/bin/specimen CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- lib_path = File.expand_path('..', __dir__) + '/lib'
4
+ lib_path = "#{File.expand_path('..', __dir__)}/lib"
4
5
  $LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
5
6
 
6
7
  require 'specimen/cli'
7
- Specimen::CLI.start!(ARGV.dup)
data/lib/specimen/cli.rb CHANGED
@@ -1,25 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'specimen'
4
- require 'specimen/cli/default_command'
5
4
 
6
- module Specimen
7
- module CLI
8
- class << self
9
- def start!(args = ARGV)
10
- command = args.shift
5
+ config = {
6
+ verbose: ENV.key?('VERBOSE'),
7
+ strict: ENV.key?('STRICT'),
8
+ log_level: ENV.key?('LOG_LEVEL') ? ENV.fetch('LOG_LEVEL').to_sym : :info
9
+ }
11
10
 
12
- case command
13
- when '--version', '-v'
14
- show_version
15
- else
16
- DefaultCommand.start(ARGV.dup)
17
- end
18
- end
19
-
20
- def show_version
21
- puts(Specimen::VERSION::STRING)
22
- end
23
- end
24
- end
25
- end
11
+ Specimen::Command.execute!(ARGV.dup, config)
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class Base < Thor
6
+ include Thor::Actions
7
+
8
+ class << self
9
+ def exit_on_failure?
10
+ false
11
+ end
12
+ end
13
+
14
+ no_commands do
15
+ def usage_path
16
+ find_in_source_paths('USAGE')
17
+ rescue Thor::Error
18
+ ''
19
+ end
20
+
21
+ def usage_content
22
+ return '' if usage_path.empty?
23
+
24
+ File.read(usage_path)
25
+ end
26
+
27
+ def class_usage
28
+ return nil if usage_content.empty?
29
+
30
+ ERB.new(usage_content, trim_mode: '-').result(binding)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class BaseGroup < Thor::Group
6
+ include Thor::Actions
7
+
8
+ class << self
9
+ def exit_on_failure?
10
+ false
11
+ end
12
+ end
13
+
14
+ no_commands do
15
+ def usage_path
16
+ find_in_source_paths('USAGE')
17
+ rescue Thor::Error
18
+ ''
19
+ end
20
+
21
+ def usage_content
22
+ return '' if usage_path.empty?
23
+
24
+ File.read(usage_path)
25
+ end
26
+
27
+ def class_usage
28
+ return nil if usage_content.empty?
29
+
30
+ ERB.new(usage_content, trim_mode: '-').result(binding)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class ExecCommandBuilder
6
+ attr_reader :config
7
+
8
+ def initialize(config:, framework: nil, tests_path: '')
9
+ @framework = framework
10
+ @config = config
11
+ @tests_path = tests_path
12
+ end
13
+
14
+ def build_cmd
15
+ raise 'Undefined framework' if base_cmd.nil?
16
+
17
+ "#{env_string} #{base_cmd} #{options_string} #{@tests_path}".strip
18
+ end
19
+
20
+ def base_cmd
21
+ config['framework'] || @framework
22
+ end
23
+
24
+ def env_vars
25
+ config['env'] || []
26
+ end
27
+
28
+ def command_options
29
+ config['options'] || []
30
+ end
31
+
32
+ def env_string
33
+ return '' unless env_vars.any?
34
+
35
+ env_vars.join(' ')
36
+ end
37
+
38
+ def options_string
39
+ return '' unless command_options.any?
40
+
41
+ command_options.map(&:to_s).join(' ')
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class CukesRunner < PathRunner
6
+ no_commands do
7
+ def perform
8
+ super
9
+
10
+ check_config_not_nil!
11
+ inside runtime.work_dir do
12
+ run(exec_cmd)
13
+ end
14
+ end
15
+
16
+ def framework
17
+ profile_config['framework'] || 'cucumber'
18
+ end
19
+
20
+ def profile_name
21
+ profile? ? profile : 'cucumber'
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class ExecRunner < TestRunner
6
+ class_option :profile, aliases: %w[-p], type: :string
7
+
8
+ no_commands do
9
+ def perform
10
+ super
11
+
12
+ run_profile_check!
13
+ check_config_not_nil!
14
+ inside runtime.work_dir do
15
+ run(exec_cmd)
16
+ end
17
+ end
18
+
19
+ def tests_path
20
+ ''
21
+ end
22
+
23
+ def run_profile_check!
24
+ raise "Missing command option '--profile|-p'" unless profile?
25
+ end
26
+
27
+ def framework
28
+ profile_config['framework'] || nil
29
+ end
30
+
31
+ def profile_name
32
+ profile? ? profile : nil
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class PathRunner < TestRunner
6
+ argument :path, type: :string, default: ''
7
+
8
+ no_commands do
9
+ def arg_is_command_option?
10
+ return false if path.empty?
11
+
12
+ path.start_with?('--', '-')
13
+ end
14
+
15
+ def tests_path
16
+ return @tests_path if @tests_path
17
+ return '' if arg_is_command_option?
18
+
19
+ @tests_path = path
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class SpecsRunner < PathRunner
6
+ no_commands do
7
+ def perform
8
+ super
9
+ check_config_not_nil!
10
+ inside runtime.work_dir do
11
+ run(exec_cmd)
12
+ end
13
+ end
14
+
15
+ def framework
16
+ profile_config['framework'] || 'rspec'
17
+ end
18
+
19
+ def profile_name
20
+ profile? ? profile : 'rspec'
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class TestRunner < BaseGroup
6
+ class ProfileDataNilError < RuntimeError
7
+ def initialize(profile_name, yml_name)
8
+ @msg = "No data found in '#{yml_name}' for profile: '#{profile_name}'"
9
+ super(@msg)
10
+ end
11
+ end
12
+
13
+ class_option :config_file, aliases: %w[-C --config], type: :string, default: 'specimen.yml'
14
+
15
+ no_commands do
16
+ def perform
17
+ runtime
18
+ end
19
+
20
+ def runtime
21
+ return @runtime if @runtime
22
+
23
+ runtime = Runtime.start!(self)
24
+ Specimen.runtime = runtime
25
+ @runtime = runtime
26
+ end
27
+
28
+ def framework
29
+ nil
30
+ end
31
+
32
+ def profile
33
+ options[:profile]
34
+ end
35
+
36
+ def profile?
37
+ !profile.nil?
38
+ end
39
+
40
+ def profile_config
41
+ runtime.profile_yml_data(profile_name)
42
+ end
43
+
44
+ def profile_name
45
+ profile? ? profile : nil
46
+ end
47
+
48
+ def exec_cmd
49
+ ExecCommandBuilder.new(config: profile_config, framework:, tests_path:).build_cmd
50
+ end
51
+
52
+ def check_config_not_nil!
53
+ raise ProfileDataNilError.new(profile_name, runtime.yml_name) if profile? && profile_config.nil?
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,207 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'colorize'
4
+ require 'thor'
5
+
6
+ require 'specimen/command/base'
7
+ require 'specimen/command/base_group'
8
+ require 'specimen/command/test_runner'
9
+ require 'specimen/command/exec_command_builder'
10
+ require 'specimen/command/runner/path_runner'
11
+ require 'specimen/command/runner/cukes_runner'
12
+ require 'specimen/command/runner/exec_runner'
13
+ require 'specimen/command/runner/specs_runner'
14
+
15
+ require 'specimen/commands/cukes/cukes_command'
16
+ require 'specimen/commands/exec/exec_command'
17
+ require 'specimen/commands/gem_help/gem_help_command'
18
+ require 'specimen/commands/init/init_command'
19
+ require 'specimen/commands/specs/specs_command'
20
+
21
+ module Specimen
22
+ module Command
23
+ class InvalidCommandError < RuntimeError; end
24
+
25
+ extend ActiveSupport::Autoload
26
+
27
+ autoload :Base
28
+ autoload :BaseGroup
29
+
30
+ COMMAND_MAPPINGS = %w[cukes exec init specs generate test].to_set
31
+ HELP_MAPPINGS = %w[-h -? --help].to_set
32
+ VERSION_MAPPINGS = %w[-v --version].to_set
33
+
34
+ class << self
35
+ attr_reader :args, :config, :exec_config
36
+
37
+ def default_config
38
+ @default_config ||= {
39
+ verbose: false,
40
+ strict: false,
41
+ log_level: :info
42
+ }
43
+ end
44
+
45
+ def execute!(args = [], config = {})
46
+ @args = args.dup
47
+ @config = config
48
+ @exec_config = default_config.merge!(config)
49
+
50
+ trap_interrupt
51
+
52
+ raise InvalidCommandError, "'#{command_arg}' is not a valid specimen command!" unless valid_command?
53
+
54
+ show_gem_help_and_exit! if gem_help?
55
+ show_gem_version_and_exit! if show_version?
56
+ show_command_help_and_exit! if command_help?
57
+
58
+ command_perform!
59
+
60
+ exit_ok
61
+ rescue StandardError => e
62
+ shell.say(e.message.red.bold)
63
+
64
+ if exec_config[:verbose]
65
+ shell.say(e.class.to_s.red.bold)
66
+ shell.say(e.backtrace&.join("\n").red)
67
+ end
68
+
69
+ exit_specimen_failed
70
+ end
71
+
72
+ def show_gem_help_and_exit!
73
+ GemHelpCommand.new([]).perform
74
+
75
+ exit_ok
76
+ end
77
+
78
+ def show_command_help_and_exit!
79
+ display_command_help
80
+
81
+ exit_ok
82
+ end
83
+
84
+ def show_gem_version_and_exit!
85
+ shell.say("specimen version: #{Specimen.gem_version.to_s.bold}")
86
+
87
+ exit_ok
88
+ end
89
+
90
+ def display_command_help
91
+ shallow_command.class_usage.nil? ? shallow_command.class.help(shell) : shell.say(shallow_command.class_usage)
92
+ end
93
+
94
+ def command_perform!
95
+ command.new(command_arguments, parsed_command_options).perform
96
+ end
97
+
98
+ def shallow_command
99
+ @shallow_command ||= command.new([])
100
+ end
101
+
102
+ def command_arg
103
+ @command_arg ||= args.first
104
+ end
105
+
106
+ def command_arg?
107
+ !command_arg.nil?
108
+ end
109
+
110
+ def command_arguments
111
+ @command_arguments ||= args.reject { |arg| arg == command_arg }
112
+ end
113
+
114
+ def command
115
+ @command ||= {
116
+ cukes: CukesCommand,
117
+ exec: ExecCommand,
118
+ gem_help: GemHelpCommand,
119
+ init: InitCommand,
120
+ specs: SpecsCommand
121
+ }[command_arg.to_sym]
122
+ end
123
+
124
+ def command_class_options
125
+ command.class_options
126
+ end
127
+
128
+ def command_local_options
129
+ @command_local_options ||= {}
130
+ end
131
+
132
+ # need to look into that
133
+ def command_options_relation
134
+ {exclusive_option_names: [], at_least_one_option_names: []}
135
+ end
136
+
137
+ def disable_required_check?
138
+ return true if command_help?
139
+
140
+ command.disable_required_check? command
141
+ end
142
+
143
+ def stop_on_unknown_option?
144
+ exec_config[:strict] || false
145
+ end
146
+
147
+ def parsed_command_options
148
+ Thor::Options.new(
149
+ command_class_options,
150
+ command_local_options,
151
+ stop_on_unknown_option?,
152
+ disable_required_check?,
153
+ command_options_relation
154
+ ).parse(command_arguments)
155
+ end
156
+
157
+ def command?
158
+ COMMAND_MAPPINGS.include?(command_arg)
159
+ end
160
+
161
+ def command_help?
162
+ HELP_MAPPINGS.include?(command_arguments.first)
163
+ end
164
+
165
+ def gem_help?
166
+ return true if command_arg.nil?
167
+
168
+ HELP_MAPPINGS.include?(command_arg)
169
+ end
170
+
171
+ def valid_command?
172
+ command? || gem_help? || show_version?
173
+ end
174
+
175
+ def show_version?
176
+ return false if command_arg.nil?
177
+
178
+ VERSION_MAPPINGS.include?(command_arg)
179
+ end
180
+
181
+ private
182
+
183
+ def shell
184
+ @shell ||= Thor::Base.shell.new
185
+ end
186
+
187
+ def exit_ok
188
+ Kernel.exit(0)
189
+ end
190
+
191
+ def exit_specimen_failed
192
+ Kernel.exit(1)
193
+ end
194
+
195
+ def exit_unable_to_finish
196
+ Kernel.exit(2)
197
+ end
198
+
199
+ def trap_interrupt
200
+ Signal.trap('INT') do
201
+ shell.say("\nExiting... Interrupt again to exit immediately.".red.bold)
202
+ exit_unable_to_finish
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class CukesCommand < CukesRunner
6
+ namespace :cukes
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specimen
4
+ module Command
5
+ class ExecCommand < ExecRunner
6
+ namespace :exec
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ Usage:
2
+ specimen COMMAND [options]
3
+
4
+ You must specify a command:
5
+
6
+ init Initialize a new specimen project
7
+ cukes Run Cucumber tests (WIP)
8
+ specs Run RSpec tests (WIP)
9
+ exec Run tests via a config file (WIP)
10
+
11
+ -v|--version Show specimen version
12
+ -h|--help You are looking at it
13
+
14
+ All commands can be run with -h (or --help) for more information.