xcpretty 0.2.2 → 0.2.3

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