xcpretty 0.0.1

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