dotpretty 0.8.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/dotpretty +11 -13
- data/lib/dotpretty/http/client.rb +26 -0
- data/lib/dotpretty/http/null_client.rb +10 -0
- data/lib/dotpretty/options.rb +45 -0
- data/lib/dotpretty/parser.rb +157 -60
- data/lib/dotpretty/reporters/basic.rb +13 -7
- data/lib/dotpretty/reporters/browser.rb +60 -0
- data/lib/dotpretty/reporters/factory.rb +5 -0
- data/lib/dotpretty/reporters/json.rb +12 -7
- data/lib/dotpretty/reporters/names.rb +3 -1
- data/lib/dotpretty/reporters/progress.rb +14 -5
- data/lib/dotpretty/runner.rb +64 -10
- data/lib/dotpretty/version.rb +1 -1
- metadata +20 -3
- data/lib/dotpretty/aggregator.rb +0 -146
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c19f485b3423444380bc1288152ab158d27b1b3f0a80909d094e745ae24df8ec
|
4
|
+
data.tar.gz: ecea2dab730e241d3774d9ec13e9f216ae3b780c7d331e82791f25a0ead8579c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 39193f4dc7bc9566e5a87702610d70286cacbc9c1775aa6b58964a62cc21108db20fa4bb5ab73efbcb1fb5030e83dee6aead8aeaf5cb47374f8340a37479077e
|
7
|
+
data.tar.gz: 215b44b59aadcedd0a638701354124ebdd23a8c6cf3b22547ed4d98d57d82a1f95bf804862b752d3115efc844fa9da4c45e5fc566ff0a13187c630fb49c66c09
|
data/bin/dotpretty
CHANGED
@@ -1,21 +1,18 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require "dotpretty/color_palettes/bash"
|
6
|
-
require "dotpretty/color_palettes/null"
|
7
|
-
require "dotpretty/reporters/names"
|
3
|
+
require "dotpretty/options"
|
8
4
|
require "dotpretty/runner"
|
5
|
+
require "dotpretty/reporters/names"
|
9
6
|
require "dotpretty/version"
|
10
7
|
require "optparse"
|
11
8
|
|
12
|
-
|
9
|
+
command_line_args = {}
|
13
10
|
OptionParser.new do |opts|
|
14
11
|
|
15
12
|
opts.banner = "Usage: dotnet test -v=normal Test.Project/ | dotnet [options]"
|
16
13
|
|
17
14
|
opts.on("-c", "--color", "Enable color output") do |color|
|
18
|
-
|
15
|
+
command_line_args[:color] = color
|
19
16
|
end
|
20
17
|
|
21
18
|
opts.on("-h", "--help", "Display this help") do
|
@@ -26,7 +23,7 @@ OptionParser.new do |opts|
|
|
26
23
|
all_reporter_names = Dotpretty::Reporters::Names::ALL
|
27
24
|
reporter_message = ["Set reporter. Defaults to basic", "Available reporters: #{all_reporter_names.join(", ")}"]
|
28
25
|
opts.on("-rREPORTER", "--reporter=REPORTER", *reporter_message) do |reporter_name|
|
29
|
-
|
26
|
+
command_line_args[:reporter_name] = reporter_name
|
30
27
|
end
|
31
28
|
|
32
29
|
if STDIN.tty?
|
@@ -37,11 +34,12 @@ OptionParser.new do |opts|
|
|
37
34
|
|
38
35
|
end.parse!
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
color_palette: color_palette,
|
37
|
+
options = Dotpretty::Options.build({
|
38
|
+
color: command_line_args.fetch(:color, false),
|
43
39
|
output: STDOUT,
|
44
|
-
reporter_name:
|
40
|
+
reporter_name: command_line_args.fetch(:reporter_name, Dotpretty::Reporters::Names::BASIC)
|
45
41
|
})
|
46
|
-
|
42
|
+
|
43
|
+
runner = Dotpretty::Runner.new({ reporter: options.reporter })
|
44
|
+
STDIN.each_line { |line| runner.input_received(line) }
|
47
45
|
runner.done_with_input
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "httparty"
|
2
|
+
|
3
|
+
module Dotpretty
|
4
|
+
module Http
|
5
|
+
class Client
|
6
|
+
|
7
|
+
def initialize(api_root:)
|
8
|
+
self.api_root = api_root
|
9
|
+
end
|
10
|
+
|
11
|
+
def post_json(route, data=nil)
|
12
|
+
HTTParty.post("#{api_root}#{route}", {
|
13
|
+
body: data.to_json,
|
14
|
+
headers: {
|
15
|
+
"Content-Type": "application/json"
|
16
|
+
}
|
17
|
+
})
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_accessor :api_root
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "dotpretty/color_palettes/bash"
|
2
|
+
require "dotpretty/color_palettes/null"
|
3
|
+
require "dotpretty/http/client"
|
4
|
+
require "dotpretty/http/null_client"
|
5
|
+
require "dotpretty/reporters/factory"
|
6
|
+
|
7
|
+
module Dotpretty
|
8
|
+
class Options
|
9
|
+
|
10
|
+
def self.build(command_line_args)
|
11
|
+
color_palette = command_line_args[:color] ? Dotpretty::ColorPalettes::Bash : Dotpretty::ColorPalettes::Null
|
12
|
+
http_client = Dotpretty::Http::Client.new({
|
13
|
+
api_root: "http://localhost:4567"
|
14
|
+
})
|
15
|
+
reporter_name = command_line_args.fetch(:reporter_name)
|
16
|
+
return Dotpretty::Options.new({
|
17
|
+
color_palette: color_palette,
|
18
|
+
http_client: http_client,
|
19
|
+
output: command_line_args.fetch(:output),
|
20
|
+
reporter_name: reporter_name
|
21
|
+
})
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(color_palette:, http_client: Dotpretty::Http::NullClient.new, output:, reporter_name:)
|
25
|
+
self.color_palette = color_palette
|
26
|
+
self.http_client = http_client
|
27
|
+
self.output = output
|
28
|
+
self.reporter_name = reporter_name
|
29
|
+
end
|
30
|
+
|
31
|
+
def reporter
|
32
|
+
return Dotpretty::Reporters::Factory.build_reporter(reporter_name, {
|
33
|
+
color_palette: color_palette,
|
34
|
+
http_client: http_client,
|
35
|
+
output: output
|
36
|
+
})
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_accessor :color_palette, :http_client, :output, :reporter_name
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/lib/dotpretty/parser.rb
CHANGED
@@ -1,76 +1,173 @@
|
|
1
|
-
require "dotpretty/aggregator"
|
2
|
-
require "dotpretty/reporters/basic"
|
3
|
-
require "dotpretty/state_machine/state_machine_builder"
|
4
|
-
|
5
1
|
module Dotpretty
|
6
2
|
class Parser
|
7
3
|
|
4
|
+
BUILD_STARTED = /^Build started/
|
5
|
+
BUILD_COMPLETED = /^Build completed/
|
6
|
+
BUILD_FAILED = /^Build FAILED.$/
|
7
|
+
TEST_FAILED = /^Failed/
|
8
|
+
TEST_PASSED = /^Passed/
|
9
|
+
TEST_SKIPPED = /^Skipped/
|
10
|
+
TEST_SUMMARY = /^Total tests/
|
11
|
+
TESTS_STARTED = /^Starting test execution, please wait...$/
|
12
|
+
|
13
|
+
attr_accessor :state_machine
|
14
|
+
|
8
15
|
def initialize(reporter:)
|
9
|
-
self.
|
10
|
-
self.
|
11
|
-
state :waiting do
|
12
|
-
transition :build_started, :build_in_progress, :build_started
|
13
|
-
end
|
14
|
-
state :build_in_progress do
|
15
|
-
transition :received_build_input, :parsing_build_input
|
16
|
-
end
|
17
|
-
state :parsing_build_input do
|
18
|
-
on_entry :parse_build_input
|
19
|
-
transition :build_completed, :ready_to_run_tests, :build_completed
|
20
|
-
transition :build_failed, :reading_build_failure_details, :reset_build_failure_details
|
21
|
-
transition :received_build_input, :build_in_progress
|
22
|
-
end
|
23
|
-
state :reading_build_failure_details do
|
24
|
-
transition :received_build_failure_details, :reading_build_failure_details, :track_build_failure_details
|
25
|
-
transition :end_of_input, :done, :report_failing_build
|
26
|
-
end
|
27
|
-
state :ready_to_run_tests do
|
28
|
-
transition :received_input_line, :determining_if_tests_started
|
29
|
-
end
|
30
|
-
state :determining_if_tests_started do
|
31
|
-
on_entry :determine_if_tests_started
|
32
|
-
transition :tests_started, :waiting_for_test_input, :starting_tests
|
33
|
-
transition :tests_did_not_start, :ready_to_run_tests
|
34
|
-
end
|
35
|
-
state :waiting_for_test_input do
|
36
|
-
transition :test_input_received, :parsing_test_input
|
37
|
-
end
|
38
|
-
state :parsing_test_input do
|
39
|
-
on_entry :parse_test_input
|
40
|
-
transition :received_other_input, :waiting_for_test_input
|
41
|
-
transition :test_failed, :waiting_for_failure_details, :reset_current_failing_test
|
42
|
-
transition :test_passed, :waiting_for_test_input, :test_passed
|
43
|
-
transition :test_skipped, :waiting_for_test_input, :test_skipped
|
44
|
-
transition :tests_completed, :done, :show_test_summary
|
45
|
-
end
|
46
|
-
state :waiting_for_failure_details do
|
47
|
-
transition :received_failure_details, :reading_failure_details
|
48
|
-
end
|
49
|
-
state :reading_failure_details do
|
50
|
-
on_entry :parse_failure_line
|
51
|
-
transition :done_reading_failure, :parsing_test_input, :report_failing_test
|
52
|
-
transition :received_failure_output, :waiting_for_failure_details, :track_failure_details
|
53
|
-
end
|
54
|
-
state :parsing_failure_line do
|
55
|
-
on_entry :parse_failure_line
|
56
|
-
transition :received_failure_output, :reading_failure_details, :track_failure_details
|
57
|
-
transition :tests_completed, :done, :show_test_summary
|
58
|
-
end
|
59
|
-
end
|
60
|
-
aggregator.state_machine = state_machine
|
16
|
+
self.raw_input_inlines = []
|
17
|
+
self.reporter = reporter
|
61
18
|
end
|
62
19
|
|
63
20
|
def parse_line(input_line)
|
64
|
-
|
21
|
+
raw_input_inlines << input_line
|
22
|
+
case state_machine.current_state_name
|
23
|
+
when :waiting_for_build_to_start
|
24
|
+
state_machine.trigger(:received_input_line, input_line)
|
25
|
+
when :build_in_progress
|
26
|
+
state_machine.trigger(:received_build_input, input_line)
|
27
|
+
when :reading_build_failure_details
|
28
|
+
state_machine.trigger(:received_build_failure_details, input_line)
|
29
|
+
when :ready_to_run_tests
|
30
|
+
state_machine.trigger(:received_input_line, input_line)
|
31
|
+
when :waiting_for_test_input
|
32
|
+
state_machine.trigger(:test_input_received, input_line)
|
33
|
+
when :waiting_for_failure_details
|
34
|
+
state_machine.trigger(:received_failure_details, input_line)
|
35
|
+
when :reading_failure_details
|
36
|
+
state_machine.trigger(:received_input_line, input_line)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def handle_end_of_input
|
41
|
+
case state_machine.current_state_name
|
42
|
+
when :waiting_for_build_to_start
|
43
|
+
state_machine.trigger(:build_failed_to_start)
|
44
|
+
else
|
45
|
+
state_machine.trigger(:end_of_input)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse_prebuild_input(input_line)
|
50
|
+
if input_line.match(BUILD_STARTED)
|
51
|
+
state_machine.trigger(:build_started)
|
52
|
+
else
|
53
|
+
state_machine.trigger(:build_did_not_start)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_failed_to_start
|
58
|
+
reporter.build_failed_to_start(raw_input_inlines)
|
59
|
+
end
|
60
|
+
|
61
|
+
def parse_build_input(input_line)
|
62
|
+
if input_line.match(BUILD_COMPLETED)
|
63
|
+
state_machine.trigger(:build_completed)
|
64
|
+
elsif input_line.match(BUILD_FAILED)
|
65
|
+
state_machine.trigger(:build_failed)
|
66
|
+
else
|
67
|
+
state_machine.trigger(:received_build_input)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def determine_if_tests_started(input_line)
|
72
|
+
if input_line.match(TESTS_STARTED)
|
73
|
+
state_machine.trigger(:tests_started)
|
74
|
+
else
|
75
|
+
state_machine.trigger(:tests_did_not_start)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def parse_test_input(input_line)
|
80
|
+
if input_line.match(TEST_PASSED)
|
81
|
+
match = input_line.match(/^Passed\s+(.+)$/)
|
82
|
+
state_machine.trigger(:test_passed, match[1])
|
83
|
+
elsif input_line.match(TEST_FAILED)
|
84
|
+
match = input_line.match(/^Failed\s+(.+)$/)
|
85
|
+
state_machine.trigger(:test_failed, match[1])
|
86
|
+
elsif input_line.match(TEST_SKIPPED)
|
87
|
+
match = input_line.match(/^Skipped\s+(.+)$/)
|
88
|
+
state_machine.trigger(:test_skipped, match[1])
|
89
|
+
elsif input_line.match(TEST_SUMMARY)
|
90
|
+
state_machine.trigger(:tests_completed, input_line)
|
91
|
+
else
|
92
|
+
state_machine.trigger(:received_other_input)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def build_completed
|
97
|
+
reporter.build_completed
|
98
|
+
end
|
99
|
+
|
100
|
+
def build_started
|
101
|
+
reporter.build_started
|
102
|
+
end
|
103
|
+
|
104
|
+
def reset_build_failure_details
|
105
|
+
self.build_failure_details = []
|
106
|
+
end
|
107
|
+
|
108
|
+
def track_build_failure_details(input_line)
|
109
|
+
build_failure_details << input_line
|
110
|
+
end
|
111
|
+
|
112
|
+
def report_failing_build
|
113
|
+
reporter.build_failed(build_failure_details)
|
114
|
+
end
|
115
|
+
|
116
|
+
def track_failure_details(details)
|
117
|
+
current_failing_test[:details] << details.rstrip if details.rstrip != ""
|
118
|
+
end
|
119
|
+
|
120
|
+
def show_test_summary(summary)
|
121
|
+
match = summary.match(/^Total tests: (\d+). Passed: (\d+). Failed: (\d+). Skipped: (\d+)./)
|
122
|
+
reporter.show_test_summary({
|
123
|
+
failedTests: match[3].to_i,
|
124
|
+
passedTests: match[2].to_i,
|
125
|
+
skippedTests: match[4].to_i,
|
126
|
+
totalTests: match[1].to_i
|
127
|
+
})
|
128
|
+
end
|
129
|
+
|
130
|
+
def report_failing_test(*_)
|
131
|
+
reporter.test_failed({
|
132
|
+
details: current_failing_test[:details],
|
133
|
+
name: current_failing_test[:name]
|
134
|
+
})
|
135
|
+
end
|
136
|
+
|
137
|
+
def parse_failure_line(input_line)
|
138
|
+
if input_line.match(TEST_PASSED)
|
139
|
+
state_machine.trigger(:done_reading_failure, input_line)
|
140
|
+
elsif input_line.match(TEST_SUMMARY)
|
141
|
+
state_machine.trigger(:done_reading_failure, input_line)
|
142
|
+
elsif input_line.match(TEST_FAILED)
|
143
|
+
state_machine.trigger(:done_reading_failure, input_line)
|
144
|
+
else
|
145
|
+
state_machine.trigger(:received_failure_output, input_line)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def starting_tests
|
150
|
+
reporter.starting_tests
|
151
|
+
end
|
152
|
+
|
153
|
+
def reset_current_failing_test(test_name)
|
154
|
+
self.current_failing_test = {
|
155
|
+
details: [],
|
156
|
+
name: test_name
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_passed(name)
|
161
|
+
reporter.test_passed({ name: name })
|
65
162
|
end
|
66
163
|
|
67
|
-
def
|
68
|
-
|
164
|
+
def test_skipped(name)
|
165
|
+
reporter.test_skipped({ name: name })
|
69
166
|
end
|
70
167
|
|
71
168
|
private
|
72
169
|
|
73
|
-
attr_accessor :
|
170
|
+
attr_accessor :build_failure_details, :current_failing_test, :raw_input_inlines, :reporter
|
74
171
|
|
75
172
|
end
|
76
173
|
end
|
@@ -14,6 +14,12 @@ module Dotpretty
|
|
14
14
|
output.puts("Build started")
|
15
15
|
end
|
16
16
|
|
17
|
+
def build_failed_to_start(raw_input_inlines)
|
18
|
+
raw_input_inlines.each do |raw_input_line|
|
19
|
+
output.puts(raw_input_line)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
17
23
|
def build_completed
|
18
24
|
output.puts("Build completed")
|
19
25
|
output.puts("")
|
@@ -30,17 +36,17 @@ module Dotpretty
|
|
30
36
|
output.puts("Starting test execution...")
|
31
37
|
end
|
32
38
|
|
33
|
-
def test_passed(
|
34
|
-
output.puts("#{green("Passed")} #{
|
39
|
+
def test_passed(name:)
|
40
|
+
output.puts("#{green("Passed")} #{name}")
|
35
41
|
end
|
36
42
|
|
37
|
-
def test_skipped(
|
38
|
-
output.puts("#{yellow("Skipped")} #{
|
43
|
+
def test_skipped(name:)
|
44
|
+
output.puts("#{yellow("Skipped")} #{name}")
|
39
45
|
end
|
40
46
|
|
41
|
-
def test_failed(
|
42
|
-
output.puts("#{red("Failed")} #{
|
43
|
-
|
47
|
+
def test_failed(name:, details:)
|
48
|
+
output.puts("#{red("Failed")} #{name}")
|
49
|
+
details.each do |line|
|
44
50
|
output.puts(line)
|
45
51
|
end
|
46
52
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Dotpretty
|
2
|
+
module Reporters
|
3
|
+
class Browser
|
4
|
+
|
5
|
+
def initialize(http_client:)
|
6
|
+
self.http_client = http_client
|
7
|
+
end
|
8
|
+
|
9
|
+
def build_completed
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_failed_to_start(raw_input_inlines)
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_failed(failure_details)
|
16
|
+
end
|
17
|
+
|
18
|
+
def build_started
|
19
|
+
http_client.post_json("/build_started")
|
20
|
+
end
|
21
|
+
|
22
|
+
def show_test_summary(test_summary)
|
23
|
+
http_client.post_json("/update_results", {
|
24
|
+
tests: tests
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
def starting_tests
|
29
|
+
self.tests = []
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_failed(name:, details:)
|
33
|
+
tests << {
|
34
|
+
details: details,
|
35
|
+
name: name,
|
36
|
+
result: "failed"
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_passed(name:)
|
41
|
+
tests << {
|
42
|
+
name: name,
|
43
|
+
result: "passed"
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_skipped(name:)
|
48
|
+
tests << {
|
49
|
+
name: name,
|
50
|
+
result: "skipped"
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
attr_accessor :http_client, :tests
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "dotpretty/color_palettes/null"
|
2
2
|
require "dotpretty/reporters/basic"
|
3
|
+
require "dotpretty/reporters/browser"
|
3
4
|
require "dotpretty/reporters/json"
|
4
5
|
require "dotpretty/reporters/names"
|
5
6
|
require "dotpretty/reporters/progress"
|
@@ -10,6 +11,10 @@ module Dotpretty
|
|
10
11
|
|
11
12
|
def self.build_reporter(name, options = {})
|
12
13
|
case name
|
14
|
+
when Dotpretty::Reporters::Names::BROWSER
|
15
|
+
return Dotpretty::Reporters::Browser.new({
|
16
|
+
http_client: options.fetch(:http_client)
|
17
|
+
})
|
13
18
|
when Dotpretty::Reporters::Names::JSON
|
14
19
|
return Dotpretty::Reporters::Json.new(options.fetch(:output))
|
15
20
|
when Dotpretty::Reporters::Names::PROGRESS
|
@@ -12,6 +12,9 @@ module Dotpretty
|
|
12
12
|
def build_started
|
13
13
|
end
|
14
14
|
|
15
|
+
def build_failed_to_start(raw_input_inlines)
|
16
|
+
end
|
17
|
+
|
15
18
|
def build_completed
|
16
19
|
end
|
17
20
|
|
@@ -21,24 +24,26 @@ module Dotpretty
|
|
21
24
|
def starting_tests
|
22
25
|
end
|
23
26
|
|
24
|
-
def test_passed(
|
27
|
+
def test_passed(name:)
|
25
28
|
tests << {
|
26
|
-
name:
|
29
|
+
name: name,
|
27
30
|
result: "passed"
|
28
31
|
}
|
29
32
|
end
|
30
33
|
|
31
|
-
def test_skipped(
|
34
|
+
def test_skipped(name:)
|
32
35
|
tests << {
|
33
|
-
name:
|
36
|
+
name: name,
|
34
37
|
result: "skipped"
|
35
38
|
}
|
36
39
|
end
|
37
40
|
|
38
|
-
def test_failed(
|
39
|
-
tests <<
|
41
|
+
def test_failed(name:, details:)
|
42
|
+
tests << {
|
43
|
+
details: details,
|
44
|
+
name: name,
|
40
45
|
result: "failed"
|
41
|
-
}
|
46
|
+
}
|
42
47
|
end
|
43
48
|
|
44
49
|
def show_test_summary(summary)
|
@@ -15,6 +15,12 @@ module Dotpretty
|
|
15
15
|
output.puts("")
|
16
16
|
end
|
17
17
|
|
18
|
+
def build_failed_to_start(raw_input_inlines)
|
19
|
+
raw_input_inlines.each do |raw_input_line|
|
20
|
+
output.puts(raw_input_line)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
18
24
|
def build_started
|
19
25
|
output.puts("Build started")
|
20
26
|
end
|
@@ -38,17 +44,20 @@ module Dotpretty
|
|
38
44
|
output.puts("Starting test execution")
|
39
45
|
end
|
40
46
|
|
41
|
-
def test_failed(
|
42
|
-
failing_tests <<
|
47
|
+
def test_failed(name:, details:)
|
48
|
+
failing_tests << {
|
49
|
+
details: details,
|
50
|
+
name: name
|
51
|
+
}
|
43
52
|
output.print(red("F"))
|
44
53
|
end
|
45
54
|
|
46
|
-
def test_passed(
|
55
|
+
def test_passed(name:)
|
47
56
|
output.print(green("."))
|
48
57
|
end
|
49
58
|
|
50
|
-
def test_skipped(
|
51
|
-
skipped_test_names <<
|
59
|
+
def test_skipped(name:)
|
60
|
+
skipped_test_names << name
|
52
61
|
output.print(yellow("*"))
|
53
62
|
end
|
54
63
|
|
data/lib/dotpretty/runner.rb
CHANGED
@@ -1,28 +1,82 @@
|
|
1
1
|
require "dotpretty/parser"
|
2
|
-
require "dotpretty/reporters/
|
2
|
+
require "dotpretty/reporters/basic"
|
3
|
+
require "dotpretty/state_machine/state_machine_builder"
|
3
4
|
|
4
5
|
module Dotpretty
|
5
6
|
class Runner
|
6
7
|
|
7
|
-
def initialize(
|
8
|
-
reporter = Dotpretty::Reporters::Factory.build_reporter(reporter_name, {
|
9
|
-
output: output,
|
10
|
-
color_palette: color_palette
|
11
|
-
})
|
8
|
+
def initialize(reporter:)
|
12
9
|
self.parser = Dotpretty::Parser.new({ reporter: reporter })
|
10
|
+
self.state_machine = Dotpretty::StateMachine::StateMachineBuilder.build(parser) do
|
11
|
+
state :waiting_for_build_to_start do
|
12
|
+
transition :build_failed_to_start, :done, :build_failed_to_start
|
13
|
+
transition :received_input_line, :determining_if_build_started
|
14
|
+
end
|
15
|
+
state :determining_if_build_started do
|
16
|
+
on_entry :parse_prebuild_input
|
17
|
+
transition :build_started, :build_in_progress, :build_started
|
18
|
+
transition :build_did_not_start, :waiting_for_build_to_start
|
19
|
+
end
|
20
|
+
state :build_in_progress do
|
21
|
+
transition :received_build_input, :parsing_build_input
|
22
|
+
end
|
23
|
+
state :parsing_build_input do
|
24
|
+
on_entry :parse_build_input
|
25
|
+
transition :build_completed, :ready_to_run_tests, :build_completed
|
26
|
+
transition :build_failed, :reading_build_failure_details, :reset_build_failure_details
|
27
|
+
transition :received_build_input, :build_in_progress
|
28
|
+
end
|
29
|
+
state :reading_build_failure_details do
|
30
|
+
transition :received_build_failure_details, :reading_build_failure_details, :track_build_failure_details
|
31
|
+
transition :end_of_input, :done, :report_failing_build
|
32
|
+
end
|
33
|
+
state :ready_to_run_tests do
|
34
|
+
transition :received_input_line, :determining_if_tests_started
|
35
|
+
end
|
36
|
+
state :determining_if_tests_started do
|
37
|
+
on_entry :determine_if_tests_started
|
38
|
+
transition :tests_started, :waiting_for_test_input, :starting_tests
|
39
|
+
transition :tests_did_not_start, :ready_to_run_tests
|
40
|
+
end
|
41
|
+
state :waiting_for_test_input do
|
42
|
+
transition :test_input_received, :parsing_test_input
|
43
|
+
end
|
44
|
+
state :parsing_test_input do
|
45
|
+
on_entry :parse_test_input
|
46
|
+
transition :received_other_input, :waiting_for_test_input
|
47
|
+
transition :test_failed, :waiting_for_failure_details, :reset_current_failing_test
|
48
|
+
transition :test_passed, :waiting_for_test_input, :test_passed
|
49
|
+
transition :test_skipped, :waiting_for_test_input, :test_skipped
|
50
|
+
transition :tests_completed, :done, :show_test_summary
|
51
|
+
end
|
52
|
+
state :waiting_for_failure_details do
|
53
|
+
transition :received_failure_details, :reading_failure_details
|
54
|
+
end
|
55
|
+
state :reading_failure_details do
|
56
|
+
on_entry :parse_failure_line
|
57
|
+
transition :done_reading_failure, :parsing_test_input, :report_failing_test
|
58
|
+
transition :received_failure_output, :waiting_for_failure_details, :track_failure_details
|
59
|
+
end
|
60
|
+
state :parsing_failure_line do
|
61
|
+
on_entry :parse_failure_line
|
62
|
+
transition :received_failure_output, :reading_failure_details, :track_failure_details
|
63
|
+
transition :tests_completed, :done, :show_test_summary
|
64
|
+
end
|
65
|
+
end
|
66
|
+
parser.state_machine = state_machine
|
13
67
|
end
|
14
68
|
|
15
|
-
def
|
16
|
-
parser.parse_line(
|
69
|
+
def input_received(input_line)
|
70
|
+
parser.parse_line(input_line)
|
17
71
|
end
|
18
72
|
|
19
73
|
def done_with_input
|
20
|
-
parser.
|
74
|
+
parser.handle_end_of_input
|
21
75
|
end
|
22
76
|
|
23
77
|
private
|
24
78
|
|
25
|
-
attr_accessor :parser
|
79
|
+
attr_accessor :parser, :output, :state_machine
|
26
80
|
|
27
81
|
end
|
28
82
|
end
|
data/lib/dotpretty/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dotpretty
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Meyer
|
@@ -9,7 +9,21 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2019-05-02 00:00:00.000000000 Z
|
12
|
-
dependencies:
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.17'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.17'
|
13
27
|
description: A gem to parse and improve the output of the dotnet command
|
14
28
|
email:
|
15
29
|
executables:
|
@@ -18,11 +32,14 @@ extensions: []
|
|
18
32
|
extra_rdoc_files: []
|
19
33
|
files:
|
20
34
|
- bin/dotpretty
|
21
|
-
- lib/dotpretty/aggregator.rb
|
22
35
|
- lib/dotpretty/color_palettes/bash.rb
|
23
36
|
- lib/dotpretty/color_palettes/null.rb
|
37
|
+
- lib/dotpretty/http/client.rb
|
38
|
+
- lib/dotpretty/http/null_client.rb
|
39
|
+
- lib/dotpretty/options.rb
|
24
40
|
- lib/dotpretty/parser.rb
|
25
41
|
- lib/dotpretty/reporters/basic.rb
|
42
|
+
- lib/dotpretty/reporters/browser.rb
|
26
43
|
- lib/dotpretty/reporters/factory.rb
|
27
44
|
- lib/dotpretty/reporters/json.rb
|
28
45
|
- lib/dotpretty/reporters/names.rb
|
data/lib/dotpretty/aggregator.rb
DELETED
@@ -1,146 +0,0 @@
|
|
1
|
-
module Dotpretty
|
2
|
-
class Aggregator
|
3
|
-
|
4
|
-
BUILD_COMPLETED = /^Build completed/
|
5
|
-
BUILD_FAILED = /^Build FAILED.$/
|
6
|
-
TEST_FAILED = /^Failed/
|
7
|
-
TEST_PASSED = /^Passed/
|
8
|
-
TEST_SKIPPED = /^Skipped/
|
9
|
-
TEST_SUMMARY = /^Total tests/
|
10
|
-
TESTS_STARTED = /^Starting test execution, please wait...$/
|
11
|
-
|
12
|
-
attr_accessor :state_machine
|
13
|
-
|
14
|
-
def initialize(reporter:)
|
15
|
-
self.reporter = reporter
|
16
|
-
end
|
17
|
-
|
18
|
-
def parse_line(input_line)
|
19
|
-
case state_machine.current_state_name
|
20
|
-
when :waiting
|
21
|
-
state_machine.trigger(:build_started)
|
22
|
-
when :build_in_progress
|
23
|
-
state_machine.trigger(:received_build_input, input_line)
|
24
|
-
when :reading_build_failure_details
|
25
|
-
state_machine.trigger(:received_build_failure_details, input_line)
|
26
|
-
when :ready_to_run_tests
|
27
|
-
state_machine.trigger(:received_input_line, input_line)
|
28
|
-
when :waiting_for_test_input
|
29
|
-
state_machine.trigger(:test_input_received, input_line)
|
30
|
-
when :waiting_for_failure_details
|
31
|
-
state_machine.trigger(:received_failure_details, input_line)
|
32
|
-
when :reading_failure_details
|
33
|
-
state_machine.trigger(:received_input_line, input_line)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def parse_build_input(input_line)
|
38
|
-
if input_line.match(BUILD_COMPLETED)
|
39
|
-
state_machine.trigger(:build_completed)
|
40
|
-
elsif input_line.match(BUILD_FAILED)
|
41
|
-
state_machine.trigger(:build_failed)
|
42
|
-
else
|
43
|
-
state_machine.trigger(:received_build_input)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def determine_if_tests_started(input_line)
|
48
|
-
if input_line.match(TESTS_STARTED)
|
49
|
-
state_machine.trigger(:tests_started)
|
50
|
-
else
|
51
|
-
state_machine.trigger(:tests_did_not_start)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def parse_test_input(input_line)
|
56
|
-
if input_line.match(TEST_PASSED)
|
57
|
-
match = input_line.match(/^Passed\s+(.+)$/)
|
58
|
-
state_machine.trigger(:test_passed, match[1])
|
59
|
-
elsif input_line.match(TEST_FAILED)
|
60
|
-
match = input_line.match(/^Failed\s+(.+)$/)
|
61
|
-
state_machine.trigger(:test_failed, match[1])
|
62
|
-
elsif input_line.match(TEST_SKIPPED)
|
63
|
-
match = input_line.match(/^Skipped\s+(.+)$/)
|
64
|
-
state_machine.trigger(:test_skipped, match[1])
|
65
|
-
elsif input_line.match(TEST_SUMMARY)
|
66
|
-
state_machine.trigger(:tests_completed, input_line)
|
67
|
-
else
|
68
|
-
state_machine.trigger(:received_other_input)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def build_completed
|
73
|
-
reporter.build_completed
|
74
|
-
end
|
75
|
-
|
76
|
-
def build_started
|
77
|
-
reporter.build_started
|
78
|
-
end
|
79
|
-
|
80
|
-
def reset_build_failure_details
|
81
|
-
self.build_failure_details = []
|
82
|
-
end
|
83
|
-
|
84
|
-
def track_build_failure_details(input_line)
|
85
|
-
build_failure_details << input_line
|
86
|
-
end
|
87
|
-
|
88
|
-
def report_failing_build
|
89
|
-
reporter.build_failed(build_failure_details)
|
90
|
-
end
|
91
|
-
|
92
|
-
def track_failure_details(details)
|
93
|
-
current_failing_test[:details] << details.rstrip if details.rstrip != ""
|
94
|
-
end
|
95
|
-
|
96
|
-
def show_test_summary(summary)
|
97
|
-
match = summary.match(/^Total tests: (\d+). Passed: (\d+). Failed: (\d+). Skipped: (\d+)./)
|
98
|
-
reporter.show_test_summary({
|
99
|
-
failedTests: match[3].to_i,
|
100
|
-
passedTests: match[2].to_i,
|
101
|
-
skippedTests: match[4].to_i,
|
102
|
-
totalTests: match[1].to_i
|
103
|
-
})
|
104
|
-
end
|
105
|
-
|
106
|
-
def report_failing_test(*args)
|
107
|
-
reporter.test_failed(current_failing_test)
|
108
|
-
end
|
109
|
-
|
110
|
-
def parse_failure_line(input_line)
|
111
|
-
if input_line.match(TEST_PASSED)
|
112
|
-
state_machine.trigger(:done_reading_failure, input_line)
|
113
|
-
elsif input_line.match(TEST_SUMMARY)
|
114
|
-
state_machine.trigger(:done_reading_failure, input_line)
|
115
|
-
elsif input_line.match(TEST_FAILED)
|
116
|
-
state_machine.trigger(:done_reading_failure, input_line)
|
117
|
-
else
|
118
|
-
state_machine.trigger(:received_failure_output, input_line)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def starting_tests
|
123
|
-
reporter.starting_tests
|
124
|
-
end
|
125
|
-
|
126
|
-
def reset_current_failing_test(test_name)
|
127
|
-
self.current_failing_test = {
|
128
|
-
details: [],
|
129
|
-
name: test_name
|
130
|
-
}
|
131
|
-
end
|
132
|
-
|
133
|
-
def test_passed(test_name)
|
134
|
-
reporter.test_passed(test_name)
|
135
|
-
end
|
136
|
-
|
137
|
-
def test_skipped(test_name)
|
138
|
-
reporter.test_skipped(test_name)
|
139
|
-
end
|
140
|
-
|
141
|
-
private
|
142
|
-
|
143
|
-
attr_accessor :build_failure_details, :current_failing_test, :reporter
|
144
|
-
|
145
|
-
end
|
146
|
-
end
|