omnitest 0.2.1
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 +7 -0
- data/.gitignore +18 -0
- data/.gitmodules +0 -0
- data/.groc.json +7 -0
- data/.rspec +6 -0
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +47 -0
- data/.travis.yml +12 -0
- data/.yardopts +3 -0
- data/Gemfile +26 -0
- data/README.md +341 -0
- data/Rakefile +33 -0
- data/appveyor.yml +9 -0
- data/bin/omnidoc +5 -0
- data/bin/omnitask +5 -0
- data/bin/omnitest +5 -0
- data/bower.json +21 -0
- data/doc-src/index.md.tt +341 -0
- data/doc-src/project_sets.md.tt +31 -0
- data/doc-src/usage/crosstask.md.tt +86 -0
- data/doc-src/usage/omnitest.md.tt +87 -0
- data/features/bootstrapping.feature +25 -0
- data/features/cloning.feature +32 -0
- data/features/fixtures/configs/omnitest_sample.yaml +11 -0
- data/features/fixtures/configs/skeptic_empty.yaml +12 -0
- data/features/fixtures/configs/skeptic_hello_world.yaml +10 -0
- data/features/show.feature +38 -0
- data/features/states.feature +40 -0
- data/features/step_definitions/sdk_steps.rb +22 -0
- data/features/support/env.rb +9 -0
- data/lib/omnitest.rb +211 -0
- data/lib/omnitest/cli.rb +297 -0
- data/lib/omnitest/command.rb +103 -0
- data/lib/omnitest/command/generate.rb +29 -0
- data/lib/omnitest/command/generators/code2doc.rb +79 -0
- data/lib/omnitest/command/generators/dashboard.rb +148 -0
- data/lib/omnitest/command/generators/documentation.rb +119 -0
- data/lib/omnitest/command/list.rb +62 -0
- data/lib/omnitest/command/project_action.rb +26 -0
- data/lib/omnitest/command/scenario_action.rb +20 -0
- data/lib/omnitest/command/show.rb +148 -0
- data/lib/omnitest/command/task.rb +27 -0
- data/lib/omnitest/command/test.rb +41 -0
- data/lib/omnitest/configuration.rb +53 -0
- data/lib/omnitest/documentation_generator.rb +68 -0
- data/lib/omnitest/project.rb +100 -0
- data/lib/omnitest/project_logger.rb +273 -0
- data/lib/omnitest/project_set.rb +47 -0
- data/lib/omnitest/reporters.rb +27 -0
- data/lib/omnitest/reporters/hash_reporter.rb +32 -0
- data/lib/omnitest/reporters/json_reporter.rb +12 -0
- data/lib/omnitest/reporters/markdown_reporter.rb +26 -0
- data/lib/omnitest/reporters/yaml_reporter.rb +12 -0
- data/lib/omnitest/run_action.rb +44 -0
- data/lib/omnitest/version.rb +3 -0
- data/lib/omnitest/workflow.rb +5 -0
- data/mkdocs.yml +8 -0
- data/omnitest.gemspec +39 -0
- data/omnitest.yaml +5 -0
- data/resources/assets/angular/angular.min.js +217 -0
- data/resources/assets/angular/angular.min.js.map +8 -0
- data/resources/assets/angular/json-formatter.min.css +6 -0
- data/resources/assets/angular/json-formatter.min.js +7 -0
- data/resources/assets/angular/ng-table.map +1 -0
- data/resources/assets/angular/ng-table.min.css +3 -0
- data/resources/assets/angular/ng-table.min.js +3 -0
- data/resources/assets/angular/ui-bootstrap-tpls.min.js +10 -0
- data/resources/assets/bootstrap/bootstrap.min.css +9 -0
- data/resources/assets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/resources/assets/fonts/glyphicons-halflings-regular.svg +229 -0
- data/resources/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/resources/assets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/resources/assets/pygments/autumn.css +58 -0
- data/resources/assets/pygments/borland.css +46 -0
- data/resources/assets/pygments/bw.css +34 -0
- data/resources/assets/pygments/colorful.css +61 -0
- data/resources/assets/pygments/default.css +62 -0
- data/resources/assets/pygments/emacs.css +61 -0
- data/resources/assets/pygments/friendly.css +61 -0
- data/resources/assets/pygments/fruity.css +69 -0
- data/resources/assets/pygments/github.css +61 -0
- data/resources/assets/pygments/manni.css +61 -0
- data/resources/assets/pygments/monokai.css +64 -0
- data/resources/assets/pygments/murphy.css +61 -0
- data/resources/assets/pygments/native.css +69 -0
- data/resources/assets/pygments/pastie.css +60 -0
- data/resources/assets/pygments/perldoc.css +58 -0
- data/resources/assets/pygments/tango.css +69 -0
- data/resources/assets/pygments/trac.css +59 -0
- data/resources/assets/pygments/vim.css +69 -0
- data/resources/assets/pygments/vs.css +33 -0
- data/resources/assets/pygments/zenburn.css +1 -0
- data/resources/assets/style.css +56 -0
- data/resources/code_sample.tt +2 -0
- data/resources/generators/dashboard/files/dashboard.html.tt +51 -0
- data/resources/generators/dashboard/files/dashboard.js +26 -0
- data/resources/generators/dashboard/templates/_test_report.html.haml +91 -0
- data/resources/generators/todo/templates/todo.md.tt +6 -0
- data/resources/generators/todo/todo_template.rb +1 -0
- data/samples/.gitignore +2 -0
- data/samples/_markdown.md +5 -0
- data/samples/bootstrap.sh +2 -0
- data/samples/clone.sh +2 -0
- data/samples/code2doc.sh +5 -0
- data/samples/default_bootstrap.rb +7 -0
- data/samples/detect.sh +2 -0
- data/samples/exec.sh +2 -0
- data/samples/omnitest.yaml +24 -0
- data/samples/omnitest_simple.yaml +8 -0
- data/samples/scripts/bootstrap +3 -0
- data/samples/show.sh +4 -0
- data/samples/skeptic.yaml +13 -0
- data/samples/skeptic_simple.yaml +9 -0
- data/samples/test.sh +2 -0
- data/samples/tests/omnitest/validators.rb +23 -0
- data/samples/verify.sh +3 -0
- data/scripts/bootstrap.ps1 +7 -0
- data/scripts/run_script.sh +4 -0
- data/skeptic.yaml +26 -0
- data/spec/fabricators/project_fabricator.rb +19 -0
- data/spec/fabricators/scenario_fabricator.rb +6 -0
- data/spec/fabricators/test_manifest_fabricator.rb +41 -0
- data/spec/fabricators/validator_fabricator.rb +12 -0
- data/spec/fixtures/factorial.py +18 -0
- data/spec/fixtures/omnitest.yaml +11 -0
- data/spec/fixtures/skeptic.yaml +16 -0
- data/spec/fixtures/src-doc/_scenario.md.erb +1 -0
- data/spec/fixtures/src-doc/quine.md.erb +20 -0
- data/spec/omnitest/cli_spec.rb +38 -0
- data/spec/omnitest/configuration_spec.rb +25 -0
- data/spec/omnitest/documentation_generator_spec.rb +59 -0
- data/spec/omnitest/file_finder_spec.rb +21 -0
- data/spec/omnitest/project_spec.rb +65 -0
- data/spec/omnitest_spec.rb +13 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/thor_spy.rb +66 -0
- data/tests/omnitest/bootstrap_validations.rb +7 -0
- data/tests/omnitest/show_validations.rb +22 -0
- data/yard_macros.rb +25 -0
- metadata +470 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Fabricator(:validator, from: Omnitest::Skeptic::Validator) do
|
|
2
|
+
initialize_with do
|
|
3
|
+
callback = @_transient_attributes.delete :callback
|
|
4
|
+
desc = @_transient_attributes.delete :description
|
|
5
|
+
scope = @_transient_attributes
|
|
6
|
+
@_klass.new(desc, scope, &callback)
|
|
7
|
+
end # Hash based initialization
|
|
8
|
+
transient description: 'Sample validator'
|
|
9
|
+
transient suite: LANGUAGES.sample
|
|
10
|
+
transient scenario: SCENARIO_NAMES.sample
|
|
11
|
+
transient callback: Proc.new { Proc.new { |_scenario| } } # rubocop:disable Proc
|
|
12
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Content above the snippet is ignored
|
|
3
|
+
|
|
4
|
+
print 'Hello, world!'
|
|
5
|
+
|
|
6
|
+
# {{snippet factorial}}
|
|
7
|
+
def factorial(n):
|
|
8
|
+
if n == 0:
|
|
9
|
+
return 1
|
|
10
|
+
else:
|
|
11
|
+
return n * factorial(n-1)
|
|
12
|
+
# {{endsnippet}}
|
|
13
|
+
|
|
14
|
+
# So is content below the snippet
|
|
15
|
+
print "{{snippet factorial_result}}"
|
|
16
|
+
print "The result of factorial(7) is:"
|
|
17
|
+
print " %d" % factorial(7)
|
|
18
|
+
print "{{endsnippet}}"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
I am a generic template that is being used for the <%= scenario %> scenario.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Quines
|
|
2
|
+
|
|
3
|
+
This document is a small collection of quines. This documentation is generated from a [Omnitest](https://github.com/omnitest/omnitest) that validated each quine.
|
|
4
|
+
|
|
5
|
+
Examples for <%= scenario %> scenario:
|
|
6
|
+
|
|
7
|
+
<% Omnitest.projects.each do |project| %>
|
|
8
|
+
## <%= project %> <%#= project.name %>
|
|
9
|
+
|
|
10
|
+
Source:
|
|
11
|
+
|
|
12
|
+
```<%#= project.language %>
|
|
13
|
+
<%#= project.sample_code_for scenario %>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Output:
|
|
17
|
+
```
|
|
18
|
+
<%#= project.result_for scenario %>
|
|
19
|
+
```
|
|
20
|
+
<% end %>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'omnitest/cli'
|
|
3
|
+
|
|
4
|
+
module Omnitest
|
|
5
|
+
module CLI
|
|
6
|
+
describe OmnitestCLI do
|
|
7
|
+
let(:kernel) { double(:kernel) }
|
|
8
|
+
subject { ThorSpy.on(described_class, kernel) }
|
|
9
|
+
describe 'bootstrap' do
|
|
10
|
+
context 'with no args' do
|
|
11
|
+
xit 'calls bootstrap on each project' do
|
|
12
|
+
expect(kernel).to receive(:exit).with(0)
|
|
13
|
+
# TODO: Any way to test each project is called? We can't use
|
|
14
|
+
# `Omnitest.projects` because it will be reloaded.
|
|
15
|
+
subject.bootstrap
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context 'with an existing project' do
|
|
20
|
+
xit 'calls bootstrap on the project' do
|
|
21
|
+
# expect(@project).to receive(:bootstrap)
|
|
22
|
+
expect(kernel).to receive(:exit).with(0)
|
|
23
|
+
subject.bootstrap('test')
|
|
24
|
+
expect(subject.stderr.string).to eq('')
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'with an non-existant project' do
|
|
29
|
+
it 'fails' do
|
|
30
|
+
expect(kernel).to receive(:exit).with(1)
|
|
31
|
+
subject.bootstrap('missing')
|
|
32
|
+
expect(subject.stderr.string).to include('No projects matching regex `missing\'')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Omnitest
|
|
2
|
+
describe Configuration do
|
|
3
|
+
subject(:configuration) { Configuration.new }
|
|
4
|
+
|
|
5
|
+
describe '.project_set' do
|
|
6
|
+
it 'parses the YAML file and registers the project set' do
|
|
7
|
+
original_project_set = configuration.project_set
|
|
8
|
+
configuration.project_set = 'spec/fixtures/omnitest.yaml'
|
|
9
|
+
new_project_set = configuration.project_set
|
|
10
|
+
expect(original_project_set).to_not eq(new_project_set)
|
|
11
|
+
expect(new_project_set).to(be_an_instance_of(ProjectSet))
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe '.manifest' do
|
|
16
|
+
it 'parses the YAML file and registers the manifest' do
|
|
17
|
+
original_manifest = configuration.skeptic.manifest
|
|
18
|
+
configuration.skeptic.manifest_file = 'spec/fixtures/skeptic.yaml'
|
|
19
|
+
new_manifest = configuration.skeptic.manifest
|
|
20
|
+
expect(original_manifest).to_not eq(new_manifest)
|
|
21
|
+
expect(new_manifest).to(be_an_instance_of(Skeptic::TestManifest))
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Omnitest
|
|
2
|
+
describe DocumentationGenerator do
|
|
3
|
+
let(:scenario_name) { 'Quine' }
|
|
4
|
+
# let(:search_path) { 'spec/fixtures/src-doc' }
|
|
5
|
+
let(:bound_data) { double }
|
|
6
|
+
|
|
7
|
+
describe 'process' do
|
|
8
|
+
let(:generated_doc) { generator.process bound_data }
|
|
9
|
+
|
|
10
|
+
context 'when template is readable' do
|
|
11
|
+
subject(:generator) { DocumentationGenerator.new('spec/fixtures/src-doc/quine.md.erb', scenario_name) }
|
|
12
|
+
|
|
13
|
+
it 'processes the template' do
|
|
14
|
+
expect(generated_doc).to include 'Examples for Quine scenario:'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'when template is not readable' do
|
|
19
|
+
subject(:generator) { DocumentationGenerator.new('non_existant_file.md', scenario_name) }
|
|
20
|
+
it 'processes the template' do
|
|
21
|
+
expect(generated_doc).to be_nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe 'code2doc' do
|
|
27
|
+
subject(:generator) { DocumentationGenerator.new }
|
|
28
|
+
|
|
29
|
+
let(:source_code) do
|
|
30
|
+
<<-eos.gsub(/^( |\t)+/, '')
|
|
31
|
+
#!/usr/bin/env ruby
|
|
32
|
+
|
|
33
|
+
# Comments are documentation
|
|
34
|
+
puts 'And this is a code block'
|
|
35
|
+
eos
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
let(:source_file) do
|
|
39
|
+
file = Tempfile.new(['source', '.rb'])
|
|
40
|
+
file.write source_code
|
|
41
|
+
file.close
|
|
42
|
+
file.path
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'converts source code to documentation' do
|
|
46
|
+
expect(generator.code2doc(source_file, 'ruby')).to eq(
|
|
47
|
+
<<-eos.gsub(/^( |\t)+/, '')
|
|
48
|
+
Comments are documentation
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
puts 'And this is a code block'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
eos
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Omnitest
|
|
2
|
+
module Core
|
|
3
|
+
describe FileSystem do
|
|
4
|
+
it 'finds files within the search path' do
|
|
5
|
+
search_path = 'spec/fixtures/src-doc'
|
|
6
|
+
file = subject.find_file search_path, 'quine'
|
|
7
|
+
expect(file.relative_path_from path(search_path)).to eq(path('quine.md.erb'))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'raises Errno::ENOENT if no file is found' do
|
|
11
|
+
expect { subject.find_file 'spec/fixtures/src-doc', 'quinez' }.to raise_error Errno::ENOENT
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def path(p)
|
|
17
|
+
Pathname.new p
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Omnitest
|
|
4
|
+
describe Project do
|
|
5
|
+
subject(:project) { described_class.new(name: 'test', language: 'ruby', basedir: expected_project_dir) }
|
|
6
|
+
let(:expected_project_dir) { 'samples/sdks/foo' }
|
|
7
|
+
let(:psychic) { double('psychic') }
|
|
8
|
+
let(:psychic) { double('global psychic', basedir: current_dir) }
|
|
9
|
+
let(:expected_project_path) { Pathname.new(expected_project_dir) }
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
subject.psychic = psychic
|
|
13
|
+
Omnitest.psychic = psychic
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe '#bootstrap' do
|
|
17
|
+
# Need an project that's already cloned
|
|
18
|
+
let(:expected_project_dir) { 'samples/sdks/ruby' }
|
|
19
|
+
|
|
20
|
+
it 'executes script/bootstrap' do
|
|
21
|
+
task = double('task')
|
|
22
|
+
expect(task).to receive(:execute)
|
|
23
|
+
expect(psychic).to receive(:task).with('bootstrap').and_return(task)
|
|
24
|
+
project.bootstrap
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe '#clone' do
|
|
29
|
+
it 'does nothing if there is no clone option' do
|
|
30
|
+
expect(psychic).to_not receive(:execute)
|
|
31
|
+
project.clone
|
|
32
|
+
|
|
33
|
+
project.clone
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'with git as a simple string' do
|
|
37
|
+
it 'clones the repo specified by the string' do
|
|
38
|
+
project.git = 'git@github.com/foo/bar'
|
|
39
|
+
expect(psychic).to receive(:execute).with("git clone git@github.com/foo/bar -b master #{expected_project_path}")
|
|
40
|
+
project.clone
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'with git as a hash' do
|
|
45
|
+
it 'clones the repo specified by the repo parameter' do
|
|
46
|
+
project.git = { repo: 'git@github.com/foo/bar' }
|
|
47
|
+
expect(psychic).to receive(:execute).with("git clone git@github.com/foo/bar -b master #{expected_project_path}")
|
|
48
|
+
project.clone
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'clones the repo on the branch specified by the brach parameter' do
|
|
52
|
+
project.git = { repo: 'git@github.com/foo/bar', branch: 'quuz' }
|
|
53
|
+
expect(psychic).to receive(:execute).with("git clone git@github.com/foo/bar -b quuz #{expected_project_path}")
|
|
54
|
+
project.clone
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'clones the repo to the location specified by the to parameter' do
|
|
58
|
+
project.git = { repo: 'git@github.com/foo/bar', to: 'sdks/foo' }
|
|
59
|
+
expect(psychic).to receive(:execute).with('git clone git@github.com/foo/bar -b master sdks/foo')
|
|
60
|
+
project.clone
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Omnitest do
|
|
4
|
+
describe '.validate' do
|
|
5
|
+
context 'block given' do
|
|
6
|
+
it 'creates and registers a validator' do
|
|
7
|
+
Omnitest.validate 'custom validator', suite: 'test', scenario: 'test' do |_scenario|
|
|
8
|
+
# Validate the scenario results
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'simplecov'
|
|
2
|
+
SimpleCov.start
|
|
3
|
+
|
|
4
|
+
require 'omnitest'
|
|
5
|
+
require 'fabrication'
|
|
6
|
+
require 'thor_spy'
|
|
7
|
+
require 'aruba'
|
|
8
|
+
require 'aruba/api'
|
|
9
|
+
|
|
10
|
+
# Config required for project
|
|
11
|
+
RSpec.configure do | config |
|
|
12
|
+
config.include Aruba::Api
|
|
13
|
+
config.before(:example) do
|
|
14
|
+
@aruba_timeout_seconds = 30
|
|
15
|
+
clean_current_dir
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
RSpec.configure do |c|
|
|
20
|
+
c.before(:each) do
|
|
21
|
+
Omnitest.reset
|
|
22
|
+
end
|
|
23
|
+
c.expose_current_running_example_as :example
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# For Fabricators
|
|
27
|
+
LANGUAGES = %w(java ruby python nodejs c# golang php)
|
|
28
|
+
SCENARIO_NAMES = [
|
|
29
|
+
'hello world',
|
|
30
|
+
'quine',
|
|
31
|
+
'my_kata'
|
|
32
|
+
]
|
data/spec/thor_spy.rb
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
class ThorSpy
|
|
2
|
+
attr_reader :stdout, :stdin, :stderr
|
|
3
|
+
attr_accessor :app
|
|
4
|
+
|
|
5
|
+
def self.on(app, kernel = Kernel)
|
|
6
|
+
new([], StringIO.new, StringIO.new, StringIO.new, kernel).with_app(app)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Allow everything fun to be injected from the outside while defaulting to normal implementations.
|
|
10
|
+
def initialize(argv = [], stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = Kernel)
|
|
11
|
+
@argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def app
|
|
15
|
+
fail 'You must set the Thor app via ThorSpy.on or #with_app before calling execute!' unless @app
|
|
16
|
+
@app
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def with_app(app)
|
|
20
|
+
fail ArgumentError, 'app should be a class' unless app.is_a? Class
|
|
21
|
+
fail ArgumentError, 'app should be a subclass of Thor' unless app < Thor
|
|
22
|
+
@app = app
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def execute!
|
|
27
|
+
exit_code = begin
|
|
28
|
+
# Thor accesses these streams directly rather than letting them be injected, so we replace them...
|
|
29
|
+
$stderr = @stderr
|
|
30
|
+
$stdin = @stdin
|
|
31
|
+
$stdout = @stdout
|
|
32
|
+
|
|
33
|
+
fail 'You must set the Thor app' if @app.nil?
|
|
34
|
+
|
|
35
|
+
# Run our normal Thor app the way we know and love.
|
|
36
|
+
app.start(@argv)
|
|
37
|
+
|
|
38
|
+
# Thor::Base#start does not have a return value, assume success if no exception is raised.
|
|
39
|
+
0
|
|
40
|
+
rescue StandardError => e
|
|
41
|
+
# The ruby interpreter would pipe this to STDERR and exit 1 in the case of an unhandled exception
|
|
42
|
+
b = e.backtrace
|
|
43
|
+
b.unshift("#{b.shift}: #{e.message} (#{e.class})")
|
|
44
|
+
@stderr.puts(b.map { |s| "\tfrom #{s}" }.join("\n"))
|
|
45
|
+
1
|
|
46
|
+
rescue SystemExit => e
|
|
47
|
+
e.status
|
|
48
|
+
ensure
|
|
49
|
+
# ...then we put them back.
|
|
50
|
+
$stderr = STDERR
|
|
51
|
+
$stdin = STDIN
|
|
52
|
+
$stdout = STDOUT
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Proxy our exit code back to the injected kernel.
|
|
56
|
+
@kernel.exit(exit_code)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def method_missing(meth, *args)
|
|
60
|
+
# I don't think a block makes sense, unless it's stdin.
|
|
61
|
+
return super if block_given?
|
|
62
|
+
|
|
63
|
+
@argv = [meth.to_s].concat(args)
|
|
64
|
+
execute!
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
Omnitest.validate 'Bootstraps java and ruby, but not python', suite: 'CLI', scenario: 'bootstrap' do |scenario|
|
|
4
|
+
expect(scenario.result.stdout).to include('-----> Bootstrapping java')
|
|
5
|
+
expect(scenario.result.stdout).to include('-----> Bootstrapping ruby')
|
|
6
|
+
expect(scenario.result.stdout).to_not include('-----> Bootstrapping python')
|
|
7
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
Omnitest.validate 'Expected output for show', suite: 'Reports', scenario: 'show' do |scenario|
|
|
4
|
+
expected_output = <<-eos
|
|
5
|
+
katas-hello_world-ruby: Fully Verified (2 of 2)
|
|
6
|
+
Test suite: Katas
|
|
7
|
+
Test scenario: hello world
|
|
8
|
+
Project: ruby
|
|
9
|
+
Source: sdks/ruby/katas/hello_world.rb
|
|
10
|
+
Execution result:
|
|
11
|
+
Exit Status: 0
|
|
12
|
+
Stdout:
|
|
13
|
+
Hello, world!
|
|
14
|
+
Stderr:
|
|
15
|
+
Validations:
|
|
16
|
+
Hello world validator: ✓ Passed
|
|
17
|
+
default validator: ✓ Passed
|
|
18
|
+
Data from spies:
|
|
19
|
+
eos
|
|
20
|
+
cleaned_up = scenario.result.stdout.gsub(/\e\[(\d+)(;\d+)*m/, '').gsub("\r\n", "\n")
|
|
21
|
+
expect(cleaned_up).to include(expected_output)
|
|
22
|
+
end
|