learn-xcpretty 0.1.11

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.
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