specimen 0.0.1.alpha.b → 0.0.2.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 +47 -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 +209 -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 +11 -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 +33 -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 +49 -0
  41. data/lib/specimen/runtime.rb +84 -0
  42. data/lib/specimen/version.rb +4 -6
  43. data/lib/specimen.rb +11 -3
  44. metadata +99 -12
  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: e3fce910bcf39219d89c6e71fc7b55f49190059d3b667075efbf3cc52c856023
4
+ data.tar.gz: 988fd2a04568f0e29bac692cc108e1086b9a3d200db7f74315ff4d56835a4bdf
5
5
  SHA512:
6
- metadata.gz: 83f173e5ecfe205b8581e18851aed9de5e0e19f52c995790f53af3316d7e16238d8ff02104339c360caf0db07916347c157664c955522bc89b6ad2a6c28dbcbe
7
- data.tar.gz: 0ab049182afb589bfe054d0325114cd0d3536c4ec9990df0e222bfd5ef8713e93b2e901dbf2ae534794e9fda09d5bd4a42a87e778d8142346ea6f1bd50d817fc
6
+ metadata.gz: 3445ddf6f2c1ff018d60153f9f6693d240ef61424f3783a6cc937ae6dfbd5f21e71354b24ea4aedca32ae0e7f301017adf59db1eb3cd564b938769c84000e64f
7
+ data.tar.gz: 7e4ff97d90c40fe7bfc2ee43da5826cc355b49531fc65cbf84d8771742ce8b17e1b6b2a34911decc1656196070e3642e87f92f41e9e61297512be77f3da17444
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.2.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,47 @@
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
+
45
+
46
+ end
47
+ 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,209 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'colorize'
4
+ require 'thor'
5
+
6
+ require 'pry'
7
+
8
+ require 'specimen/command/base'
9
+ require 'specimen/command/base_group'
10
+ require 'specimen/command/test_runner'
11
+ require 'specimen/command/exec_command_builder'
12
+ require 'specimen/command/runner/path_runner'
13
+ require 'specimen/command/runner/cukes_runner'
14
+ require 'specimen/command/runner/exec_runner'
15
+ require 'specimen/command/runner/specs_runner'
16
+
17
+ require 'specimen/commands/cukes/cukes_command'
18
+ require 'specimen/commands/exec/exec_command'
19
+ require 'specimen/commands/gem_help/gem_help_command'
20
+ require 'specimen/commands/init/init_command'
21
+ require 'specimen/commands/specs/specs_command'
22
+
23
+ module Specimen
24
+ module Command
25
+ class InvalidCommandError < RuntimeError; end
26
+
27
+ extend ActiveSupport::Autoload
28
+
29
+ autoload :Base
30
+ autoload :BaseGroup
31
+
32
+ COMMAND_MAPPINGS = %w[cukes exec init specs generate test].to_set
33
+ HELP_MAPPINGS = %w[-h -? --help].to_set
34
+ VERSION_MAPPINGS = %w[-v --version].to_set
35
+
36
+ class << self
37
+ attr_reader :args, :config, :exec_config
38
+
39
+ def default_config
40
+ @default_config ||= {
41
+ verbose: false,
42
+ strict: false,
43
+ log_level: :info
44
+ }
45
+ end
46
+
47
+ def execute!(args = [], config = {})
48
+ @args = args.dup
49
+ @config = config
50
+ @exec_config = default_config.merge!(config)
51
+
52
+ trap_interrupt
53
+
54
+ raise InvalidCommandError, "'#{command_arg}' is not a valid specimen command!" unless valid_command?
55
+
56
+ show_gem_help_and_exit! if gem_help?
57
+ show_gem_version_and_exit! if show_version?
58
+ show_command_help_and_exit! if command_help?
59
+
60
+ command_perform!
61
+
62
+ exit_ok
63
+ rescue StandardError => e
64
+ shell.say(e.message.red.bold)
65
+
66
+ if exec_config[:verbose]
67
+ shell.say(e.class.to_s.red.bold)
68
+ shell.say(e.backtrace&.join("\n").red)
69
+ end
70
+
71
+ exit_specimen_failed
72
+ end
73
+
74
+ def show_gem_help_and_exit!
75
+ GemHelpCommand.new([]).perform
76
+
77
+ exit_ok
78
+ end
79
+
80
+ def show_command_help_and_exit!
81
+ display_command_help
82
+
83
+ exit_ok
84
+ end
85
+
86
+ def show_gem_version_and_exit!
87
+ shell.say("specimen version: #{Specimen.gem_version.to_s.bold}")
88
+
89
+ exit_ok
90
+ end
91
+
92
+ def display_command_help
93
+ shallow_command.class_usage.nil? ? shallow_command.class.help(shell) : shell.say(shallow_command.class_usage)
94
+ end
95
+
96
+ def command_perform!
97
+ command.new(command_arguments, parsed_command_options).perform
98
+ end
99
+
100
+ def shallow_command
101
+ @shallow_command ||= command.new([])
102
+ end
103
+
104
+ def command_arg
105
+ @command_arg ||= args.first
106
+ end
107
+
108
+ def command_arg?
109
+ !command_arg.nil?
110
+ end
111
+
112
+ def command_arguments
113
+ @command_arguments ||= args.reject { |arg| arg == command_arg }
114
+ end
115
+
116
+ def command
117
+ @command ||= {
118
+ cukes: CukesCommand,
119
+ exec: ExecCommand,
120
+ gem_help: GemHelpCommand,
121
+ init: InitCommand,
122
+ specs: SpecsCommand
123
+ }[command_arg.to_sym]
124
+ end
125
+
126
+ def command_class_options
127
+ command.class_options
128
+ end
129
+
130
+ def command_local_options
131
+ @command_local_options ||= {}
132
+ end
133
+
134
+ # need to look into that
135
+ def command_options_relation
136
+ {exclusive_option_names: [], at_least_one_option_names: []}
137
+ end
138
+
139
+ def disable_required_check?
140
+ return true if command_help?
141
+
142
+ command.disable_required_check? command
143
+ end
144
+
145
+ def stop_on_unknown_option?
146
+ exec_config[:strict] || false
147
+ end
148
+
149
+ def parsed_command_options
150
+ Thor::Options.new(
151
+ command_class_options,
152
+ command_local_options,
153
+ stop_on_unknown_option?,
154
+ disable_required_check?,
155
+ command_options_relation
156
+ ).parse(command_arguments)
157
+ end
158
+
159
+ def command?
160
+ COMMAND_MAPPINGS.include?(command_arg)
161
+ end
162
+
163
+ def command_help?
164
+ HELP_MAPPINGS.include?(command_arguments.first)
165
+ end
166
+
167
+ def gem_help?
168
+ return true if command_arg.nil?
169
+
170
+ HELP_MAPPINGS.include?(command_arg)
171
+ end
172
+
173
+ def valid_command?
174
+ command? || gem_help? || show_version?
175
+ end
176
+
177
+ def show_version?
178
+ return false if command_arg.nil?
179
+
180
+ VERSION_MAPPINGS.include?(command_arg)
181
+ end
182
+
183
+ private
184
+
185
+ def shell
186
+ @shell ||= Thor::Base.shell.new
187
+ end
188
+
189
+ def exit_ok
190
+ Kernel.exit(0)
191
+ end
192
+
193
+ def exit_specimen_failed
194
+ Kernel.exit(1)
195
+ end
196
+
197
+ def exit_unable_to_finish
198
+ Kernel.exit(2)
199
+ end
200
+
201
+ def trap_interrupt
202
+ Signal.trap('INT') do
203
+ shell.say("\nExiting... Interrupt again to exit immediately.".red.bold)
204
+ exit_unable_to_finish
205
+ end
206
+ end
207
+ end
208
+ end
209
+ 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,11 @@
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
+ All commands can be run with -h (or --help) for more information.