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,148 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'tilt'
|
|
3
|
+
require 'haml'
|
|
4
|
+
require 'omnitest/reporters'
|
|
5
|
+
|
|
6
|
+
module Omnitest
|
|
7
|
+
module Command
|
|
8
|
+
class Generate
|
|
9
|
+
class Dashboard < Thor::Group
|
|
10
|
+
include Thor::Actions
|
|
11
|
+
include Omnitest::Core::FileSystem
|
|
12
|
+
module Helpers
|
|
13
|
+
include Omnitest::Core::Util::String
|
|
14
|
+
# include Padrino::Helpers::RenderHelpers # requires sinatra-compatible render method
|
|
15
|
+
include Padrino::Helpers::TagHelpers
|
|
16
|
+
include Padrino::Helpers::OutputHelpers
|
|
17
|
+
include Padrino::Helpers::AssetTagHelpers
|
|
18
|
+
|
|
19
|
+
def projects
|
|
20
|
+
Omnitest.projects.map do |project|
|
|
21
|
+
slugify(project.name)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def results
|
|
26
|
+
rows = []
|
|
27
|
+
grouped_scenarios = Omnitest.scenarios.group_by { |scenario| [scenario.suite, scenario.name] }
|
|
28
|
+
grouped_scenarios.each do |(suite, name), scenarios|
|
|
29
|
+
row = {
|
|
30
|
+
slug_prefix: slugify(suite, name),
|
|
31
|
+
suite: suite,
|
|
32
|
+
scenario: name
|
|
33
|
+
}
|
|
34
|
+
Omnitest.projects.each do |project|
|
|
35
|
+
scenario = scenarios.find { |s| s.psychic.name == project.name }
|
|
36
|
+
row[slugify(project.name)] = scenario.status_description
|
|
37
|
+
end
|
|
38
|
+
rows << row
|
|
39
|
+
end
|
|
40
|
+
rows
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def as_json(data)
|
|
44
|
+
JSON.dump(data)
|
|
45
|
+
rescue => e
|
|
46
|
+
JSON.dump(to_utf(data))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def to_utf(data)
|
|
50
|
+
Hash[
|
|
51
|
+
data.collect do |k, v|
|
|
52
|
+
if v.respond_to?(:collect)
|
|
53
|
+
[k, to_utf(v)]
|
|
54
|
+
elsif v.respond_to?(:encoding)
|
|
55
|
+
[k, v.dup.encode('UTF-8')]
|
|
56
|
+
else
|
|
57
|
+
[k, v]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def status(status, msg = nil, _color = :cyan)
|
|
64
|
+
"<strong>#{status}</strong> <em>#{msg}</em>"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def bootstrap_color(color)
|
|
68
|
+
bootstrap_classes = {
|
|
69
|
+
green: 'success',
|
|
70
|
+
cyan: 'primary',
|
|
71
|
+
red: 'danger',
|
|
72
|
+
yellow: 'warning'
|
|
73
|
+
}
|
|
74
|
+
bootstrap_classes.key?(color) ? bootstrap_classes[color] : color
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
include Helpers
|
|
79
|
+
|
|
80
|
+
class_option :destination, default: 'reports/'
|
|
81
|
+
class_option :code_style, default: 'github'
|
|
82
|
+
|
|
83
|
+
def self.source_root
|
|
84
|
+
Omnitest::Reporters::GENERATORS_DIR
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def report_name
|
|
88
|
+
@report_name ||= self.class.name.downcase.split('::').last
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def add_framework_to_source_root
|
|
92
|
+
source_paths.map do | path |
|
|
93
|
+
path << "/#{report_name}"
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def set_destination_root
|
|
98
|
+
self.destination_root = options[:destination]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def setup
|
|
102
|
+
@tabs = {}
|
|
103
|
+
@tabs['Dashboard'] = 'dashboard.html'
|
|
104
|
+
Omnitest.update_config!(options)
|
|
105
|
+
Omnitest.setup
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def create_spy_reports
|
|
109
|
+
reports = Omnitest::Skeptic::Spies.reports[:dashboard]
|
|
110
|
+
reports.each do | report_class |
|
|
111
|
+
if report_class.respond_to? :tab_name
|
|
112
|
+
@active_tab = report_class.tab_name
|
|
113
|
+
@tabs[@active_tab] = report_class.tab_target
|
|
114
|
+
else
|
|
115
|
+
@active_tab = nil
|
|
116
|
+
end
|
|
117
|
+
report_class.tabs = @tabs
|
|
118
|
+
invoke report_class, args, options
|
|
119
|
+
end if reports
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def copy_assets
|
|
123
|
+
directory Omnitest::Reporters::ASSETS_DIR, 'assets'
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def copy_base_structure
|
|
127
|
+
@active_tab = 'Dashboard'
|
|
128
|
+
directory 'files', '.'
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def create_results_json
|
|
132
|
+
create_file 'matrix.json', as_json(results)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def create_test_reports
|
|
136
|
+
template_file = find_in_source_paths('templates/_test_report.html.haml')
|
|
137
|
+
template = Tilt.new(template_file)
|
|
138
|
+
Omnitest.scenarios.each do |scenario|
|
|
139
|
+
@scenario = scenario
|
|
140
|
+
add_file "details/#{scenario.slug}.html" do
|
|
141
|
+
template.render(self)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'omnitest/reporters'
|
|
3
|
+
|
|
4
|
+
module Omnitest
|
|
5
|
+
module Command
|
|
6
|
+
class Generate
|
|
7
|
+
class Documentation < Thor::Group
|
|
8
|
+
include Thor::Actions
|
|
9
|
+
include Omnitest::Core::FileSystem
|
|
10
|
+
include Omnitest::Psychic::Code2Doc::CodeHelper
|
|
11
|
+
include Omnitest::Psychic::Code2Doc::SnippetHelper
|
|
12
|
+
|
|
13
|
+
BUILTIN_GENERATORS = Dir["#{Omnitest::Reporters::GENERATORS_DIR}/*"].select { |f| File.directory? f }
|
|
14
|
+
|
|
15
|
+
attr_reader :projects, :project, :project_name, :project_basedir
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
def generators
|
|
19
|
+
BUILTIN_GENERATORS + Dir['tests/omnitest/generators/*'].select { |f| File.directory? f }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def generator_names
|
|
23
|
+
generators.map { |d| File.basename d }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def generator_not_found(generator)
|
|
27
|
+
s = "ERROR: No generator named #{generator}, available generators: "
|
|
28
|
+
s << generator_names.join(', ')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def source_root
|
|
32
|
+
Omnitest::RESOURCES_DIR
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
argument :project_regexp, default: 'all'
|
|
37
|
+
argument :scenario_regexp, default: 'all'
|
|
38
|
+
class_option :source, default: 'doc-src/', desc: 'Source folder with documentation templates'
|
|
39
|
+
class_option :destination, default: 'docs/', desc: 'Destination for generated documentation'
|
|
40
|
+
class_option :template, desc: 'The name or location of a custom generator template'
|
|
41
|
+
class_option :scope, desc: 'Whether the template should be applied once (global), per project, or per scenario',
|
|
42
|
+
enum: %w(global project scenario), default: 'global'
|
|
43
|
+
class_option :failed, type: :boolean, desc: 'Only list tests that failed / passed'
|
|
44
|
+
class_option :skipped, type: :boolean, desc: 'Only list tests that were skipped / executed'
|
|
45
|
+
class_option :samples, type: :boolean, desc: 'Only list tests that have sample code / do not have sample code'
|
|
46
|
+
class_option :travis, type: :boolean, desc: "Enable/disable delegation to travis-build, if it's available"
|
|
47
|
+
def setup
|
|
48
|
+
Omnitest.update_config!(options)
|
|
49
|
+
Omnitest.setup
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def set_source_and_destination
|
|
53
|
+
unless options[:template] || File.exist?(options[:source])
|
|
54
|
+
abort 'Either the --source directory must exist, or --template must be specified'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
if options[:template]
|
|
58
|
+
generator = self.class.generators.find { |d| File.basename(d) == options[:template] }
|
|
59
|
+
abort self.class.generator_not_found(generator) if generator.nil?
|
|
60
|
+
source_paths << generator
|
|
61
|
+
else
|
|
62
|
+
source_paths << Pathname(options[:source]).expand_path
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
self.destination_root = options[:destination]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def apply_template
|
|
69
|
+
if options[:template]
|
|
70
|
+
generator_script = "#{options[:template]}_template.rb"
|
|
71
|
+
apply(generator_script)
|
|
72
|
+
else
|
|
73
|
+
case options[:scope]
|
|
74
|
+
when 'global'
|
|
75
|
+
@projects = Omnitest.filter_projects(project_regexp)
|
|
76
|
+
process_directory
|
|
77
|
+
when 'project'
|
|
78
|
+
Omnitest.filter_projects(project_regexp).each do | project |
|
|
79
|
+
bind_project_variables(project)
|
|
80
|
+
process_directory
|
|
81
|
+
end
|
|
82
|
+
when 'scenario'
|
|
83
|
+
Omnitest.scenarios(project_regexp, scenario_regexp).each do | scenario |
|
|
84
|
+
bind_scenario_variables(scenario)
|
|
85
|
+
process_directory
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def scenario_output_snippet(project_regex, scenario_regex, opts = {})
|
|
94
|
+
scenario = Omnitest.scenarios(project_regex, scenario_regex).first
|
|
95
|
+
fail "Output is not available for #{scenario_name} because that scenario does not exist" unless scenario
|
|
96
|
+
fail "Output is not available for #{scenario_name} because it has not been executed" unless scenario.result
|
|
97
|
+
snippetize_output(scenario.result, opts)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def process_directory
|
|
101
|
+
directory Pathname(options[:source]).expand_path, Pathname(options[:destination]).expand_path
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def bind_project_variables(project)
|
|
105
|
+
@project = project
|
|
106
|
+
@project_name = project.name
|
|
107
|
+
@project_basedir = project.basedir
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def bind_scenario_variables(scenario)
|
|
111
|
+
bind_project_variables(scenario.project)
|
|
112
|
+
@scenario = scenario
|
|
113
|
+
@scenario_name = scenario.name
|
|
114
|
+
@scenario_slug = scenario.slug
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'omnitest/reporters'
|
|
2
|
+
module Omnitest
|
|
3
|
+
module Command
|
|
4
|
+
class List < Omnitest::Command::Base
|
|
5
|
+
include Omnitest::Reporters
|
|
6
|
+
|
|
7
|
+
def call
|
|
8
|
+
setup
|
|
9
|
+
@reporter = Omnitest::Reporters.reporter(options[:format], shell)
|
|
10
|
+
tests = parse_subcommand(args.shift, args.shift)
|
|
11
|
+
|
|
12
|
+
table = [header_row]
|
|
13
|
+
table += tests.map do | scenario |
|
|
14
|
+
row(scenario)
|
|
15
|
+
end
|
|
16
|
+
print_table(table)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def header_row
|
|
22
|
+
row = []
|
|
23
|
+
row << colorize('Suite', :green)
|
|
24
|
+
row << colorize('Scenario', :green)
|
|
25
|
+
row << colorize('Project', :green)
|
|
26
|
+
row << colorize('Status', :green)
|
|
27
|
+
row << colorize('Source', :green) if options[:source]
|
|
28
|
+
row
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def row(scenario)
|
|
32
|
+
row = []
|
|
33
|
+
row << color_pad(scenario.suite)
|
|
34
|
+
row << color_pad(scenario.name)
|
|
35
|
+
row << color_pad(scenario.psychic.name)
|
|
36
|
+
row << format_status(scenario)
|
|
37
|
+
if options[:source]
|
|
38
|
+
source_file = scenario.absolute_source_file ? scenario.source_file : colorize('<No code sample>', :red)
|
|
39
|
+
row << source_file
|
|
40
|
+
end
|
|
41
|
+
row
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def print_table(*args)
|
|
45
|
+
@reporter.print_table(*args)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def colorize(string, *args)
|
|
49
|
+
return string unless @reporter.respond_to? :set_color
|
|
50
|
+
@reporter.set_color(string, *args)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def color_pad(string)
|
|
54
|
+
string + colorize('', :white)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def format_status(scenario)
|
|
58
|
+
colorize(scenario.status_description, scenario.status_color)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'benchmark'
|
|
2
|
+
|
|
3
|
+
module Omnitest
|
|
4
|
+
module Command
|
|
5
|
+
class ProjectAction < Omnitest::Command::Base
|
|
6
|
+
include RunAction
|
|
7
|
+
|
|
8
|
+
# Invoke the command.
|
|
9
|
+
def call
|
|
10
|
+
banner "Starting Omnitest (v#{Omnitest::VERSION})"
|
|
11
|
+
elapsed = Benchmark.measure do
|
|
12
|
+
setup
|
|
13
|
+
project_regex = args.shift
|
|
14
|
+
if %w(task workflow).include? action # a bit hacky...
|
|
15
|
+
argument = project_regex
|
|
16
|
+
project_regex = args.shift
|
|
17
|
+
args.unshift argument
|
|
18
|
+
end
|
|
19
|
+
projects = select_projects(project_regex, options)
|
|
20
|
+
run_action(projects, action, options[:concurrency], *args)
|
|
21
|
+
end
|
|
22
|
+
banner "Omnitest is finished. #{Core::Util.duration(elapsed.real)}"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'benchmark'
|
|
2
|
+
|
|
3
|
+
module Omnitest
|
|
4
|
+
module Command
|
|
5
|
+
class ScenarioAction < Omnitest::Command::Base
|
|
6
|
+
include RunAction
|
|
7
|
+
|
|
8
|
+
# Invoke the command.
|
|
9
|
+
def call
|
|
10
|
+
banner "Starting Omnitest (v#{Omnitest::VERSION})"
|
|
11
|
+
elapsed = Benchmark.measure do
|
|
12
|
+
setup
|
|
13
|
+
scenarios = parse_subcommand(args.shift, args.shift)
|
|
14
|
+
run_action(scenarios, action, options[:concurrency])
|
|
15
|
+
end
|
|
16
|
+
banner "Omnitest is finished. #{Core::Util.duration(elapsed.real)}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
require 'omnitest/reporters'
|
|
2
|
+
|
|
3
|
+
module Omnitest
|
|
4
|
+
module Command
|
|
5
|
+
class Show < Omnitest::Command::Base # rubocop:disable Metrics/ClassLength
|
|
6
|
+
include Omnitest::Reporters
|
|
7
|
+
include Omnitest::Core::Util::String
|
|
8
|
+
include Omnitest::Core::FileSystem
|
|
9
|
+
|
|
10
|
+
def call
|
|
11
|
+
@indent_level = 0
|
|
12
|
+
setup
|
|
13
|
+
@reporter = Omnitest::Reporters.reporter(options[:format], shell)
|
|
14
|
+
scenarios = parse_subcommand(args.shift, args.shift)
|
|
15
|
+
|
|
16
|
+
scenarios.each do | scenario |
|
|
17
|
+
status_color = scenario.status_color.to_sym
|
|
18
|
+
status(scenario.slug, colorize(scenario.status_description, status_color), status_color)
|
|
19
|
+
indent do
|
|
20
|
+
status('Test suite', scenario.suite)
|
|
21
|
+
status('Test scenario', scenario.name)
|
|
22
|
+
status('Project', scenario.psychic.name)
|
|
23
|
+
source_file = if scenario.code_sample
|
|
24
|
+
Core::FileSystem.relativize(scenario.absolute_source_file, Dir.pwd)
|
|
25
|
+
else
|
|
26
|
+
colorize('<No code sample>', :red)
|
|
27
|
+
end
|
|
28
|
+
status('Source', source_file)
|
|
29
|
+
display_source(scenario)
|
|
30
|
+
display_execution_result(scenario)
|
|
31
|
+
display_validations(scenario)
|
|
32
|
+
display_spy_data(scenario)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def reformat(string)
|
|
40
|
+
return if string.nil? || string.empty?
|
|
41
|
+
|
|
42
|
+
indent do
|
|
43
|
+
string.gsub(/^/, indent)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def indent
|
|
48
|
+
if block_given?
|
|
49
|
+
@indent_level += 2
|
|
50
|
+
result = yield
|
|
51
|
+
@indent_level -= 2
|
|
52
|
+
result
|
|
53
|
+
else
|
|
54
|
+
' ' * @indent_level
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def display_source(test)
|
|
59
|
+
return if !options[:source] || !test.source?
|
|
60
|
+
|
|
61
|
+
shell.say test.highlighted_code
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def display_execution_result(test)
|
|
65
|
+
return if test.result.nil? || test.result.execution_result.nil?
|
|
66
|
+
|
|
67
|
+
execution_result = test.result.execution_result
|
|
68
|
+
status 'Execution result'
|
|
69
|
+
indent do
|
|
70
|
+
status('Exit Status', execution_result.exitstatus)
|
|
71
|
+
status 'Stdout'
|
|
72
|
+
say reformat(execution_result.stdout)
|
|
73
|
+
status 'Stderr'
|
|
74
|
+
say reformat(execution_result.stderr)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def display_validations(test)
|
|
79
|
+
return if test.validations.nil?
|
|
80
|
+
|
|
81
|
+
status 'Validations'
|
|
82
|
+
indent do
|
|
83
|
+
test.validations.each do | name, validation |
|
|
84
|
+
status(name, indicator(validation))
|
|
85
|
+
indent do
|
|
86
|
+
status 'Error message', validation.error if validation.error
|
|
87
|
+
unless !options[:source] || !validation.error_source?
|
|
88
|
+
status 'Validator source'
|
|
89
|
+
say highlight(validation.error_source, language: 'ruby')
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def display_spy_data(test)
|
|
97
|
+
return if test.spy_data.nil?
|
|
98
|
+
|
|
99
|
+
status 'Data from spies'
|
|
100
|
+
indent do
|
|
101
|
+
test.spy_data.each do |_spy, data|
|
|
102
|
+
indent do
|
|
103
|
+
data.each_pair do |k, v|
|
|
104
|
+
status(k, v)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def say(msg)
|
|
112
|
+
shell.say msg if msg
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def status(status, msg = nil, color = :cyan, colwidth = 50)
|
|
116
|
+
msg = yield if block_given?
|
|
117
|
+
shell.say(indent)
|
|
118
|
+
status = shell.set_color("#{status}:", color, true)
|
|
119
|
+
# The built-in say_status is right-aligned, we want left-aligned
|
|
120
|
+
shell.say format("%-#{colwidth}s %s", status, msg).rstrip
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def print_table(*args)
|
|
124
|
+
@reporter.print_table(*args)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def colorize(string, *args)
|
|
128
|
+
return string unless @reporter.respond_to? :set_color
|
|
129
|
+
@reporter.set_color(string, *args)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def color_pad(string)
|
|
133
|
+
string + colorize('', :white)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def indicator(validation)
|
|
137
|
+
case validation.status
|
|
138
|
+
when :passed
|
|
139
|
+
colorize("\u2713 Passed", :green)
|
|
140
|
+
when :failed
|
|
141
|
+
colorize('x Failed', :red)
|
|
142
|
+
else
|
|
143
|
+
colorize(validation.status, :yellow)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|