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.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +0 -0
  4. data/.groc.json +7 -0
  5. data/.rspec +6 -0
  6. data/.rubocop.yml +5 -0
  7. data/.rubocop_todo.yml +47 -0
  8. data/.travis.yml +12 -0
  9. data/.yardopts +3 -0
  10. data/Gemfile +26 -0
  11. data/README.md +341 -0
  12. data/Rakefile +33 -0
  13. data/appveyor.yml +9 -0
  14. data/bin/omnidoc +5 -0
  15. data/bin/omnitask +5 -0
  16. data/bin/omnitest +5 -0
  17. data/bower.json +21 -0
  18. data/doc-src/index.md.tt +341 -0
  19. data/doc-src/project_sets.md.tt +31 -0
  20. data/doc-src/usage/crosstask.md.tt +86 -0
  21. data/doc-src/usage/omnitest.md.tt +87 -0
  22. data/features/bootstrapping.feature +25 -0
  23. data/features/cloning.feature +32 -0
  24. data/features/fixtures/configs/omnitest_sample.yaml +11 -0
  25. data/features/fixtures/configs/skeptic_empty.yaml +12 -0
  26. data/features/fixtures/configs/skeptic_hello_world.yaml +10 -0
  27. data/features/show.feature +38 -0
  28. data/features/states.feature +40 -0
  29. data/features/step_definitions/sdk_steps.rb +22 -0
  30. data/features/support/env.rb +9 -0
  31. data/lib/omnitest.rb +211 -0
  32. data/lib/omnitest/cli.rb +297 -0
  33. data/lib/omnitest/command.rb +103 -0
  34. data/lib/omnitest/command/generate.rb +29 -0
  35. data/lib/omnitest/command/generators/code2doc.rb +79 -0
  36. data/lib/omnitest/command/generators/dashboard.rb +148 -0
  37. data/lib/omnitest/command/generators/documentation.rb +119 -0
  38. data/lib/omnitest/command/list.rb +62 -0
  39. data/lib/omnitest/command/project_action.rb +26 -0
  40. data/lib/omnitest/command/scenario_action.rb +20 -0
  41. data/lib/omnitest/command/show.rb +148 -0
  42. data/lib/omnitest/command/task.rb +27 -0
  43. data/lib/omnitest/command/test.rb +41 -0
  44. data/lib/omnitest/configuration.rb +53 -0
  45. data/lib/omnitest/documentation_generator.rb +68 -0
  46. data/lib/omnitest/project.rb +100 -0
  47. data/lib/omnitest/project_logger.rb +273 -0
  48. data/lib/omnitest/project_set.rb +47 -0
  49. data/lib/omnitest/reporters.rb +27 -0
  50. data/lib/omnitest/reporters/hash_reporter.rb +32 -0
  51. data/lib/omnitest/reporters/json_reporter.rb +12 -0
  52. data/lib/omnitest/reporters/markdown_reporter.rb +26 -0
  53. data/lib/omnitest/reporters/yaml_reporter.rb +12 -0
  54. data/lib/omnitest/run_action.rb +44 -0
  55. data/lib/omnitest/version.rb +3 -0
  56. data/lib/omnitest/workflow.rb +5 -0
  57. data/mkdocs.yml +8 -0
  58. data/omnitest.gemspec +39 -0
  59. data/omnitest.yaml +5 -0
  60. data/resources/assets/angular/angular.min.js +217 -0
  61. data/resources/assets/angular/angular.min.js.map +8 -0
  62. data/resources/assets/angular/json-formatter.min.css +6 -0
  63. data/resources/assets/angular/json-formatter.min.js +7 -0
  64. data/resources/assets/angular/ng-table.map +1 -0
  65. data/resources/assets/angular/ng-table.min.css +3 -0
  66. data/resources/assets/angular/ng-table.min.js +3 -0
  67. data/resources/assets/angular/ui-bootstrap-tpls.min.js +10 -0
  68. data/resources/assets/bootstrap/bootstrap.min.css +9 -0
  69. data/resources/assets/fonts/glyphicons-halflings-regular.eot +0 -0
  70. data/resources/assets/fonts/glyphicons-halflings-regular.svg +229 -0
  71. data/resources/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
  72. data/resources/assets/fonts/glyphicons-halflings-regular.woff +0 -0
  73. data/resources/assets/pygments/autumn.css +58 -0
  74. data/resources/assets/pygments/borland.css +46 -0
  75. data/resources/assets/pygments/bw.css +34 -0
  76. data/resources/assets/pygments/colorful.css +61 -0
  77. data/resources/assets/pygments/default.css +62 -0
  78. data/resources/assets/pygments/emacs.css +61 -0
  79. data/resources/assets/pygments/friendly.css +61 -0
  80. data/resources/assets/pygments/fruity.css +69 -0
  81. data/resources/assets/pygments/github.css +61 -0
  82. data/resources/assets/pygments/manni.css +61 -0
  83. data/resources/assets/pygments/monokai.css +64 -0
  84. data/resources/assets/pygments/murphy.css +61 -0
  85. data/resources/assets/pygments/native.css +69 -0
  86. data/resources/assets/pygments/pastie.css +60 -0
  87. data/resources/assets/pygments/perldoc.css +58 -0
  88. data/resources/assets/pygments/tango.css +69 -0
  89. data/resources/assets/pygments/trac.css +59 -0
  90. data/resources/assets/pygments/vim.css +69 -0
  91. data/resources/assets/pygments/vs.css +33 -0
  92. data/resources/assets/pygments/zenburn.css +1 -0
  93. data/resources/assets/style.css +56 -0
  94. data/resources/code_sample.tt +2 -0
  95. data/resources/generators/dashboard/files/dashboard.html.tt +51 -0
  96. data/resources/generators/dashboard/files/dashboard.js +26 -0
  97. data/resources/generators/dashboard/templates/_test_report.html.haml +91 -0
  98. data/resources/generators/todo/templates/todo.md.tt +6 -0
  99. data/resources/generators/todo/todo_template.rb +1 -0
  100. data/samples/.gitignore +2 -0
  101. data/samples/_markdown.md +5 -0
  102. data/samples/bootstrap.sh +2 -0
  103. data/samples/clone.sh +2 -0
  104. data/samples/code2doc.sh +5 -0
  105. data/samples/default_bootstrap.rb +7 -0
  106. data/samples/detect.sh +2 -0
  107. data/samples/exec.sh +2 -0
  108. data/samples/omnitest.yaml +24 -0
  109. data/samples/omnitest_simple.yaml +8 -0
  110. data/samples/scripts/bootstrap +3 -0
  111. data/samples/show.sh +4 -0
  112. data/samples/skeptic.yaml +13 -0
  113. data/samples/skeptic_simple.yaml +9 -0
  114. data/samples/test.sh +2 -0
  115. data/samples/tests/omnitest/validators.rb +23 -0
  116. data/samples/verify.sh +3 -0
  117. data/scripts/bootstrap.ps1 +7 -0
  118. data/scripts/run_script.sh +4 -0
  119. data/skeptic.yaml +26 -0
  120. data/spec/fabricators/project_fabricator.rb +19 -0
  121. data/spec/fabricators/scenario_fabricator.rb +6 -0
  122. data/spec/fabricators/test_manifest_fabricator.rb +41 -0
  123. data/spec/fabricators/validator_fabricator.rb +12 -0
  124. data/spec/fixtures/factorial.py +18 -0
  125. data/spec/fixtures/omnitest.yaml +11 -0
  126. data/spec/fixtures/skeptic.yaml +16 -0
  127. data/spec/fixtures/src-doc/_scenario.md.erb +1 -0
  128. data/spec/fixtures/src-doc/quine.md.erb +20 -0
  129. data/spec/omnitest/cli_spec.rb +38 -0
  130. data/spec/omnitest/configuration_spec.rb +25 -0
  131. data/spec/omnitest/documentation_generator_spec.rb +59 -0
  132. data/spec/omnitest/file_finder_spec.rb +21 -0
  133. data/spec/omnitest/project_spec.rb +65 -0
  134. data/spec/omnitest_spec.rb +13 -0
  135. data/spec/spec_helper.rb +32 -0
  136. data/spec/thor_spy.rb +66 -0
  137. data/tests/omnitest/bootstrap_validations.rb +7 -0
  138. data/tests/omnitest/show_validations.rb +22 -0
  139. data/yard_macros.rb +25 -0
  140. 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,11 @@
1
+ ---
2
+ projects:
3
+ ruby:
4
+ language: 'ruby'
5
+ basedir: 'sdks/ruby'
6
+ java:
7
+ language: 'java'
8
+ basedir: 'sdks/java'
9
+ python:
10
+ language: 'python'
11
+ basedir: 'sdks/python'
@@ -0,0 +1,16 @@
1
+ ---
2
+ global_env:
3
+ LOCALE: <%= ENV['LANG'] %>
4
+ FAVORITE_NUMBER: 5
5
+ suites:
6
+ Katas:
7
+ env:
8
+ NAME: 'Max'
9
+ samples:
10
+ - hello world
11
+ - quine
12
+ Tutorials:
13
+ env:
14
+ samples:
15
+ - deploying
16
+ - documenting
@@ -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
@@ -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
+ ]
@@ -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