learn-xcpretty 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.kick +17 -0
  4. data/.travis.yml +18 -0
  5. data/CHANGELOG.md +152 -0
  6. data/CONTRIBUTING.md +60 -0
  7. data/Gemfile +8 -0
  8. data/LICENSE.txt +61 -0
  9. data/README.md +143 -0
  10. data/Rakefile +24 -0
  11. data/assets/report.html.erb +155 -0
  12. data/bin/learn-xcpretty +80 -0
  13. data/features/custom_formatter.feature +15 -0
  14. data/features/fixtures/xcodebuild.log +5963 -0
  15. data/features/html_report.feature +40 -0
  16. data/features/json_compilation_database_report.feature +21 -0
  17. data/features/junit_report.feature +44 -0
  18. data/features/knock_format.feature +11 -0
  19. data/features/simple_format.feature +172 -0
  20. data/features/steps/formatting_steps.rb +268 -0
  21. data/features/steps/html_steps.rb +23 -0
  22. data/features/steps/json_steps.rb +37 -0
  23. data/features/steps/junit_steps.rb +38 -0
  24. data/features/steps/report_steps.rb +21 -0
  25. data/features/steps/xcpretty_steps.rb +31 -0
  26. data/features/support/env.rb +108 -0
  27. data/features/tap_format.feature +31 -0
  28. data/features/test_format.feature +39 -0
  29. data/features/xcpretty.feature +14 -0
  30. data/learn-xcpretty.gemspec +37 -0
  31. data/lib/xcpretty/ansi.rb +71 -0
  32. data/lib/xcpretty/formatters/formatter.rb +134 -0
  33. data/lib/xcpretty/formatters/knock.rb +34 -0
  34. data/lib/xcpretty/formatters/rspec.rb +27 -0
  35. data/lib/xcpretty/formatters/simple.rb +155 -0
  36. data/lib/xcpretty/formatters/tap.rb +39 -0
  37. data/lib/xcpretty/parser.rb +421 -0
  38. data/lib/xcpretty/printer.rb +20 -0
  39. data/lib/xcpretty/reporters/html.rb +73 -0
  40. data/lib/xcpretty/reporters/json_compilation_database.rb +58 -0
  41. data/lib/xcpretty/reporters/junit.rb +99 -0
  42. data/lib/xcpretty/reporters/learn.rb +154 -0
  43. data/lib/xcpretty/snippet.rb +34 -0
  44. data/lib/xcpretty/syntax.rb +20 -0
  45. data/lib/xcpretty/version.rb +3 -0
  46. data/lib/xcpretty.rb +39 -0
  47. data/spec/fixtures/NSStringTests.m +64 -0
  48. data/spec/fixtures/constants.rb +546 -0
  49. data/spec/fixtures/custom_formatter.rb +17 -0
  50. data/spec/fixtures/oneliner.m +1 -0
  51. data/spec/fixtures/raw_kiwi_compilation_fail.txt +24 -0
  52. data/spec/fixtures/raw_kiwi_fail.txt +1896 -0
  53. data/spec/fixtures/raw_specta_fail.txt +3110 -0
  54. data/spec/spec_helper.rb +6 -0
  55. data/spec/support/matchers/colors.rb +20 -0
  56. data/spec/xcpretty/ansi_spec.rb +46 -0
  57. data/spec/xcpretty/formatters/formatter_spec.rb +113 -0
  58. data/spec/xcpretty/formatters/rspec_spec.rb +55 -0
  59. data/spec/xcpretty/formatters/simple_spec.rb +129 -0
  60. data/spec/xcpretty/parser_spec.rb +421 -0
  61. data/spec/xcpretty/printer_spec.rb +53 -0
  62. data/spec/xcpretty/snippet_spec.rb +39 -0
  63. data/spec/xcpretty/syntax_spec.rb +35 -0
  64. data/vendor/json_pure/COPYING +57 -0
  65. data/vendor/json_pure/LICENSE +340 -0
  66. data/vendor/json_pure/generator.rb +443 -0
  67. data/vendor/json_pure/parser.rb +364 -0
  68. metadata +261 -0
@@ -0,0 +1,23 @@
1
+ Then(/^I should see a test suite section in HTML$/) do
2
+ html_test_suites.first.should_not be_nil
3
+ end
4
+
5
+ Then(/^I should see a failed test in HTML$/) do
6
+ html_report_body.get_elements("//*[contains(@class, 'test failing')]/").to_a.size.should_not == 0
7
+ end
8
+
9
+ Then(/^the failure counter should show (\d+) tests?$/) do |fail_count|
10
+ html_report_body.get_elements("//*[@id='fail-count']/").first.elements.to_a.first.text.to_i.should == fail_count.to_i
11
+ end
12
+
13
+ Then(/^I should see a passing test in HTML$/) do
14
+ html_report_body.get_elements("//*[contains(@class, 'test passing')]/").to_a.size.should_not == 0
15
+ end
16
+
17
+ Then(/^I should see (\d+) tests in HTML$/) do |test_count|
18
+ html_report_body.get_elements("//*[contains(@class, 'test ')]/").size.should == test_count.to_i
19
+ end
20
+
21
+ Then(/^I should see (\d+) test suite sections? in HTML$/) do |section_count|
22
+ html_test_suites.size.should == section_count.to_i
23
+ end
@@ -0,0 +1,37 @@
1
+ Given(/^some big input$/) do
2
+ add_run_input File.open('features/fixtures/xcodebuild.log', 'r').read
3
+ end
4
+
5
+ Then(/^I should have a JSON compilation database in a custom path$/) do
6
+ step("I should have a JSON compilation database at \"#{custom_report_path}\"")
7
+ end
8
+
9
+ Then(/^I should have a JSON compilation database at "(.*?)"$/) do |path|
10
+ json = JSON.parse(File.open(path, 'r').read)
11
+ json.should_not be_nil
12
+ end
13
+
14
+ Then(/^I should have JSON compilation databases in two custom paths$/) do
15
+ step("I should have a JSON compilation database at \"#{custom_report_path}\"")
16
+ step("I should have a JSON compilation database at \"#{other_custom_report_path}\"")
17
+ end
18
+
19
+ Then(/^the JSON compilation database should contain an entry with a command$/) do
20
+ json_db.length.should == 1
21
+
22
+ json_db[0]["command"].should start_with("/Applications/Xcode.app/Contents/Developer")
23
+ json_db[0]["command"].should end_with(".o")
24
+ end
25
+
26
+ Then(/^the JSON compilation database should contain an entry with a file$/) do
27
+ json_db[0]["file"].should == "NSMutableArray+ObjectiveSugar.m"
28
+ end
29
+
30
+ Then(/^the JSON compilation database should contain an entry with a directory$/) do
31
+ json_db[0]["directory"].should == "/Users/musalj/code/OSS/ObjectiveSugar/Classes"
32
+ end
33
+
34
+ Then(/^the JSON compilation database should be complete$/) do
35
+ entries = json_db.select {|entry| entry['command'] && entry['file'] && entry['directory']}
36
+ entries.length.should == JSON_DB_FIXTURE_COMMAND_COUNT
37
+ end
@@ -0,0 +1,38 @@
1
+ Then(/^I should see a failed test node in my report$/) do
2
+ junit_report_root.elements.to_a.detect do |node|
3
+ element = node.elements.to_a.first
4
+ element && element.name == "failure"
5
+ end.should_not be_nil
6
+ end
7
+
8
+ Then(/^I should see a passing test node in my report$/) do
9
+ junit_report_root.elements.to_a.detect do |node|
10
+ node.attributes["time"] != nil
11
+ end.should_not be_nil
12
+ end
13
+
14
+ Then(/^I should see a pending test node in my report$/) do
15
+ junit_report_root.elements.to_a.detect do |node|
16
+ node.elements.to_a.detect {|child| child.name == 'skipped'}
17
+ end.should_not be_nil
18
+ end
19
+
20
+ Then(/^I should see a test suite node$/) do
21
+ junit_report_root.elements.to_a.first.should_not be_nil
22
+ end
23
+
24
+ Then(/^I should see (\d+) tests in my report$/) do |test_count|
25
+ junit_report_root.attributes["tests"].should == test_count
26
+ junit_report_root.elements.to_a.count.should == test_count.to_i
27
+ end
28
+
29
+ Then(/^I should see (\d+) test suites$/) do |count|
30
+ suites = junit_report.root.elements.to_a
31
+ suites.size.should == count.to_i
32
+ suites.select {|s| s.name == 'testsuite' }.size.should == count.to_i
33
+ end
34
+
35
+ Then(/^I should have a test report at "(.*?)"$/) do |path|
36
+ doc = REXML::Document.new(File.open(path, 'r').read)
37
+ doc.root.should_not be_nil
38
+ end
@@ -0,0 +1,21 @@
1
+ Given(/^I have tests in my suite from 2 classes$/) do
2
+ add_run_input SAMPLE_OCUNIT_TEST
3
+ add_run_input SAMPLE_KIWI_TEST
4
+ end
5
+
6
+ When(/^I pipe to xcpretty with "(.*?)" and specify a custom path$/) do |args|
7
+ step("I pipe to xcpretty with \"#{args} --output #{custom_report_path}\"")
8
+ end
9
+
10
+ When(/^I pipe to xcpretty with two custom "(.*?)" report paths$/) do |type|
11
+ step("I pipe to xcpretty with \"--report #{type} --output #{custom_report_path} --report #{type} --output #{other_custom_report_path}\"")
12
+ end
13
+
14
+ Then(/^I should have test reports in two custom paths$/) do
15
+ step("I should have a test report at \"#{custom_report_path}\"")
16
+ step("I should have a test report at \"#{other_custom_report_path}\"")
17
+ end
18
+
19
+ Then(/^I should have a test report in a custom path$/) do
20
+ step("I should have a test report at \"#{custom_report_path}\"")
21
+ end
@@ -0,0 +1,31 @@
1
+ When(/^I run xcpretty$/) do
2
+ @output = `bin/xcpretty 2>&1`
3
+ end
4
+
5
+ When(/^I run xcpretty with (.*)$/) do |flags|
6
+ @output = `bin/xcpretty #{flags}`
7
+ end
8
+
9
+ When(/^I run xcpretty over a big file$/) do
10
+ start_time = Time.now
11
+ @output = `cat features/fixtures/xcodebuild.log | bin/xcpretty -c`
12
+ @xcpretty_run_time = Time.now - start_time
13
+ end
14
+
15
+ Then(/^I should see the help banner$/) do
16
+ run_output.should include("Usage: xcodebuild [options] | xcpretty")
17
+ end
18
+
19
+ Then(/^I should see the xcpretty version$/) do
20
+ run_output.should include(XCPretty::VERSION)
21
+ end
22
+
23
+ Then(/^the exit status code should be (\d)$/) do |numbah|
24
+ $?.exitstatus.should == numbah.to_i
25
+ end
26
+
27
+ Then(/^the performance should be way faster than running cat$/) do
28
+ puts "XCPretty run time: #{@xcpretty_run_time}"
29
+ @xcpretty_run_time.should < 2
30
+ end
31
+
@@ -0,0 +1,108 @@
1
+ $:.unshift File.expand_path('../../..', __FILE__)
2
+
3
+ require 'tempfile'
4
+ require 'spec/fixtures/constants'
5
+ require 'spec/support/matchers/colors'
6
+ require 'lib/xcpretty/ansi'
7
+ require 'lib/xcpretty/version'
8
+ require 'lib/xcpretty/syntax'
9
+ require 'rexml/document'
10
+ require 'lib/xcpretty/formatters/formatter'
11
+ require 'lib/xcpretty/reporters/junit'
12
+ require 'lib/xcpretty/reporters/html'
13
+ require 'lib/xcpretty/reporters/json_compilation_database'
14
+ begin
15
+ require 'json'
16
+ rescue LoadError
17
+ require 'vendor/json_pure/parser'
18
+ end
19
+
20
+ include XCPretty::ANSI
21
+
22
+ TEST_RUN_START_MATCHER = /Test Suite .+ started/
23
+ TEST_SUITE_COMPLETION_MATCHER = /Executed \d+ tests, with \d+ failures \(\d+ unexpected\) in \d+\.\d+ \(\d+\.\d+\) seconds/
24
+ TEST_SUITE_START_MATCHER = /[\w]*(Spec|Tests)$/
25
+ TEST_PATH_MATCHER = %r{[\w/\-\s]+:\d+}
26
+ PASSING_TEST_NAME_MATCHER = %r{\w+\s\(\d+\.\d+\sseconds\)}
27
+ PENDING_TEST_NAME_MATCHER = %r{\w+\s\[PENDING\]}
28
+ FAILING_TEST_NAME_MATCHER = %r{\w+, expected:}
29
+
30
+ JSON_DB_FIXTURE_COMMAND_COUNT = 557
31
+
32
+ def run_xcpretty(flags)
33
+ input_file = Tempfile.new('xcpretty_input')
34
+ File.open(input_file.path, 'w') do |file|
35
+ file.print run_input
36
+ end
37
+ @output = %x(cat '#{input_file.path}' | bin/xcpretty #{flags})
38
+ input_file.unlink
39
+ end
40
+
41
+ def add_run_input(text)
42
+ run_input << "\n#{text}"
43
+ end
44
+
45
+ def run_input
46
+ @input ||= ''
47
+ end
48
+
49
+ def run_output
50
+ @output ||= ''
51
+ end
52
+
53
+ def html_report
54
+ @html_report ||= REXML::Document.new(File.open(XCPretty::HTML::FILEPATH, 'r').read.sub("<!DOCTYPE html>",""))
55
+ end
56
+
57
+ def html_report_body
58
+ html_report.root.get_elements('//body').first
59
+ end
60
+
61
+ def html_test_suites
62
+ parent = html_report_body.get_elements("//*[@id='test-suites']/").first
63
+ parent.elements.to_a.select do |e|
64
+ e.attributes['class'] && e.attributes['class'].include?('test-suite')
65
+ end
66
+ end
67
+
68
+ def json_db
69
+ @json ||= JSON.parse(File.open(custom_report_path, 'r').read)
70
+ end
71
+
72
+ def junit_report
73
+ REXML::Document.new(File.open(XCPretty::JUnit::FILEPATH, 'r').read)
74
+ end
75
+
76
+ def junit_report_root
77
+ junit_report.root.elements.to_a.first
78
+ end
79
+
80
+ def custom_report_path
81
+ @custom_report_path ||= begin
82
+ @custom_report_file1 = Tempfile.new('custom_report_path')
83
+ @custom_report_file1.path
84
+ end
85
+ end
86
+
87
+ def other_custom_report_path
88
+ @custom_report_path2 ||= begin
89
+ @custom_report_file2 = Tempfile.new('custom_report_path')
90
+ @custom_report_file2.path
91
+ end
92
+ end
93
+
94
+ Before do
95
+ self.colorize = true
96
+ end
97
+
98
+ After do
99
+ @input = ""
100
+ @output = ""
101
+ @custom_report_file1.unlink if @custom_report_file1
102
+ @custom_report_file2.unlink if @custom_report_file2
103
+ @html_report = nil
104
+ @json = nil
105
+ FileUtils.rm_rf(XCPretty::JUnit::FILEPATH)
106
+ FileUtils.rm_rf(XCPretty::HTML::FILEPATH)
107
+ FileUtils.rm_rf(XCPretty::JSONCompilationDatabase::FILEPATH)
108
+ end
@@ -0,0 +1,31 @@
1
+ Feature: Showing Test Anything Protocol-compatible test output
2
+
3
+ Scenario: Showing failed tests
4
+ Given I have a failing test in my suite
5
+ When I pipe to xcpretty with "--tap"
6
+ Then I should see text beginning with "not ok 1"
7
+
8
+ Scenario: Showing passing tests
9
+ Given I have a passing test in my suite
10
+ When I pipe to xcpretty with "--tap"
11
+ Then I should see text beginning with "ok 1"
12
+
13
+ Scenario: Showing pending tests
14
+ Given I have a pending test in my suite
15
+ When I pipe to xcpretty with "--tap"
16
+ Then I should see text containing " # TODO" and beginning with "not ok 1"
17
+
18
+ Scenario: Showing how many tests completed
19
+ Given I have a pending test in my suite
20
+ And I have a passing test in my suite
21
+ And I have a failing test in my suite
22
+ And the test suite has finished
23
+ When I pipe to xcpretty with "--tap"
24
+ Then I should see text matching "1..3"
25
+
26
+ Scenario: Showing a running test counter
27
+ Given I have a passing test in my suite
28
+ And I have a failing test in my suite
29
+ When I pipe to xcpretty with "--tap"
30
+ Then I should see text beginning with "ok 1"
31
+ And I should see text beginning with "not ok 2"
@@ -0,0 +1,39 @@
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 pipe to xcpretty with "--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 pipe to xcpretty with "--test"
11
+ Then I should see a passing test icon in ASCII
12
+
13
+ Scenario: Showing pending tests
14
+ Given I have a pending test in my suite
15
+ When I pipe to xcpretty with "--test"
16
+ Then I should see a pending test icon in ASCII
17
+
18
+ Scenario: Showing some tests failed with color
19
+ Given I have a failing test in my suite
20
+ And the test suite has finished
21
+ When I pipe to xcpretty with "--test --color"
22
+ Then I should see a red failed test icon
23
+ And I should see the path of a failed test
24
+ And the final execution message should be red
25
+
26
+ Scenario: Showing passing tests with color
27
+ Given I have a passing test in my suite
28
+ When I pipe to xcpretty with "--test --color"
29
+ Then I should see a green passing test icon
30
+
31
+ Scenario: Showing pending tests with color
32
+ Given I have a pending test in my suite
33
+ When I pipe to xcpretty with "--test --color"
34
+ Then I should see a yellow pending test icon
35
+
36
+ Scenario: Showing that all tests passed with color
37
+ Given all of my tests will pass in my suite
38
+ When I pipe to xcpretty with "--test --color"
39
+ Then the final execution message should be green
@@ -0,0 +1,14 @@
1
+ Feature: CLI behavior
2
+
3
+ Scenario: Starting xcpretty without any flags
4
+ When I run xcpretty
5
+ Then I should see the help banner
6
+
7
+ Scenario: Starting xcpretty with version
8
+ When I run xcpretty with -v
9
+ Then I should see the xcpretty version
10
+
11
+ Scenario: Performance
12
+ When I run xcpretty over a big file
13
+ Then the performance should be way faster than running cat
14
+
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'xcpretty/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "learn-xcpretty"
8
+ spec.version = XCPretty::VERSION
9
+ spec.authors = ["Marin Usalj", "Delisa Mason"]
10
+ spec.email = ["mneorr@gmail.com", "iskanamagus@gmail.com"]
11
+ spec.required_ruby_version = '>= 1.8.7'
12
+ spec.description =
13
+ %q{
14
+ Xcodebuild formatter designed to be piped with `xcodebuild`,
15
+ and thus keeping 100% compatibility.
16
+
17
+ It has modes for CI, running tests (RSpec dot-style),
18
+ and it can also mine Bitcoins.
19
+ }
20
+ spec.summary = %q{xcodebuild formatter done right}
21
+ spec.homepage = "https://github.com/mneorr/xcpretty"
22
+ spec.license = "MIT"
23
+
24
+ spec.files = `git ls-files`.split($/)
25
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
26
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.3"
30
+ spec.add_development_dependency "rake"
31
+ spec.add_development_dependency "rspec", "~> 2"
32
+ spec.add_development_dependency "cucumber"
33
+ spec.add_dependency "oj", "~> 2.12"
34
+ spec.add_dependency "git", "~> 1.2"
35
+ spec.add_dependency "netrc", "~> 0.10"
36
+ spec.add_dependency "faraday", "~> 0.9"
37
+ end
@@ -0,0 +1,71 @@
1
+ module XCPretty
2
+ module ANSI
3
+
4
+ attr_accessor :colorize
5
+
6
+ FORMATTED_MATCHER = %r{\e\[(\d+)[;]?(\d+)?m(.*)\e\[0m}
7
+
8
+ EFFECT = {
9
+ :reset => '0',
10
+ :bold => '1',
11
+ :underline => '4'
12
+ }
13
+
14
+ COLORS = {
15
+ :black => '30',
16
+ :red => '31',
17
+ :green => '32',
18
+ :yellow => '33',
19
+ :blue => '34',
20
+ :cyan => '36',
21
+ :white => '37',
22
+ :plain => '39'
23
+ }
24
+
25
+ def colorize?
26
+ !!@colorize
27
+ end
28
+
29
+ def white(text)
30
+ ansi_parse(text, :plain, :bold)
31
+ end
32
+
33
+ def red(text)
34
+ ansi_parse(text, :red)
35
+ end
36
+
37
+ def green(text)
38
+ ansi_parse(text, :green, :bold)
39
+ end
40
+
41
+ def cyan(text)
42
+ ansi_parse(text, :cyan)
43
+ end
44
+
45
+ def yellow(text)
46
+ ansi_parse(text, :yellow)
47
+ end
48
+
49
+ def applied_effects(text)
50
+ effects = []
51
+ if text =~ FORMATTED_MATCHER
52
+ colors = COLORS.invert[$1]
53
+ effect = EFFECT.invert[$2]
54
+ effects << colors if colors
55
+ effects << effect if effect
56
+ end
57
+ effects
58
+ end
59
+
60
+ def strip(text)
61
+ text =~ FORMATTED_MATCHER ? $3 : text
62
+ end
63
+
64
+ def ansi_parse(text, color, effect=nil)
65
+ return text unless colorize?
66
+ colors_code = COLORS[color] || ''
67
+ effect_code = EFFECT[effect] ? ';' + EFFECT[effect] : ''
68
+ "\e[#{colors_code}#{effect_code}m#{text}\e[#{EFFECT[:reset]}m"
69
+ end
70
+ end
71
+ end