xcpretty-bb 0.1.12.bb1
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 +19 -0
- data/.hound.yml +2 -0
- data/.kick +17 -0
- data/.rubocop.yml +239 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +200 -0
- data/CONTRIBUTING.md +64 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +61 -0
- data/README.md +93 -0
- data/Rakefile +26 -0
- data/assets/report.html.erb +172 -0
- data/bin/xcpretty +85 -0
- data/features/assets/RACCommandSpec, line 80, hello xcpretty.png +0 -0
- data/features/assets/apple_raw.png +0 -0
- data/features/custom_formatter.feature +15 -0
- data/features/fixtures/xcodebuild.log +5963 -0
- data/features/html_report.feature +54 -0
- data/features/json_compilation_database_report.feature +21 -0
- data/features/junit_report.feature +44 -0
- data/features/knock_format.feature +11 -0
- data/features/simple_format.feature +204 -0
- data/features/steps/formatting_steps.rb +330 -0
- data/features/steps/html_steps.rb +32 -0
- data/features/steps/json_steps.rb +37 -0
- data/features/steps/junit_steps.rb +39 -0
- data/features/steps/report_steps.rb +22 -0
- data/features/steps/xcpretty_steps.rb +31 -0
- data/features/support/env.rb +117 -0
- data/features/tap_format.feature +31 -0
- data/features/test_format.feature +49 -0
- data/features/xcpretty.feature +14 -0
- data/lib/xcpretty/ansi.rb +72 -0
- data/lib/xcpretty/formatters/formatter.rb +177 -0
- data/lib/xcpretty/formatters/knock.rb +35 -0
- data/lib/xcpretty/formatters/rspec.rb +33 -0
- data/lib/xcpretty/formatters/simple.rb +200 -0
- data/lib/xcpretty/formatters/tap.rb +40 -0
- data/lib/xcpretty/parser.rb +591 -0
- data/lib/xcpretty/printer.rb +24 -0
- data/lib/xcpretty/reporters/html.rb +98 -0
- data/lib/xcpretty/reporters/json_compilation_database.rb +62 -0
- data/lib/xcpretty/reporters/junit.rb +102 -0
- data/lib/xcpretty/snippet.rb +38 -0
- data/lib/xcpretty/syntax.rb +51 -0
- data/lib/xcpretty/term.rb +14 -0
- data/lib/xcpretty/version.rb +4 -0
- data/lib/xcpretty.rb +37 -0
- data/spec/fixtures/NSStringTests.m +64 -0
- data/spec/fixtures/constants.rb +600 -0
- data/spec/fixtures/custom_formatter.rb +18 -0
- data/spec/fixtures/oneliner.m +1 -0
- data/spec/fixtures/raw_kiwi_compilation_fail.txt +24 -0
- data/spec/fixtures/raw_kiwi_fail.txt +1896 -0
- data/spec/fixtures/raw_specta_fail.txt +3110 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/support/matchers/colors.rb +21 -0
- data/spec/xcpretty/ansi_spec.rb +47 -0
- data/spec/xcpretty/formatters/formatter_spec.rb +140 -0
- data/spec/xcpretty/formatters/rspec_spec.rb +56 -0
- data/spec/xcpretty/formatters/simple_spec.rb +173 -0
- data/spec/xcpretty/parser_spec.rb +542 -0
- data/spec/xcpretty/printer_spec.rb +55 -0
- data/spec/xcpretty/snippet_spec.rb +46 -0
- data/spec/xcpretty/syntax_spec.rb +39 -0
- data/spec/xcpretty/term_spec.rb +26 -0
- data/xcpretty.gemspec +37 -0
- metadata +237 -0
data/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
__`xcpretty` is a fast and flexible formatter for `xcodebuild`__.<br/>
|
|
4
|
+
It does one thing, and it should do it well.
|
|
5
|
+
|
|
6
|
+
[](http://rubygems.org/gems/xcpretty)
|
|
7
|
+
[](https://travis-ci.org/supermarin/xcpretty)
|
|
8
|
+
[](https://codeclimate.com/github/supermarin/xcpretty)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
``` bash
|
|
12
|
+
$ gem install xcpretty
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
``` bash
|
|
17
|
+
$ xcodebuild [flags] | xcpretty -c
|
|
18
|
+
```
|
|
19
|
+
`xcpretty` is designed to be piped with `xcodebuild` and thus keeping 100%
|
|
20
|
+
compatibility with it. It's even a bit faster than `xcodebuild` itself, since
|
|
21
|
+
it saves your terminal some prints.
|
|
22
|
+
|
|
23
|
+
__Important:__ If you're running `xcpretty` on a CI like Travis or Jenkins, you
|
|
24
|
+
may want to exit with same status code as `xcodebuild`.
|
|
25
|
+
CI systems usually use status codes to determine if the build has failed.
|
|
26
|
+
|
|
27
|
+
``` bash
|
|
28
|
+
$ set -o pipefail && xcodebuild [flags] | xcpretty -c
|
|
29
|
+
#
|
|
30
|
+
# OR
|
|
31
|
+
#
|
|
32
|
+
$ xcodebuild [flags] | xcpretty -c && exit ${PIPESTATUS[0]}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Raw xcodebuild output
|
|
36
|
+
You might want to use `xcpretty` together with `tee` to store the raw log in a
|
|
37
|
+
file, and get the pretty output in the terminal. This might be useful if you
|
|
38
|
+
want to inspect a failure in detail and aren't able to tell from the pretty
|
|
39
|
+
output.
|
|
40
|
+
|
|
41
|
+
Here's a way of doing it:
|
|
42
|
+
``` bash
|
|
43
|
+
$ xcodebuild [flags] | tee xcodebuild.log | xcpretty -c
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Formats
|
|
47
|
+
|
|
48
|
+
- `--[no-]color`: Show build icons in color. (you can add it to `--simple` or `--test` format).
|
|
49
|
+
Defaults to auto-detecting color availability.
|
|
50
|
+
- `--[no-]utf`: Use unicode characters in build output or only ASCII.
|
|
51
|
+
Defaults to auto-detecting the current locale
|
|
52
|
+
|
|
53
|
+
- `--simple`, `-s` (default)
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
- `--test`, `-t` (RSpec style)
|
|
57
|
+

|
|
58
|
+
- `--tap` ([Test Anything Protocol](http://testanything.org)-compatible output)
|
|
59
|
+
- `--knock`, `-k` (a [simplified version](https://github.com/chneukirchen/knock) of the Test Anything Protocol)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
## Reporters
|
|
63
|
+
|
|
64
|
+
- `--report junit`, `-r junit`: Creates a JUnit-style XML report at `build/reports/junit.xml`, compatible with Jenkins and TeamCity CI.
|
|
65
|
+
|
|
66
|
+
- `--report html`, `-r html`: Creates a simple HTML report at `build/reports/tests.html`.
|
|
67
|
+

|
|
68
|
+
|
|
69
|
+
- `--report json-compilation-database`, `-r json-compilation-database`: Creates a [JSON compilation database](http://clang.llvm.org/docs/JSONCompilationDatabase.html) at `build/reports/compilation.json`. This is a format to replay single compilations independently of the build system.
|
|
70
|
+
|
|
71
|
+
Writing a report to a custom path can be specified using `--output PATH`.
|
|
72
|
+
|
|
73
|
+
## Extensions
|
|
74
|
+
|
|
75
|
+
`xcpretty` supports custom formatters through the use of the
|
|
76
|
+
`--formatter` flag, which takes a path to a file as an argument. The
|
|
77
|
+
file must contain a Ruby subclass of `XCPretty::Formatter`, and
|
|
78
|
+
return that class at the end of te file. The class
|
|
79
|
+
can override the `format_*` methods to hook into output parsing
|
|
80
|
+
events.
|
|
81
|
+
|
|
82
|
+
### Known extensions
|
|
83
|
+
|
|
84
|
+
* [xcpretty-travis-formatter](https://github.com/kattrali/xcpretty-travis-formatter): support for cleaner output in TravisCI using code folding
|
|
85
|
+
|
|
86
|
+
The recommended format is a gem containing the formatter and named
|
|
87
|
+
with an `xcpretty-` prefix, for easier discovery.
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
## Team
|
|
91
|
+
|
|
92
|
+
- [Marin Usalj](http://github.com/supermarin) http://supermar.in
|
|
93
|
+
- [Delisa Mason](http://github.com/kattrali) http://delisa.me
|
data/Rakefile
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
2
|
+
require 'rubocop/rake_task'
|
|
3
|
+
require 'rspec/core/rake_task'
|
|
4
|
+
require 'cucumber/rake/task'
|
|
5
|
+
|
|
6
|
+
task :kick do
|
|
7
|
+
sh 'bundle exec kicker -r ruby'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
Cucumber::Rake::Task.new(:cucumber) do |task|
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
|
14
|
+
task.rspec_opts = %w(--color --format=doc)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
RuboCop::RakeTask.new(:lint) do |task|
|
|
18
|
+
task.fail_on_error = false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
task :ci do
|
|
22
|
+
Rake::Task[:spec].invoke
|
|
23
|
+
Rake::Task[:cucumber].invoke
|
|
24
|
+
Rake::Task[:lint].invoke
|
|
25
|
+
end
|
|
26
|
+
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Test Results | xcpretty</title>
|
|
6
|
+
<style type="text/css">
|
|
7
|
+
body { font-family:Avenir Next, Helvetica Neue, sans-serif; color: #4A4A4A; background-color: #F0F3FB; margin:0;}
|
|
8
|
+
h1 { font-weight: normal; font-size: 24px; margin: 10px 0 0 0;}
|
|
9
|
+
h3 { font-weight: normal; margin: 2px; font-size: 1.1em;}
|
|
10
|
+
header { position: fixed;width: 100%;background: rgba(249, 254, 255, 0.9);margin: 0;padding: 10px;}
|
|
11
|
+
header:before, header:after { content:""; display:table;}
|
|
12
|
+
header:after { clear:both;}
|
|
13
|
+
a:link { color: #A1D761;}
|
|
14
|
+
footer { clear: both;position: relative;z-index: 10;height: 40px;margin-top: -10px; margin-left:30px; font-size:12px;}
|
|
15
|
+
table { width:100%; border-collapse: collapse;}
|
|
16
|
+
tr td:first-child { width:7%}
|
|
17
|
+
.left { float: left; margin-left:30px;}
|
|
18
|
+
.right { float: right; margin-right: 40px; margin-top: 0; margin-bottom:0;}
|
|
19
|
+
.test-suite { margin: 0 0 30px 0;}
|
|
20
|
+
.test-suite > .heading { font-family:Menlo, Monaco, monospace; font-weight: bold; border-color: #A1D761; background-color: #B8E986; border-width: 1px;}
|
|
21
|
+
.test-suite.failing > .heading { border-color: #C84F5E; background-color: #E58591;}
|
|
22
|
+
.test-suite > .heading > .title { margin-top: 4px; margin-left: 10px;}
|
|
23
|
+
.tests { overflow: scroll;margin: 0 30px 0 60px;}
|
|
24
|
+
.test, .test-suite > .heading { height: 30px; overflow: hidden; margin: 0 30px;}
|
|
25
|
+
.test, .test-suite > .heading { border-width: 1px; border-collapse: collapse; border-style: solid; }
|
|
26
|
+
.test { margin-left: 30px; border-top:none;}
|
|
27
|
+
.test.failing { border-color: #C84F5E; background-color: #F4DDE0;}
|
|
28
|
+
.test.passing { border-color: #A1D761;}
|
|
29
|
+
.test.failing { background-color: #E7A1AA;}
|
|
30
|
+
.test.passing { background-color: #CAF59F;}
|
|
31
|
+
.test.failing.odd { background-color: #EEC7CC;}
|
|
32
|
+
.test.passing.odd { background-color: #E5FBCF;}
|
|
33
|
+
.details { background-color: #F4DDE0; border: 1px solid #C84F5E;}
|
|
34
|
+
.test .test-detail:last-child { padding-bottom: 8px;}
|
|
35
|
+
.test .title { float: left; font-size: 0.9em; margin-top: 8px; font-family: Menlo, Monaco, monospace;}
|
|
36
|
+
.test .time { float: left;margin: 4px 10px 0 20px;}
|
|
37
|
+
.test-detail { font-family:Menlo, Monaco, monospace; font-size: 0.9em; margin: 5px 0 5px 0px;}
|
|
38
|
+
.screenshots { height: auto; overflow: hidden; padding: 4px 4px 0 4px; background-color: #B8E986; border: #A1D761; border-width: 0 1px; border-style: solid; }
|
|
39
|
+
.screenshots.failing { border-color: #C84F5E; background-color: #E58591; }
|
|
40
|
+
.screenshot { max-height: 60px; float: left; transition: max-height 0.2s; margin: 0 4px 4px 0 }
|
|
41
|
+
.screenshot.selected { max-height: 568px; }
|
|
42
|
+
#test-suites { display: inline-block; width: 100%;margin-top:100px;}
|
|
43
|
+
#segment-bar { margin-top: 10px;margin-left: 14px;float:right;}
|
|
44
|
+
#segment-bar a:first-child { border-radius: 9px 0 0 9px; border-right: none;}
|
|
45
|
+
#segment-bar a:last-child { border-radius: 0 9px 9px 0; border-left: none;}
|
|
46
|
+
#segment-bar > a { color: #565656; border: 2px solid #7B7B7B; width: 80px; font-weight: bold; display:inline-block;text-align:center; font-weight: normal;}
|
|
47
|
+
#segment-bar > a.selected { background-color: #979797; color: #F0F3FB;}
|
|
48
|
+
#counters { float: left;margin: 10px;text-align: right;}
|
|
49
|
+
#counters h2 { font-size: 16px; font-family: Avenir, sans-serif; font-weight: lighter; display:inline;}
|
|
50
|
+
#counters .number { font-size: 20px;}
|
|
51
|
+
#fail-count { color: #D0021B; margin-left:10px;}
|
|
52
|
+
@media (max-width: 640px) {
|
|
53
|
+
h1, #counters, #segment-bar { margin: 5px auto; text-align:center;}
|
|
54
|
+
header, #segment-bar { width: 100%; position: relative; background:none;}
|
|
55
|
+
.left, .right { float:none; margin:0;}
|
|
56
|
+
#test-suites { margin-top: 0;}
|
|
57
|
+
#counters { float:none;}
|
|
58
|
+
}
|
|
59
|
+
</style>
|
|
60
|
+
<script type="text/javascript">
|
|
61
|
+
var hide = function(element) { element.style.display = 'none';}
|
|
62
|
+
var show = function(element) { element.style.display = '';}
|
|
63
|
+
var isHidden = function(element) { return element.style.display == 'none';}
|
|
64
|
+
var isSelected = function(element) { return element.classList.contains("selected");}
|
|
65
|
+
var deselect = function(element) { return element.classList.remove("selected");}
|
|
66
|
+
var select = function(element) { return element.classList.add("selected");}
|
|
67
|
+
var toggle = function(element) { isHidden(element) ? show(element) : hide(element);};
|
|
68
|
+
var toggleTests = function(heading) { toggle(heading.parentNode.children[1]);};
|
|
69
|
+
var toggleDetails = function(detailClass) {
|
|
70
|
+
var details = document.querySelectorAll('.' + detailClass);
|
|
71
|
+
for (var i = details.length - 1; i >= 0; i--) { toggle(details[i]);};
|
|
72
|
+
};
|
|
73
|
+
var hideAll = function(collection) {
|
|
74
|
+
for (var i = collection.length - 1; i >= 0; i--) { hide(collection[i]); };
|
|
75
|
+
}
|
|
76
|
+
var showAll = function(collection) {
|
|
77
|
+
for (var i = collection.length - 1; i >= 0; i--) { show(collection[i]); };
|
|
78
|
+
}
|
|
79
|
+
var selectSegment = function(segment) {
|
|
80
|
+
if (isSelected(segment)) return;
|
|
81
|
+
var segments = document.querySelectorAll('#segment-bar > a');
|
|
82
|
+
for (var i = segments.length - 1; i >= 0; i--) { deselect(segments[i]);};
|
|
83
|
+
select(segment);
|
|
84
|
+
if (segment.id == "all-segment") {
|
|
85
|
+
showAll(document.querySelectorAll('.test-suite'));
|
|
86
|
+
showAll(document.querySelectorAll('.test'));
|
|
87
|
+
} else if (segment.id == "failing-segment") {
|
|
88
|
+
hideAll(document.querySelectorAll('.test.passing'));
|
|
89
|
+
showAll(document.querySelectorAll('.test.failing'));
|
|
90
|
+
hideAll(document.querySelectorAll('.test-suite.passing'));
|
|
91
|
+
showAll(document.querySelectorAll('.test-suite.failing'));
|
|
92
|
+
} else if (segment.id == "passing-segment") {
|
|
93
|
+
hideAll(document.querySelectorAll('.test.failing'));
|
|
94
|
+
showAll(document.querySelectorAll('.test.passing'));
|
|
95
|
+
hideAll(document.querySelectorAll('.test-suite.failing'));
|
|
96
|
+
showAll(document.querySelectorAll('.test-suite.passing'));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
var toggleScreenshot = function(suiteName, index) {
|
|
100
|
+
var screenshot = document.getElementById("screenshot-" + suiteName + "-" + index);
|
|
101
|
+
isSelected(screenshot) ? deselect(screenshot) : select(screenshot);
|
|
102
|
+
}
|
|
103
|
+
</script>
|
|
104
|
+
</head>
|
|
105
|
+
<body>
|
|
106
|
+
<header>
|
|
107
|
+
<section class="left">
|
|
108
|
+
<h1>Test Results</h1>
|
|
109
|
+
</section>
|
|
110
|
+
<section class="right">
|
|
111
|
+
<section id="counters">
|
|
112
|
+
<h2 id="test-count"><span class="number"><%= test_count %></span> tests</h2>
|
|
113
|
+
<% if fail_count > 0 %>
|
|
114
|
+
<h2 id="fail-count"><span class="number"><%= fail_count %></span> failures</h2>
|
|
115
|
+
<% end %>
|
|
116
|
+
</section>
|
|
117
|
+
<section id="segment-bar">
|
|
118
|
+
<a id="all-segment" onclick="selectSegment(this);" class="selected">All</a><a id="failing-segment" onclick="selectSegment(this);">Failing</a><a id="passing-segment" onclick="selectSegment(this);">Passing</a>
|
|
119
|
+
</section>
|
|
120
|
+
</section>
|
|
121
|
+
</header>
|
|
122
|
+
<section id="test-suites">
|
|
123
|
+
<% test_suites.each do |name, info| %>
|
|
124
|
+
<% next unless info[:tests].size > 0 %>
|
|
125
|
+
<section class="test-suite <%= info[:failing] ? 'failing' : 'passing'%>" id="<%= name %>">
|
|
126
|
+
<section class="heading" onclick="toggleTests(this);">
|
|
127
|
+
<h3 class="title"><%= name %></h3>
|
|
128
|
+
</section>
|
|
129
|
+
<section class="tests">
|
|
130
|
+
<% unless info[:screenshots].empty? %>
|
|
131
|
+
<div class="screenshots <%= info[:failing] ? 'failing' : 'passing'%>">
|
|
132
|
+
<% info[:screenshots].each_with_index do |screenshot, index| %>
|
|
133
|
+
<a href="javascript:toggleScreenshot('<%=name %>', <%=index %>)">
|
|
134
|
+
<img class="screenshot" id="screenshot-<%=name %>-<%=index %>" src="<%=screenshot %>" />
|
|
135
|
+
</a>
|
|
136
|
+
<% end %>
|
|
137
|
+
</div>
|
|
138
|
+
<% end %>
|
|
139
|
+
<table>
|
|
140
|
+
<% info[:tests].each_with_index do |test, index| %>
|
|
141
|
+
<% detail_class = test[:name].gsub(/\s/,'') %>
|
|
142
|
+
<tr class="test <%= test[:failing] ? 'failing' : 'passing'%> <%= index % 2 != 0 ? 'odd' :''%>" onclick="toggleDetails('<%= detail_class %>');">
|
|
143
|
+
<td>
|
|
144
|
+
<% if test[:time] %>
|
|
145
|
+
<h3 class="time"><%= test[:time] %>s</h3>
|
|
146
|
+
<% end %>
|
|
147
|
+
</td>
|
|
148
|
+
<td><h3 class="title"><%= test[:name] %></h3></td>
|
|
149
|
+
</tr>
|
|
150
|
+
<% if test[:reason] || test[:snippet] %>
|
|
151
|
+
<tr class="details <%= detail_class %>">
|
|
152
|
+
<td></td>
|
|
153
|
+
<td>
|
|
154
|
+
<% if test[:reason] %>
|
|
155
|
+
<section class="test-detail reason"><%= test[:reason] %></section>
|
|
156
|
+
<% end %>
|
|
157
|
+
<% if test[:snippet] %>
|
|
158
|
+
<section class="test-detail snippet"><%= test[:snippet] %></section>
|
|
159
|
+
<section class="test-detail"><%= test[:file] %></section>
|
|
160
|
+
<% end %>
|
|
161
|
+
</td>
|
|
162
|
+
</tr>
|
|
163
|
+
<% end %>
|
|
164
|
+
<% end %>
|
|
165
|
+
</table>
|
|
166
|
+
</section>
|
|
167
|
+
</section>
|
|
168
|
+
<% end %>
|
|
169
|
+
</section>
|
|
170
|
+
<footer>Report generated with <a href="https://github.com/supermarin/xcpretty">xcpretty</a></footer>
|
|
171
|
+
</body>
|
|
172
|
+
</html>
|
data/bin/xcpretty
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
if RUBY_VERSION < '2.0.0'
|
|
4
|
+
abort "error: XCPretty requires Ruby 2.0.0 or higher."
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
if $PROGRAM_NAME == __FILE__
|
|
8
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
9
|
+
end
|
|
10
|
+
require 'xcpretty'
|
|
11
|
+
require 'optparse'
|
|
12
|
+
|
|
13
|
+
report_options = []
|
|
14
|
+
report_classes = []
|
|
15
|
+
report_formats = {
|
|
16
|
+
"junit" => XCPretty::JUnit,
|
|
17
|
+
"html" => XCPretty::HTML,
|
|
18
|
+
"json-compilation-database" => XCPretty::JSONCompilationDatabase
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
printer_opts = {
|
|
22
|
+
unicode: XCPretty::Term.unicode?,
|
|
23
|
+
colorize: XCPretty::Term.color?,
|
|
24
|
+
formatter: XCPretty::Simple
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
OptionParser.new do |opts|
|
|
28
|
+
opts.banner = "Usage: xcodebuild [options] | xcpretty"
|
|
29
|
+
opts.on('-t', '--test', 'Use RSpec style output') do
|
|
30
|
+
printer_opts[:formatter] = XCPretty::RSpec
|
|
31
|
+
end
|
|
32
|
+
opts.on('-s', '--simple', 'Use simple output (default)') do
|
|
33
|
+
printer_opts[:formatter] = XCPretty::Simple
|
|
34
|
+
end
|
|
35
|
+
opts.on('-k', '--knock', 'Use knock output') do
|
|
36
|
+
printer_opts[:formatter] = XCPretty::Knock
|
|
37
|
+
end
|
|
38
|
+
opts.on('--tap', 'Use TAP output') do
|
|
39
|
+
printer_opts[:formatter] = XCPretty::TestAnything
|
|
40
|
+
end
|
|
41
|
+
opts.on('-f', '--formatter PATH', 'Use formatter returned from evaluating the specified Ruby file') do |path|
|
|
42
|
+
printer_opts[:formatter] = XCPretty.load_custom_formatter(path)
|
|
43
|
+
end
|
|
44
|
+
opts.on('--[no-]color', 'Use colorized output. Defaults is auto') do |value|
|
|
45
|
+
printer_opts[:colorize] = value
|
|
46
|
+
end
|
|
47
|
+
opts.on('--[no-]utf', 'Use unicode characters in output. Default is auto.') do |value|
|
|
48
|
+
printer_opts[:unicode] = value
|
|
49
|
+
end
|
|
50
|
+
opts.on("-r", "--report FORMAT", "Run FORMAT reporter",
|
|
51
|
+
" Choices: #{report_formats.keys.join(', ')}") do |format|
|
|
52
|
+
report_classes << report_formats[format]
|
|
53
|
+
report_options << {}
|
|
54
|
+
end
|
|
55
|
+
opts.on('-o', '--output PATH', 'Write report output to PATH') do |path|
|
|
56
|
+
unless opts = report_options.last
|
|
57
|
+
XCPretty.exit_with_error('Expected report format to be specified before output path')
|
|
58
|
+
end
|
|
59
|
+
opts[:path] = path
|
|
60
|
+
end
|
|
61
|
+
opts.on('--screenshots', 'Collect screenshots in the HTML report') do
|
|
62
|
+
unless opts = report_options.last
|
|
63
|
+
XCPretty.exit_with_error('Expected screenshot argument to be specified after report format')
|
|
64
|
+
end
|
|
65
|
+
opts[:screenshots] = true
|
|
66
|
+
end
|
|
67
|
+
opts.on_tail('-h', '--help', 'Show this message') { puts opts; exit }
|
|
68
|
+
opts.on_tail("-v", "--version", "Show version") { puts XCPretty::VERSION; exit }
|
|
69
|
+
opts.parse!
|
|
70
|
+
|
|
71
|
+
if STDIN.tty?
|
|
72
|
+
XCPretty.exit_with_error(opts.help)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
printer = XCPretty::Printer.new(printer_opts)
|
|
77
|
+
reporters = report_classes.compact.each_with_index.map { |k, i| k.new(report_options[i]) }
|
|
78
|
+
|
|
79
|
+
STDIN.each_line do |line|
|
|
80
|
+
printer.pretty_print(line)
|
|
81
|
+
reporters.each { |r| r.handle(line) }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
reporters.each(&:finish)
|
|
85
|
+
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Feature: Loading an arbitrary Ruby file as a formatter
|
|
2
|
+
|
|
3
|
+
Scenario: The file loaded does not contain a Ruby class
|
|
4
|
+
When I pipe to xcpretty with "--formatter /bin/bash"
|
|
5
|
+
Then the exit status code should be 1
|
|
6
|
+
|
|
7
|
+
Scenario: The file loaded contains a Ruby class
|
|
8
|
+
Given I have a file to compile
|
|
9
|
+
When I pipe to xcpretty with a custom formatter
|
|
10
|
+
Then the exit status code should be 0
|
|
11
|
+
|
|
12
|
+
Scenario: Showing output using a custom formatter
|
|
13
|
+
Given I have a file to compile
|
|
14
|
+
When I pipe to xcpretty with a custom formatter
|
|
15
|
+
Then I should see a custom compilation message
|