omnitest 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|