teaspoon 1.1.2 → 1.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 +5 -5
- data/CHANGELOG.md +47 -0
- data/MIT.LICENSE +2 -2
- data/README.md +56 -35
- data/app/assets/javascripts/teaspoon/hook.coffee +1 -1
- data/app/assets/javascripts/teaspoon/teaspoon.coffee +13 -1
- data/app/controllers/teaspoon/suite_controller.rb +25 -11
- data/app/views/teaspoon/suite/index.html.erb +1 -1
- data/lib/generators/teaspoon/install/install_generator.rb +34 -34
- data/lib/generators/teaspoon/install/templates/MISSING_FRAMEWORK +1 -1
- data/lib/generators/teaspoon/install/templates/POST_INSTALL +1 -1
- data/lib/generators/teaspoon/install/templates/_boot.html.erb +1 -1
- data/lib/generators/teaspoon/install/templates/env_comments.rb.tt +9 -7
- data/lib/tasks/teaspoon/info.rake +1 -1
- data/lib/teaspoon/command_line.rb +76 -76
- data/lib/teaspoon/configuration.rb +4 -4
- data/lib/teaspoon/console.rb +41 -40
- data/lib/teaspoon/coverage.rb +29 -25
- data/lib/teaspoon/deprecated.rb +1 -1
- data/lib/teaspoon/driver.rb +1 -1
- data/lib/teaspoon/driver/browserstack.rb +111 -0
- data/lib/teaspoon/driver/phantomjs.rb +25 -26
- data/lib/teaspoon/driver/phantomjs/runner.js +31 -3
- data/lib/teaspoon/driver/selenium.rb +13 -9
- data/lib/teaspoon/engine.rb +32 -16
- data/lib/teaspoon/environment.rb +28 -28
- data/lib/teaspoon/exceptions.rb +7 -7
- data/lib/teaspoon/exporter.rb +23 -23
- data/lib/teaspoon/formatter/base.rb +64 -46
- data/lib/teaspoon/formatter/clean.rb +2 -2
- data/lib/teaspoon/formatter/documentation.rb +40 -40
- data/lib/teaspoon/formatter/dot.rb +12 -12
- data/lib/teaspoon/formatter/json.rb +21 -21
- data/lib/teaspoon/formatter/junit.rb +52 -51
- data/lib/teaspoon/formatter/modules/report_module.rb +34 -32
- data/lib/teaspoon/formatter/pride.rb +21 -21
- data/lib/teaspoon/formatter/rspec_html.rb +31 -31
- data/lib/teaspoon/formatter/snowday.rb +6 -5
- data/lib/teaspoon/formatter/swayze_or_oprah.rb +91 -91
- data/lib/teaspoon/formatter/tap.rb +29 -29
- data/lib/teaspoon/formatter/tap_y.rb +57 -57
- data/lib/teaspoon/formatter/teamcity.rb +63 -63
- data/lib/teaspoon/framework/base.rb +1 -1
- data/lib/teaspoon/instrumentation.rb +18 -18
- data/lib/teaspoon/registry.rb +9 -9
- data/lib/teaspoon/registry/has_default.rb +2 -2
- data/lib/teaspoon/runner.rb +37 -37
- data/lib/teaspoon/server.rb +30 -29
- data/lib/teaspoon/suite.rb +68 -57
- data/lib/teaspoon/utility.rb +6 -0
- data/lib/teaspoon/version.rb +1 -1
- metadata +10 -17
- data/lib/teaspoon/driver/capybara_webkit.rb +0 -40
@@ -5,35 +5,35 @@ module Teaspoon
|
|
5
5
|
class Tap < Base
|
6
6
|
protected
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
8
|
+
def log_runner(_result)
|
9
|
+
log_line("1..#{@total_count}")
|
10
|
+
end
|
11
|
+
|
12
|
+
def log_passing_spec(result)
|
13
|
+
log_line("ok #{@run_count} - #{result.description}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def log_pending_spec(result)
|
17
|
+
log_line("ok #{@run_count} - [pending] #{result.description}")
|
18
|
+
end
|
19
|
+
|
20
|
+
def log_failing_spec(result)
|
21
|
+
log_line("not ok #{@run_count} - #{result.description}")
|
22
|
+
log_line(" FAIL #{result.message}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def log_console(message)
|
26
|
+
log_line("# #{message.gsub(/\n$/, '')}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def log_coverage(message)
|
30
|
+
log_line("# #{message.gsub(/\n/, "\n# ")}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def log_threshold_failure(message)
|
34
|
+
log_line("not ok #{@run_count + 1} - Coverage threshold failed")
|
35
|
+
log_line("# #{message.gsub(/\n/, "\n# ")}")
|
36
|
+
end
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -6,71 +6,71 @@ module Teaspoon
|
|
6
6
|
class TapY < Base
|
7
7
|
protected
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
def log_runner(result)
|
10
|
+
log "type" => "suite",
|
11
|
+
"start" => result.start,
|
12
|
+
"count" => result.total,
|
13
|
+
"seed" => 0,
|
14
|
+
"rev" => 4
|
15
|
+
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def log_suite(result)
|
18
|
+
log "type" => "case",
|
19
|
+
"label" => result.label,
|
20
|
+
"level" => result.level
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
def log_passing_spec(result)
|
24
|
+
log "type" => "test",
|
25
|
+
"status" => "pass",
|
26
|
+
"label" => result.label,
|
27
|
+
"stdout" => @stdout
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
30
|
+
def log_pending_spec(result)
|
31
|
+
log "type" => "test",
|
32
|
+
"status" => "pending",
|
33
|
+
"label" => result.label,
|
34
|
+
"stdout" => @stdout,
|
35
|
+
"exception" => {
|
36
|
+
"message" => result.message
|
37
|
+
}
|
38
|
+
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
40
|
+
def log_failing_spec(result)
|
41
|
+
log "type" => "test",
|
42
|
+
"status" => "fail",
|
43
|
+
"label" => result.label,
|
44
|
+
"stdout" => @stdout,
|
45
|
+
"exception" => {
|
46
|
+
"message" => result.message,
|
47
|
+
"backtrace" => ["#{result.link}#:0"],
|
48
|
+
"file" => "unknown",
|
49
|
+
"line" => "unknown",
|
50
|
+
"source" => "unknown",
|
51
|
+
"snippet" => { "0" => result.link },
|
52
|
+
"class" => "Unknown"
|
53
|
+
}
|
54
|
+
end
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
56
|
+
def log_result(result)
|
57
|
+
log "type" => "final",
|
58
|
+
"time" => result.elapsed,
|
59
|
+
"counts" => {
|
60
|
+
"total" => @run_count,
|
61
|
+
"pass" => @passes.size,
|
62
|
+
"fail" => @failures.size,
|
63
|
+
"error" => @errors.size,
|
64
|
+
"omit" => 0,
|
65
|
+
"todo" => @pendings.size
|
66
|
+
}
|
67
|
+
end
|
68
68
|
|
69
69
|
private
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
def log(hash)
|
72
|
+
log_str(hash.to_yaml)
|
73
|
+
end
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
@@ -10,87 +10,87 @@ module Teaspoon
|
|
10
10
|
|
11
11
|
protected
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def log_suite(result)
|
18
|
-
log_end_suite
|
19
|
-
log("testSuiteStarted name='#{result.label}'")
|
20
|
-
end
|
13
|
+
def log_runner(result)
|
14
|
+
log("testCount count='#{result.total}' timestamp='#{result.start}'")
|
15
|
+
end
|
21
16
|
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
def log_suite(result)
|
18
|
+
log_end_suite
|
19
|
+
log("testSuiteStarted name='#{result.label}'")
|
20
|
+
end
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
def log_passing_spec(result)
|
23
|
+
log_teamcity_spec(type: "testStarted", desc: escape(result.description))
|
24
|
+
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
log("testFailed name='#{escape(result.description)}' message='#{escape(result.message)}'")
|
26
|
+
def log_pending_spec(result)
|
27
|
+
log_teamcity_spec(type: "testIgnored", desc: escape(result.description))
|
33
28
|
end
|
34
|
-
end
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
|
30
|
+
def log_failing_spec(result)
|
31
|
+
log_teamcity_spec(type: "testStarted", desc: escape(result.description)) do
|
32
|
+
log("testFailed name='#{escape(result.description)}' message='#{escape(result.message)}'")
|
33
|
+
end
|
34
|
+
end
|
39
35
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
36
|
+
def log_error(result)
|
37
|
+
log("message text='#{escape(result.message)}' errorDetails='#{escape_trace(result.trace)}' status='ERROR'")
|
38
|
+
end
|
44
39
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
40
|
+
def log_result(result)
|
41
|
+
log_end_suite
|
42
|
+
@result = result
|
43
|
+
end
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
log_teamcity_spec(type: "testStarted", desc: "Coverage thresholds") do
|
54
|
-
log("testFailed name='Coverage thresholds' message='were not met'")
|
45
|
+
def log_coverage(message)
|
46
|
+
log("testSuiteStarted name='Coverage summary'")
|
55
47
|
log_line(message)
|
48
|
+
log("testSuiteFinished name='Coverage summary'")
|
56
49
|
end
|
57
|
-
log("testSuiteFinished name='Coverage thresholds'")
|
58
|
-
end
|
59
50
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
51
|
+
def log_threshold_failure(message)
|
52
|
+
log("testSuiteStarted name='Coverage thresholds'")
|
53
|
+
log_teamcity_spec(type: "testStarted", desc: "Coverage thresholds") do
|
54
|
+
log("testFailed name='Coverage thresholds' message='were not met'")
|
55
|
+
log_line(message)
|
56
|
+
end
|
57
|
+
log("testSuiteFinished name='Coverage thresholds'")
|
58
|
+
end
|
59
|
+
|
60
|
+
def log_complete(failure_count)
|
61
|
+
log_line("\nFinished in #{@result.elapsed} seconds")
|
62
|
+
stats = "#{pluralize('example', run_count)}, #{pluralize('failure', failure_count)}"
|
63
|
+
stats << ", #{pendings.size} pending" if pendings.size > 0
|
64
|
+
log_line(stats)
|
65
|
+
log_line if failure_count > 0
|
66
|
+
end
|
67
67
|
|
68
68
|
private
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
def log_end_suite
|
71
|
+
log("testSuiteFinished name='#{escape(@last_suite.label)}'") if @last_suite
|
72
|
+
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
def log_teamcity_spec(opts, &_block)
|
75
|
+
log("#{opts[:type]} name='#{opts[:desc]}' captureStandardOutput='true'")
|
76
|
+
log_line(@stdout.gsub(/\n$/, "")) unless @stdout.blank?
|
77
|
+
yield if block_given?
|
78
|
+
log("testFinished name='#{opts[:desc]}'")
|
79
|
+
end
|
80
80
|
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
def log(str)
|
82
|
+
log_line("##teamcity[#{str}]")
|
83
|
+
end
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
85
|
+
def escape(str)
|
86
|
+
str = str.gsub(/[|'\[\]]/) { |c| "|#{c}" }
|
87
|
+
str.gsub("\n", "|n").gsub("\r", "|r")
|
88
|
+
end
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
90
|
+
def escape_trace(trace)
|
91
|
+
lines = trace.map { |t| ["#{t['file']}:#{t['line']}", t["function"]].compact.join(" ") }
|
92
|
+
escape(lines.join("\n"))
|
93
|
+
end
|
94
94
|
end
|
95
95
|
end
|
96
96
|
end
|
@@ -43,28 +43,28 @@ module Teaspoon
|
|
43
43
|
|
44
44
|
protected
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
def self.ignored?(asset)
|
47
|
+
Array(Teaspoon::Coverage.configuration.ignore).any? do |ignore|
|
48
|
+
asset.filename.match(ignore)
|
49
|
+
end
|
50
|
+
rescue Teaspoon::UnknownCoverage
|
51
|
+
false
|
49
52
|
end
|
50
|
-
rescue Teaspoon::UnknownCoverage
|
51
|
-
false
|
52
|
-
end
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
54
|
+
def add_instrumentation(asset)
|
55
|
+
source_path = asset.filename
|
56
|
+
Dir.mktmpdir do |temp_path|
|
57
|
+
input_path = File.join(temp_path, File.basename(source_path)).sub(/\.js.+/, ".js")
|
58
|
+
File.open(input_path, "w") { |f| f.write(asset.source) }
|
59
|
+
instrument(input_path).gsub(input_path, source_path)
|
60
|
+
end
|
60
61
|
end
|
61
|
-
end
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
63
|
+
def instrument(input)
|
64
|
+
result = %x{#{self.class.executable} instrument --embed-source #{input.shellescape}}
|
65
|
+
return result if $?.exitstatus == 0
|
66
|
+
raise Teaspoon::DependencyError.new("Unable to add instrumentation to #{File.basename(input)}.")
|
67
|
+
end
|
68
68
|
end
|
69
69
|
|
70
70
|
module SprocketsInstrumentation
|
data/lib/teaspoon/registry.rb
CHANGED
@@ -22,11 +22,11 @@ module Teaspoon
|
|
22
22
|
if !(driver = @registry[normalize_name(name)])
|
23
23
|
raise not_found_exception.new(name: name, available: available.keys)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
driver.call
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def matches?(one, two)
|
30
30
|
normalize_name(one) == normalize_name(two)
|
31
31
|
end
|
32
32
|
|
@@ -36,12 +36,12 @@ module Teaspoon
|
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
def normalize_name(name)
|
40
|
+
name.to_s.gsub(/[-|\s]/, "_").to_sym
|
41
|
+
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
def not_found_exception
|
44
|
+
@not_found_exception || Teaspoon::NotFoundInRegistry
|
45
|
+
end
|
46
46
|
end
|
47
|
-
end
|
47
|
+
end
|