xcpretty 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bb26660a637d4fc3689593415923419565e2c116
4
+ data.tar.gz: 65f2722cb1e05a4fac3be83b94a95a7101e6a0cb
5
+ SHA512:
6
+ metadata.gz: 93be071f3e1f0b6c8723a4233c088fd19f538ff435ac473552f36b2fe3ac80efbaad6bafbe6ac9b7783a559e360586160d34d98ac24ad4cf68acb4632a02c09d
7
+ data.tar.gz: ef12b9807450c1f7a8f81ee845dbc60d28856f31750f1fbdc1965895ca48b2589697b8de76dbb6c5f66b4882fcbd44ade764aa3b27b37a71fa9ce51c87bc730d
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.kick ADDED
@@ -0,0 +1,17 @@
1
+ recipe :ruby
2
+ recipe :ignore
3
+
4
+ ignore(%r{^(spec/fixtures)})
5
+
6
+ process do |files|
7
+ cuke_files = files.take_and_map do |path|
8
+ if path =~ %r{^features/\w+\.feature$}
9
+ path
10
+ elsif path =~ %r{^bin}
11
+ # run all features when bin/xcpretty changes
12
+ Dir.glob("features/**/*.feature")
13
+ end
14
+ end
15
+
16
+ execute "cucumber -f progress #{cuke_files.join(' ')}"
17
+ end
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ rvm: 2.0.0
2
+ language: ruby
3
+ script: rake ci
4
+
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in xcpretty.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'kicker'
8
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Marin Usalj
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # XCPretty
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
+ ## Installation
7
+
8
+ $ gem install xcpretty
9
+
10
+ ## Usage
11
+
12
+ XCPretty is designed to be piped with `xcodebuild` and thus keeping 100% compatibility with it.
13
+ This means, when `xcodebuild` works, `xcpretty` works.
14
+ It's even a bit faster than `xcodebuild` only, since it saves your terminal some prints.
15
+
16
+ ## Formats
17
+
18
+ - simple (default)
19
+ ![xcpretty --simple](http://i.imgur.com/SMx0gUD.gif)
20
+
21
+ - test (RSpec style, shown above)
22
+ ![xcpretty alpha](http://i.imgur.com/VeTQQub.gif)
23
+
24
+ - tun / tap (not yet implemented. possible solution for most CI servers)
25
+
26
+ ## XCPretty isn't
27
+
28
+ Unlike [xctool](https://github.com/facebook/xctool), `xcpretty` isn't a build tool.
29
+ It relies on `xcodebuild` to do the build process, and it formats the output.
30
+
31
+ ## Why?
32
+
33
+ There are many usages of this tool. Let me give you some ideas:
34
+
35
+ - Xcode's test tools are close to useless. Failures in a sidebar, non-dettachable console,... You can use `xcpretty` to build your next Xcode test runner plugin
36
+ - Run tests each time you hit save. The output is minimal, so go and wire it up with Kicker or Guard and be a real hipster!
37
+ - Mine Bitcoins. You can't with this tool, but you'll be so productive that you can earn all the money and buy them!!!1!
38
+
39
+
40
+ ## Benchmark
41
+
42
+ A smaller project ([ObjectiveSugar](https://github.com/mneorr/objectivesugar)) with a fast suite
43
+
44
+ #### XCPretty
45
+ ```
46
+ $ time xcodebuild -workspace ObjectiveSugar.xcworkspace -scheme ObjectiveSugar -sdk iphonesimulator test | xcpretty -tc
47
+ ....................................................................................
48
+
49
+ Executed 84 tests, with 0 failures (0 unexpected) in 0.070 (0.094) seconds
50
+ 4.08 real 5.82 user 2.08 sys
51
+ ```
52
+ #### xcodebuild
53
+ ```
54
+ $ time xcodebuild -workspace ObjectiveSugar.xcworkspace -scheme ObjectiveSugar -sdk iphonesimulator test
55
+ ... ommitted output ...
56
+ Executed 84 tests, with 0 failures (0 unexpected) in 0.103 (0.129) seconds
57
+ ** TEST SUCCEEDED **
58
+
59
+ 4.35 real 6.07 user 2.21 sys
60
+ ```
61
+ #### XCtool
62
+ ```
63
+ $ time xctool -workspace ObjectiveSugar.xcworkspace -scheme ObjectiveSugar -sdk iphonesimulator test
64
+ ... ommitted output ...
65
+ ** TEST SUCCEEDED: 84 passed, 0 failed, 0 errored, 84 total ** (26964 ms)
66
+
67
+ 28.05 real 6.59 user 2.24 sys
68
+ ```
69
+
70
+ A bit bigger project, without CocoaPods ([ReactiveCocoa](https://github.com/ReactiveCocoa/ReactiveCocoa))
71
+
72
+ #### XCPretty
73
+ ```
74
+ $ time xcodebuild -project ReactiveCocoa.xcodeproj -scheme ReactiveCocoa test | xcpretty -tc
75
+ ..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
76
+
77
+ Executed 922 tests, with 0 failures (0 unexpected) in 6.437 (6.761) seconds
78
+ 8.72 real 5.73 user 0.81 sys
79
+ ```
80
+ #### xcodebuild
81
+ ```
82
+ $ time xcodebuild -project ReactiveCocoa.xcodeproj -scheme ReactiveCocoa test
83
+ ... ommitted output ...
84
+ Executed 922 tests, with 0 failures (0 unexpected) in 6.542 (6.913) seconds
85
+ ** TEST SUCCEEDED **
86
+
87
+ 8.82 real 5.65 user 0.75 sys
88
+ ```
89
+ #### XCtool
90
+ ```
91
+ $ time xctool -project ReactiveCocoa.xcodeproj -scheme ReactiveCocoa test
92
+ ... ommitted output ...
93
+ ** TEST SUCCEEDED: 922 passed, 0 failed, 0 errored, 922 total ** (9584 ms)
94
+
95
+ 10.80 real 6.72 user 0.76 sys
96
+ ```
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :kick do
4
+ sh 'kicker -r ruby'
5
+ end
6
+
7
+ task :spec do
8
+ sh 'rspec spec'
9
+ end
10
+
11
+ task :cucumber do
12
+ sh 'cucumber'
13
+ end
14
+
15
+ task :ci do
16
+ Rake::Task[:spec].invoke
17
+ Rake::Task[:cucumber].invoke
18
+ end
19
+
data/bin/xcpretty ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'xcpretty'
4
+ require 'optparse'
5
+
6
+ if RUBY_VERSION < '1.9.3'
7
+ abort "error: XCPretty requires Ruby 1.9.3 or higher."
8
+ end
9
+
10
+ def printer
11
+ @printer ||= XCPretty::Printer::Simple.new
12
+ end
13
+
14
+ OptionParser.new do |opts|
15
+ opts.banner = "Usage: xcodebuild [options] | xcpretty"
16
+ opts.on('-t', '--test', 'Use RSpec style output') do
17
+ @printer = XCPretty::Printer::RSpec.new
18
+ end
19
+ opts.on('-s', '--simple', 'Use simple output (default)') do
20
+ @printer = XCPretty::Printer::Simple.new
21
+ end
22
+ opts.on('-c', '--color', 'Use colorized output') do
23
+ @colorize = true
24
+ end
25
+ opts.on_tail('-h', '--help', 'Show this message') { puts opts; exit }
26
+ opts.on_tail("-v", "--version", "Show version") { puts XCPretty::VERSION; exit }
27
+ opts.parse!
28
+ printer.colorize = @colorize
29
+ end
30
+
31
+ ARGF.each_line do |line|
32
+ printer.pretty_print(line)
33
+ end
@@ -0,0 +1,21 @@
1
+ Feature: Showing build output in simple format
2
+
3
+ Scenario: Showing file compilation
4
+ Given I have a file to compile
5
+ When I run piping with options "--simple"
6
+ Then I should see a successful compilation message
7
+
8
+ Scenario: Showing precompilation
9
+ Given I have a precompiled header
10
+ When I run piping with options "--simple"
11
+ Then I should see a successful precompilation message
12
+
13
+ Scenario: Showing file compilation with colorization
14
+ Given I have a file to compile
15
+ When I run piping with options "--simple --color"
16
+ Then I should see a green success icon
17
+
18
+ Scenario: Showing precompilation
19
+ Given I have a precompiled header
20
+ When I run piping with options "--simple --color"
21
+ Then I should see a green success icon
@@ -0,0 +1,58 @@
1
+ Given(/^I have a file to compile$/) do
2
+ add_run_input SAMPLE_COMPILE
3
+ end
4
+
5
+ Given(/^I have a precompiled header$/) do
6
+ add_run_input SAMPLE_PRECOMPILE
7
+ end
8
+
9
+ Given(/^I have a failing test in my suite$/) do
10
+ add_run_input SAMPLE_SPECTA_FAILURE
11
+ end
12
+
13
+ Given(/^all of my tests will pass in my suite$/) do
14
+ 3.times { add_run_input SAMPLE_OCUNIT_TEST }
15
+ end
16
+
17
+ Given(/^I have a passing test in my suite$/) do
18
+ add_run_input SAMPLE_OCUNIT_TEST
19
+ end
20
+
21
+ When(/^I run piping with options "(.*?)"$/) do |flags|
22
+ run_xcpretty(flags)
23
+ end
24
+
25
+ Then(/^I should see a successful compilation message$/) do
26
+ run_output.should start_with("Compiling")
27
+ end
28
+
29
+ Then(/^I should see a successful precompilation message$/) do
30
+ run_output.should start_with("Precompiling")
31
+ end
32
+
33
+ Then(/^I should see a green success icon$/) do
34
+ run_output.should start_with("#{GREEN_START}✓#{COLOR_END}")
35
+ end
36
+
37
+ Then(/^I should see a failed test icon$/) do
38
+ run_output.should == "F"
39
+ end
40
+
41
+ Then(/^I should see a passing test icon$/) do
42
+ run_output.should == "."
43
+ end
44
+
45
+ Then(/^I should see a red failed test icon$/) do
46
+ run_output.should include("#{RED_START}F#{COLOR_END}")
47
+ end
48
+
49
+ Then(/^the final execution message should be (red|green)$/) do |color|
50
+ last_line = run_output.lines.last
51
+ start_color = color == "red" ? RED_START : GREEN_START
52
+ last_line.should start_with(start_color)
53
+ last_line.should end_with(COLOR_END)
54
+ end
55
+
56
+ Then(/^I should see a green passing test icon$/) do
57
+ run_output.should include("#{GREEN_START}.#{COLOR_END}")
58
+ end
@@ -0,0 +1,35 @@
1
+ $:.unshift File.expand_path('../../..', __FILE__)
2
+
3
+ require "tempfile"
4
+ require "spec/fixtures/constants.rb"
5
+
6
+ INPUT_FILE = "xcpretty_input"
7
+ RED_START = "\e[31m"
8
+ COLOR_END = "\e[0m"
9
+ GREEN_START = "\e[32;1m"
10
+
11
+ def run_xcpretty flags
12
+ add_run_input SAMPLE_EXECUTED_TESTS
13
+ add_run_input SAMPLE_KIWI_SUITE_COMPLETION
14
+ input_file = Tempfile.new(INPUT_FILE)
15
+ File.write(input_file.path, run_input)
16
+ @output = %x(cat '#{input_file.path}' | bin/xcpretty #{flags})
17
+ input_file.unlink
18
+ end
19
+
20
+ def add_run_input text
21
+ run_input << "\n#{text}"
22
+ end
23
+
24
+ def run_input
25
+ @input ||= ""
26
+ end
27
+
28
+ def run_output
29
+ @output ||= ""
30
+ end
31
+
32
+ After do
33
+ @input = ""
34
+ @output = ""
35
+ end
@@ -0,0 +1,27 @@
1
+ Feature: Showing RSpec-style test output
2
+
3
+ Scenario: Showing failed tests
4
+ Given I have a failing test in my suite
5
+ When I run piping with options "--test"
6
+ Then I should see a failed test icon
7
+
8
+ Scenario: Showing passing tests
9
+ Given I have a passing test in my suite
10
+ When I run piping with options "--test"
11
+ Then I should see a passing test icon
12
+
13
+ Scenario: Showing some tests failed with colorization
14
+ Given I have a failing test in my suite
15
+ When I run piping with options "--test --color"
16
+ Then I should see a red failed test icon
17
+ And the final execution message should be red
18
+
19
+ Scenario: Showing passing tests with colorization
20
+ Given I have a passing test in my suite
21
+ When I run piping with options "--test --color"
22
+ Then I should see a green passing test icon
23
+
24
+ Scenario: Showing that all tests passed with color
25
+ Given all of my tests will pass in my suite
26
+ When I run piping with options "--test --color"
27
+ Then the final execution message should be green
@@ -0,0 +1,105 @@
1
+ require "paint"
2
+
3
+ module XCPretty
4
+
5
+ module Printer
6
+
7
+ attr_accessor :colorize
8
+
9
+ # @regex Captured groups
10
+ # $1 = file
11
+ # $2 = test_case
12
+ # $3 = failure_message
13
+ FAILING_TEST_MATCHER = /(.+:\d+):\serror:\s[\+\-]\[(.*)\]\s:(?:\s'.*'\s\[FAILED\],)?\s(.*)/
14
+
15
+ # @regex Captured groups
16
+ # $1 = test_case
17
+ # $2 = time
18
+ PASSING_TEST_MATCHER = /Test Case\s'-\[(.*)\]'\spassed\s\((\d*\.\d{3})\sseconds\)/
19
+
20
+ TESTS_DONE_MATCHER = /Test Suite ('.*\.(oc|xc)test(.*)') finished at/
21
+ EXECUTED_MATCHER = /^Executed/
22
+
23
+ Paint::SHORTCUTS[:printer] = {
24
+ :white => Paint.color(:bold),
25
+ :red => Paint.color(:red),
26
+ :green => Paint.color(:green, :bright),
27
+ :link => Paint.color(:cyan),
28
+ }
29
+
30
+ include Paint::Printer
31
+
32
+ def pretty_print(text)
33
+ update_test_state(text)
34
+ formatted_text = pretty_format(text)
35
+ formatted_text = format_test_summary(text) if formatted_text.empty?
36
+
37
+ STDOUT.print(formatted_text + optional_newline) unless formatted_text.empty?
38
+ end
39
+
40
+ def update_test_state(text)
41
+ case text
42
+ when FAILING_TEST_MATCHER
43
+ store_failure($1, $2, $3)
44
+ when TESTS_DONE_MATCHER
45
+ @tests_done = true
46
+ end
47
+ end
48
+
49
+ def format_test_summary(text)
50
+ if text =~ EXECUTED_MATCHER && @tests_done && !@printed_summary
51
+ @printed_summary = true
52
+ test_summary(text)
53
+ else
54
+ ""
55
+ end
56
+ end
57
+
58
+ def optional_newline
59
+ ""
60
+ end
61
+
62
+ def project_build_info(text)
63
+ target = text.split('TARGET').last.split('OF PROJECT').first
64
+ clean_target = target.split('-').last.strip
65
+ project = text.split('OF PROJECT').last.split('WITH').first.strip
66
+ configuration = text.split('CONFIGURATION').last.split('===').first.strip
67
+ {
68
+ :target => clean_target,
69
+ :project => project,
70
+ :configuration => configuration
71
+ }
72
+ end
73
+
74
+ def test_summary(executed_message)
75
+ formatted_failures = failures.map do |f|
76
+ reason = colorize? ? red(f[:failure_message]) : f[:failure_message]
77
+ path = colorize? ? link(f[:file]) : f[:file]
78
+ "#{f[:test_case]}, #{reason}\n#{path}"
79
+ end.join("\n\n")
80
+ final_message = if colorize?
81
+ failures.any? ? red(executed_message) : green(executed_message)
82
+ else
83
+ executed_message
84
+ end
85
+ text = [formatted_failures, final_message].join("\n\n\n").strip
86
+ "\n\n#{text}"
87
+ end
88
+
89
+ def failures
90
+ @failures ||= []
91
+ end
92
+
93
+ def store_failure(file, test_case, failure_message)
94
+ failures << {
95
+ file: file,
96
+ test_case: test_case,
97
+ failure_message: failure_message
98
+ }
99
+ end
100
+
101
+ def colorize?
102
+ !!@colorize
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,24 @@
1
+ module XCPretty
2
+ module Printer
3
+
4
+ class RSpec
5
+
6
+ include Printer
7
+
8
+ FAIL = "F"
9
+ PASS = "."
10
+
11
+ def pretty_format(text)
12
+ case text
13
+ when PASSING_TEST_MATCHER
14
+ colorize? ? green(PASS) : PASS
15
+ when FAILING_TEST_MATCHER
16
+ colorize? ? red(FAIL) : FAIL
17
+ else
18
+ ""
19
+ end
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,124 @@
1
+ require 'shellwords'
2
+
3
+ module XCPretty
4
+ module Printer
5
+
6
+ class Simple
7
+
8
+ include Printer
9
+
10
+ PASS = "✓"
11
+ FAIL = "✗"
12
+
13
+ def pretty_format(text)
14
+ case text
15
+ when /^ProcessPCH/
16
+ print_pch(text)
17
+ when /^CompileC/
18
+ print_compiling(text)
19
+ when /^Clean.Remove/
20
+ ""
21
+ when /^Check dependencies/
22
+ ""
23
+ when /^=== CLEAN TARGET/
24
+ print_clean_target(text)
25
+ when /^=== BUILD TARGET/
26
+ print_build_target(text)
27
+ when /^PhaseScriptExecution/
28
+ print_run_script(text)
29
+ when /^Libtool/
30
+ print_libtool(text)
31
+ when /^CpResource/
32
+ print_cpresource(text)
33
+ when /^CopyStringsFile/
34
+ print_copy_strings_file(text)
35
+ when /^GenerateDSYMFile/
36
+ print_generating_dsym(text)
37
+ when /^ProcessInfoPlistFile/
38
+ print_processing_info_plist(text)
39
+ when /^Ld/
40
+ print_linking(text)
41
+ when PASSING_TEST_MATCHER
42
+ print_passing_test($1, $2)
43
+ when FAILING_TEST_MATCHER
44
+ print_failing_test($2, $3)
45
+ else
46
+ ""
47
+ end
48
+ end
49
+
50
+ def optional_newline
51
+ "\n"
52
+ end
53
+
54
+ def print_failing_test(test_case, reason)
55
+ format("", "#{test_case}, #{reason}", false)
56
+ end
57
+
58
+ def print_passing_test(test_case, time)
59
+ format("", "#{test_case} (#{time} seconds)")
60
+ end
61
+
62
+ def print_linking(text)
63
+ format("Linking", text.shellsplit[1].split('/').last)
64
+ end
65
+
66
+ def print_pch(text)
67
+ format("Precompiling", Shellwords.shellsplit(text)[2])
68
+ end
69
+
70
+ def print_processing_info_plist(text)
71
+ format("Processing", text.lines.first.shellsplit.last.split('/').last)
72
+ end
73
+
74
+ def print_compiling(text)
75
+ format("Compiling", text.shellsplit[2].split('/').last)
76
+ end
77
+
78
+ def print_clean_target(text)
79
+ info = project_build_info(text)
80
+ format("Cleaning", "#{info[:project]}/#{info[:target]} [#{info[:configuration]}]")
81
+ end
82
+
83
+ def print_build_target(text)
84
+ info = project_build_info(text)
85
+ format("Building", "#{info[:project]}/#{info[:target]} [#{info[:configuration]}]")
86
+ end
87
+
88
+ def print_run_script(text)
89
+ format("Running script", "'#{text.lines.first.shellsplit[1..-2].join(' ').gsub('\ ',' ')}'")
90
+ end
91
+
92
+ def print_libtool(text)
93
+ format("Building library", text.shellsplit[1].split('/').last)
94
+ end
95
+
96
+ def print_cpresource(text)
97
+ format("Copying", text.shellsplit[1])
98
+ end
99
+
100
+ def print_copy_strings_file(text)
101
+ format("Copying", text.shellsplit.last.split('/').last)
102
+ end
103
+
104
+ def print_generating_dsym(text)
105
+ format("Generating DSYM file")
106
+ end
107
+
108
+ def format(command, argument_text="", success=true)
109
+ command_text = colorize? ? white(command) : command
110
+ [status_symbol(success), command_text, argument_text].join(" ").strip
111
+ end
112
+
113
+ def status_symbol(success)
114
+ if success && colorize?
115
+ green(PASS)
116
+ elsif colorize?
117
+ red(FAIL)
118
+ else
119
+ ""
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,3 @@
1
+ module XCPretty
2
+ VERSION = "0.0.1"
3
+ end
data/lib/xcpretty.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "xcpretty/version"
2
+ require "xcpretty/printer"
3
+ require "xcpretty/printers/simple"
4
+ require "xcpretty/printers/rspec"
5
+
6
+ module XCPretty
7
+ # Your code goes here...
8
+ end