xcpretty 0.2.2 → 0.2.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6174a374d362e6eef62f59962119eb7b6aaf384e
4
- data.tar.gz: 14df3e40231cf38544095c3385b327375eaa4759
3
+ metadata.gz: c9e545d9dce2b78bc9b2e752084c12eea449548c
4
+ data.tar.gz: 66f8241eb6083b21bad323f67b523487beb8ddd2
5
5
  SHA512:
6
- metadata.gz: 9216ed7953d333dc50fee64448f7c768c0e5779a8e37c8a574d8760ebe39465c17d0639dd95218d5b8c5ccccc3c02d1417122b73547fb451e0ffe29fbd0d72ff
7
- data.tar.gz: f2bcf82f2de77686c8fac0b01cc26a14c39938ba619fbfcae0634dab5607eb8d7db2dc8979044740ef48f990fb7df7ce180d28d829e23b2e117dc1c67b62b56c
6
+ metadata.gz: bcbddd17addbb98fdf571bec535dfe1a1bdaf82e25c2d735988c8b2b012be022251365f129d9de7ba6a97ae2edc4f601acf802778af0940dfe4ed2961489bf2c
7
+ data.tar.gz: 8449afa6fea052c28f75667785072ca269c2c1a04e87feada85f90ff5e5f53f19d49780345a5b89003e28a1d40ac3fdd669bb56f1e9823a0b85133e8c8fd6672
data/README.md CHANGED
@@ -67,7 +67,7 @@ $ xcodebuild [flags] | tee xcodebuild.log | xcpretty
67
67
  - `--report html`, `-r html`: Creates a simple HTML report at `build/reports/tests.html`.
68
68
  ![xcpretty html](http://i.imgur.com/0Rnux3v.gif)
69
69
 
70
- - `--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
+ - `--report json-compilation-database`, `-r json-compilation-database`: Creates a [JSON compilation database](http://clang.llvm.org/docs/JSONCompilationDatabase.html) at `build/reports/compilation_db.json`. This is a format to replay single compilations independently of the build system.
71
71
 
72
72
  Writing a report to a custom path can be specified using `--output PATH`.
73
73
 
@@ -76,7 +76,7 @@ Writing a report to a custom path can be specified using `--output PATH`.
76
76
  `xcpretty` supports custom formatters through the use of the
77
77
  `--formatter` flag, which takes a path to a file as an argument. The
78
78
  file must contain a Ruby subclass of `XCPretty::Formatter`, and
79
- return that class at the end of te file. The class
79
+ return that class at the end of the file. The class
80
80
  can override the `format_*` methods to hook into output parsing
81
81
  events.
82
82
 
data/Rakefile CHANGED
@@ -23,3 +23,4 @@ task :ci do
23
23
  Rake::Task[:cucumber].invoke
24
24
  Rake::Task[:lint].invoke
25
25
  end
26
+
@@ -39,17 +39,21 @@ OptionParser.new do |opts|
39
39
  printer_opts[:formatter] = XCPretty::TestAnything
40
40
  end
41
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)
42
+ printer_opts[:formatter] = XCPretty.load_custom_class(path)
43
43
  end
44
- opts.on('--[no-]color', 'Use colorized output. Defaults is auto') do |value|
44
+ opts.on('-c', '--[no-]color', 'Use colorized output. Default is auto') do |value|
45
45
  printer_opts[:colorize] = value
46
46
  end
47
47
  opts.on('--[no-]utf', 'Use unicode characters in output. Default is auto.') do |value|
48
48
  printer_opts[:unicode] = value
49
49
  end
50
- opts.on("-r", "--report FORMAT", "Run FORMAT reporter",
50
+ opts.on("-r", "--report FORMAT or PATH", "Run FORMAT or PATH reporter",
51
51
  " Choices: #{report_formats.keys.join(', ')}") do |format|
52
- report_classes << report_formats[format]
52
+ if report_formats.key?(format)
53
+ report_classes << report_formats[format]
54
+ else
55
+ report_classes << XCPretty.load_custom_class(format)
56
+ end
53
57
  report_options << {}
54
58
  end
55
59
  opts.on('-o', '--output PATH', 'Write report output to PATH') do |path|
@@ -81,5 +85,6 @@ STDIN.each_line do |line|
81
85
  reporters.each { |r| r.handle(line) }
82
86
  end
83
87
 
88
+ printer.finish
84
89
  reporters.each(&:finish)
85
90
 
@@ -0,0 +1,29 @@
1
+ Feature: Loading an arbitrary Ruby file as a reporter
2
+
3
+ Background:
4
+ Given the tests have started running
5
+
6
+ Scenario: The file loaded does not contain a Ruby class
7
+ When I pipe to xcpretty with "-r /bin/bash"
8
+ Then the exit status code should be 1
9
+
10
+ Scenario: The file loaded contains a Ruby class
11
+ Given I have a file to compile
12
+ When I pipe to xcpretty with a custom reporter
13
+ Then the exit status code should be 0
14
+
15
+ Scenario: Showing failed tests
16
+ Given I have a failing test in my suite
17
+ When I pipe to xcpretty with a custom reporter
18
+ Then I should see a failed test in my custom report
19
+ And the custom failure counter should show 1 test
20
+
21
+ Scenario: Showing passing tests
22
+ Given I have a passing test in my suite
23
+ When I pipe to xcpretty with a custom reporter
24
+ Then I should see a passing test in my custom report
25
+
26
+ Scenario: Showing pending tests
27
+ Given I have a pending test in my suite
28
+ When I pipe to xcpretty with a custom reporter
29
+ Then I should see a pending test in my custom report
@@ -45,6 +45,11 @@ Feature: Showing build output in simple format
45
45
  When I pipe to xcpretty with "--simple --color"
46
46
  Then I should see a yellow completion icon
47
47
 
48
+ Scenario: Showing aggregate target
49
+ Given I have an aggregate target to build
50
+ When I pipe to xcpretty with "--simple --no-color"
51
+ Then I should see an aggregate target message
52
+
48
53
  Scenario: Showing analyze
49
54
  Given I have a file to analyze
50
55
  When I pipe to xcpretty with "--simple --no-color"
@@ -0,0 +1,16 @@
1
+ Then(/^I should see a passing test in my custom report$/) do
2
+ custom_report.should include("WOW such PASS.")
3
+ end
4
+
5
+ Then(/^I should see a failed test in my custom report$/) do
6
+ custom_report.should include("WOW such FAIL.")
7
+ end
8
+
9
+ Then(/^I should see a pending test in my custom report$/) do
10
+ custom_report.should include("WOW such PENDING.")
11
+ end
12
+
13
+ Then(/^the custom failure counter should show (\d+) tests?$/) do |fail_count|
14
+ custom_report.should include("Much 1 FAIL.")
15
+ end
16
+
@@ -15,6 +15,10 @@ Given(/^I have a precompiled header$/) do
15
15
  add_run_input SAMPLE_PRECOMPILE
16
16
  end
17
17
 
18
+ Given(/^I have an aggregate target to build$/) do
19
+ add_run_input SAMPLE_AGGREGATE_TARGET
20
+ end
21
+
18
22
  Given(/^I have a file to analyze$/) do
19
23
  add_run_input SAMPLE_ANALYZE
20
24
  end
@@ -169,6 +173,10 @@ Then(/^I should see a successful precompilation message$/) do
169
173
  run_output.should start_with("▸ Precompiling")
170
174
  end
171
175
 
176
+ Then(/^I should see an aggregate target message$/) do
177
+ run_output.should start_with("▸ Aggregate")
178
+ end
179
+
172
180
  Then(/^I should see a successful analyze message$/) do
173
181
  run_output.should start_with("▸ Analyzing")
174
182
  end
@@ -39,3 +39,4 @@ Then(/^entries with a command shouldn't have malformed "-include" directives$/)
39
39
  entries = json_db.select { |entry| entry['command'].match(/-include\s+-/) }
40
40
  entries.length.should == 0
41
41
  end
42
+
@@ -20,3 +20,8 @@ Then(/^I should have a test report in a custom path$/) do
20
20
  step("I should have a test report at \"#{custom_report_path}\"")
21
21
  end
22
22
 
23
+ When(/^I pipe to xcpretty with a custom reporter$/) do
24
+ reporter_path = File.expand_path('../../../spec/fixtures/custom_reporter.rb', __FILE__)
25
+ run_xcpretty("-r #{reporter_path}")
26
+ end
27
+
@@ -8,6 +8,7 @@ require 'lib/xcpretty/version'
8
8
  require 'lib/xcpretty/syntax'
9
9
  require 'rexml/document'
10
10
  require 'lib/xcpretty/formatters/formatter'
11
+ require 'lib/xcpretty/reporters/reporter'
11
12
  require 'lib/xcpretty/reporters/junit'
12
13
  require 'lib/xcpretty/reporters/html'
13
14
  require 'lib/xcpretty/reporters/json_compilation_database'
@@ -79,6 +80,10 @@ def junit_report_root
79
80
  junit_report.root.elements.to_a.first
80
81
  end
81
82
 
83
+ def custom_report
84
+ @custom_report ||= File.open(XCPretty::Reporter::FILEPATH, 'r').read
85
+ end
86
+
82
87
  def custom_report_path
83
88
  @custom_report_path ||= begin
84
89
  @custom_report_file1 = Tempfile.new('custom_report_path')
@@ -111,7 +116,8 @@ After do
111
116
  @json = nil
112
117
  FileUtils.rm_rf(XCPretty::JUnit::FILEPATH)
113
118
  FileUtils.rm_rf(XCPretty::HTML::FILEPATH)
114
- FileUtils.rm_rf(XCPretty::JSONCompilationDatabase::FILE_PATH)
119
+ FileUtils.rm_rf(XCPretty::JSONCompilationDatabase::FILEPATH)
120
+ FileUtils.rm_rf(XCPretty::Reporter::FILEPATH)
115
121
  File.delete(@screenshot_file_path) if @screenshot_file_path
116
122
  end
117
123
 
@@ -8,6 +8,7 @@ require 'xcpretty/formatters/simple'
8
8
  require 'xcpretty/formatters/rspec'
9
9
  require 'xcpretty/formatters/knock'
10
10
  require 'xcpretty/formatters/tap'
11
+ require 'xcpretty/reporters/reporter'
11
12
  require 'xcpretty/reporters/junit'
12
13
  require 'xcpretty/reporters/html'
13
14
  require 'xcpretty/reporters/json_compilation_database'
@@ -21,11 +22,11 @@ module XCPretty
21
22
  klass
22
23
  end
23
24
 
24
- def self.load_custom_formatter(path)
25
+ def self.load_custom_class(path)
25
26
  $LOAD_PATH.unshift File.dirname(path)
26
27
  class_from_path(path)
27
28
  rescue SyntaxError => e
28
- exit_with_error("Expected formatter source file to return a class. #{e}")
29
+ exit_with_error("Expected custom source file to return a class. #{e}")
29
30
  end
30
31
 
31
32
  def self.exit_with_error(message)
@@ -11,6 +11,7 @@ module XCPretty
11
11
 
12
12
  def format_analyze(file_name, file_path); EMPTY; end
13
13
  def format_build_target(target, project, configuration); EMPTY; end
14
+ def format_aggregate_target(target, project, configuration); EMPTY; end
14
15
  def format_analyze_target(target, project, configuration); EMPTY; end
15
16
  def format_check_dependencies; EMPTY; end
16
17
  def format_clean(project, target, configuration); EMPTY; end
@@ -30,7 +31,7 @@ module XCPretty
30
31
  def format_passing_test(suite, test, time); EMPTY; end
31
32
  def format_pending_test(suite, test); EMPTY; end
32
33
  def format_measuring_test(suite, test, time); EMPTY; end
33
- def format_failing_test(suite, test, time, file_path); EMPTY; end
34
+ def format_failing_test(suite, test, reason, file_path); EMPTY; end
34
35
  def format_process_pch(file); EMPTY; end
35
36
  def format_process_pch_command(file_path); EMPTY; end
36
37
  def format_phase_success(phase_name); EMPTY; end
@@ -78,6 +79,9 @@ module XCPretty
78
79
  @parser = Parser.new(self)
79
80
  end
80
81
 
82
+ def finish
83
+ end
84
+
81
85
  # Override if you want to catch something specific with your regex
82
86
  def pretty_format(text)
83
87
  parser.parse(text)
@@ -158,10 +162,19 @@ module XCPretty
158
162
  end
159
163
 
160
164
  def format_failure(f)
161
- " #{f[:test_case]}, #{red(f[:reason])}\n #{cyan(f[:file_path])}\n" \
162
- " ```\n" +
163
- Syntax.highlight(Snippet.from_filepath(f[:file_path])) +
164
- " ```"
165
+ snippet = Snippet.from_filepath(f[:file_path])
166
+
167
+ output = " #{f[:test_case]}, #{red(f[:reason])}\n " \
168
+ "#{cyan(f[:file_path])}\n ```\n"
169
+
170
+ if @colorize
171
+ output += Syntax.highlight(snippet)
172
+ else
173
+ output += snippet.contents
174
+ end
175
+
176
+ output += " ```"
177
+ output
165
178
  end
166
179
 
167
180
  def error_symbol
@@ -174,4 +187,3 @@ module XCPretty
174
187
 
175
188
  end
176
189
  end
177
-
@@ -27,6 +27,10 @@ module XCPretty
27
27
  format("Building", "#{project}/#{target} [#{configuration}]")
28
28
  end
29
29
 
30
+ def format_aggregate_target(target, project, configuration)
31
+ format("Aggregate", "#{project}/#{target} [#{configuration}]")
32
+ end
33
+
30
34
  def format_analyze_target(target, project, configuration)
31
35
  format("Analyzing", "#{project}/#{target} [#{configuration}]")
32
36
  end
@@ -7,7 +7,7 @@ module XCPretty
7
7
  # @regex Captured groups
8
8
  # $1 file_path
9
9
  # $2 file_name
10
- ANALYZE_MATCHER = /^Analyze(?:Shallow)?\s(.*\/(.*\.m))*/
10
+ ANALYZE_MATCHER = /^Analyze(?:Shallow)?\s(.*\/(.*\.(?:m|mm|cc|cpp|c|cxx)))\s*/
11
11
 
12
12
  # @regex Captured groups
13
13
  # $1 target
@@ -15,6 +15,12 @@ module XCPretty
15
15
  # $3 configuration
16
16
  BUILD_TARGET_MATCHER = /^=== BUILD TARGET\s(.*)\sOF PROJECT\s(.*)\sWITH.*CONFIGURATION\s(.*)\s===/
17
17
 
18
+ # @regex Captured groups
19
+ # $1 target
20
+ # $2 project
21
+ # $3 configuration
22
+ AGGREGATE_TARGET_MATCHER = /^=== BUILD AGGREGATE TARGET\s(.*)\sOF PROJECT\s(.*)\sWITH.*CONFIGURATION\s(.*)\s===/
23
+
18
24
  # @regex Captured groups
19
25
  # $1 target
20
26
  # $2 project
@@ -92,7 +98,12 @@ module XCPretty
92
98
  # $2 = test_suite
93
99
  # $3 = test_case
94
100
  # $4 = reason
95
- FAILING_TEST_MATCHER = /^\s*(.+:\d+):\serror:\s[\+\-]\[(.*)\s(.*)\]\s:(?:\s'.*'\s\[FAILED\],)?\s(.*)/
101
+ TEST_FAILURE_MATCHER = /^\s*(.+:\d+):\serror:\s[\+\-]\[(.*)\s(.*)\]\s:(?:\s'.*'\s\[FAILED\],)?\s(.*)/
102
+
103
+ # @regex Captured groups
104
+ # $1 = file
105
+ # $2 = reason
106
+ TEST_UI_FAILURE_MATCHER = /Assertion\sFailure:\s(.+:\d+):\s(.*)/
96
107
 
97
108
  # @regex Captured groups
98
109
  # $1 = dsym
@@ -106,7 +117,13 @@ module XCPretty
106
117
  # $1 = target
107
118
  # $2 = build_variants (normal, profile, debug)
108
119
  # $3 = architecture
109
- LINKING_MATCHER = /^Ld \/.*\/(.*) (.*) (.*)$/
120
+ LINKING_MATCHER = /^Ld \/?.*\/(.*?) (.*) (.*)$/
121
+
122
+ # @regex Captured groups
123
+ # $1 = suite
124
+ # $2 = test_case
125
+ # $3 = time
126
+ FAILING_TEST_MATCHER = /^\s*Test Case\s'-\[(.*)\s(.*)\]'\sfailed\s\((\d*\.\d{3})\sseconds\)/
110
127
 
111
128
  # @regex Captured groups
112
129
  # $1 = suite
@@ -281,6 +298,8 @@ module XCPretty
281
298
  formatter.format_analyze($2, $1)
282
299
  when BUILD_TARGET_MATCHER
283
300
  formatter.format_build_target($1, $2, $3)
301
+ when AGGREGATE_TARGET_MATCHER
302
+ formatter.format_aggregate_target($1, $2, $3)
284
303
  when ANALYZE_TARGET_MATCHER
285
304
  formatter.format_analyze_target($1, $2, $3)
286
305
  when CLEAN_REMOVE_MATCHER
@@ -315,7 +334,7 @@ module XCPretty
315
334
  formatter.format_cpresource($1)
316
335
  when EXECUTED_MATCHER
317
336
  format_summary_if_needed(text)
318
- when FAILING_TEST_MATCHER
337
+ when TEST_FAILURE_MATCHER
319
338
  formatter.format_failing_test($2, $3, $4, $1)
320
339
  when FATAL_ERROR_MATCHER
321
340
  formatter.format_error($1)
@@ -335,6 +354,12 @@ module XCPretty
335
354
  formatter.format_measuring_test($1, $2, $3)
336
355
  when PENDING_TEST_MATCHER
337
356
  formatter.format_pending_test($1, $2)
357
+ when FAILING_TEST_MATCHER
358
+ if @current_assertion_failure
359
+ formatter.format_failing_test($1, $2, @current_assertion_failure[:reason], @current_assertion_failure[:file])
360
+ else
361
+ formatter.format_failing_test($1, $2, '', '')
362
+ end
338
363
  when PASSING_TEST_MATCHER
339
364
  formatter.format_passing_test($1, $2, $3)
340
365
  when PODS_ERROR_MATCHER
@@ -384,9 +409,22 @@ module XCPretty
384
409
  @tests_done = false
385
410
  @formatted_summary = false
386
411
  @failures = {}
412
+ @assertion_failure = []
413
+ @current_assertion_failure = {}
387
414
  when TESTS_RUN_COMPLETION_MATCHER
388
415
  @tests_done = true
416
+ when TEST_UI_FAILURE_MATCHER
417
+ @current_assertion_failure = {
418
+ file: $1,
419
+ reason: $2
420
+ }
389
421
  when FAILING_TEST_MATCHER
422
+ if @current_assertion_failure
423
+ store_failure(@current_assertion_failure[:file], $1, $2, @current_assertion_failure[:reason])
424
+ else
425
+ store_failure(nil, $1, $2, '')
426
+ end
427
+ when TEST_FAILURE_MATCHER
390
428
  store_failure($1, $2, $3, $4)
391
429
  end
392
430
  end
@@ -535,4 +573,3 @@ module XCPretty
535
573
 
536
574
  end
537
575
  end
538
-
@@ -11,6 +11,10 @@ module XCPretty
11
11
  @formatter = klass.new(params[:unicode], params[:colorize])
12
12
  end
13
13
 
14
+ def finish
15
+ @formatter.finish
16
+ end
17
+
14
18
  def pretty_print(text)
15
19
  formatted_text = formatter.pretty_format(text)
16
20
  unless formatted_text.empty?
@@ -1,7 +1,6 @@
1
1
  module XCPretty
2
- class HTML
2
+ class HTML < Reporter
3
3
 
4
- include XCPretty::FormatMethods
5
4
  FILEPATH = 'build/reports/tests.html'
6
5
  TEMPLATE = File.expand_path('../../../../assets/report.html.erb', __FILE__)
7
6
  SCREENSHOT_DIR = 'build/reports'
@@ -16,12 +15,8 @@ module XCPretty
16
15
  end
17
16
 
18
17
  def initialize(options)
19
- load_dependencies
18
+ super(options)
20
19
  @test_suites = {}
21
- @filepath = options[:path] || FILEPATH
22
- @parser = Parser.new(self)
23
- @test_count = 0
24
- @fail_count = 0
25
20
  @collect_screenshots = options[:screenshots]
26
21
  end
27
22
 
@@ -39,16 +34,11 @@ module XCPretty
39
34
  add_test(suite, name: test_case, time: time)
40
35
  end
41
36
 
42
- def finish
43
- FileUtils.mkdir_p(File.dirname(@filepath))
44
- write_report
45
- end
46
-
47
37
  private
48
38
 
49
39
  def formatted_snippet(filepath)
50
40
  snippet = Snippet.from_filepath(filepath)
51
- Syntax.highlight(snippet)
41
+ Syntax.highlight_html(snippet)
52
42
  end
53
43
 
54
44
 
@@ -1,8 +1,7 @@
1
1
  module XCPretty
2
- class JSONCompilationDatabase
2
+ class JSONCompilationDatabase < Reporter
3
3
 
4
- include XCPretty::FormatMethods
5
- FILE_PATH = 'build/reports/compilation_db.json'
4
+ FILEPATH = 'build/reports/compilation_db.json'
6
5
 
7
6
  def load_dependencies
8
7
  unless @@loaded ||= false
@@ -14,19 +13,13 @@ module XCPretty
14
13
  end
15
14
 
16
15
  def initialize(options)
17
- load_dependencies
18
- @file_path = options[:path] || FILE_PATH
19
- @parser = Parser.new(self)
16
+ super(options)
20
17
  @compilation_units = []
21
18
  @pch_path = nil
22
19
  @current_file = nil
23
20
  @current_path = nil
24
21
  end
25
22
 
26
- def handle(line)
27
- @parser.parse(line)
28
- end
29
-
30
23
  def format_process_pch_command(file_path)
31
24
  @pch_path = file_path
32
25
  end
@@ -48,15 +41,8 @@ module XCPretty
48
41
  directory: directory}
49
42
  end
50
43
 
51
- def finish
52
- FileUtils.mkdir_p(File.dirname(@file_path))
53
- write_report
54
- end
55
-
56
- private
57
-
58
44
  def write_report
59
- File.open(@file_path, 'w') do |f|
45
+ File.open(@filepath, 'w') do |f|
60
46
  f.write(@compilation_units.to_json)
61
47
  end
62
48
  end