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,20 @@
1
+ require "xcpretty/ansi"
2
+
3
+ module XCPretty
4
+
5
+ class Printer
6
+
7
+ attr_reader :formatter
8
+
9
+ def initialize(params)
10
+ klass = params[:formatter]
11
+ @formatter = klass.new(params[:unicode], params[:colorize])
12
+ end
13
+
14
+ def pretty_print(text)
15
+ formatted_text = formatter.pretty_format(text)
16
+ STDOUT.print(formatted_text + formatter.optional_newline) unless formatted_text.empty?
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,73 @@
1
+ module XCPretty
2
+ class HTML
3
+
4
+ include XCPretty::FormatMethods
5
+ FILEPATH = 'build/reports/tests.html'
6
+ TEMPLATE = File.expand_path('../../../../assets/report.html.erb', __FILE__)
7
+
8
+ def load_dependencies
9
+ unless @@loaded ||= false
10
+ require 'fileutils'
11
+ require 'pathname'
12
+ require 'erb'
13
+ @@loaded = true
14
+ end
15
+ end
16
+
17
+ def initialize(options)
18
+ load_dependencies
19
+ @test_suites = {}
20
+ @filepath = options[:path] || FILEPATH
21
+ @parser = Parser.new(self)
22
+ @test_count = 0
23
+ @fail_count = 0
24
+ end
25
+
26
+ def handle(line)
27
+ @parser.parse(line)
28
+ end
29
+
30
+ def format_failing_test(suite, test_case, reason, file)
31
+ add_test(suite, {:name => test_case, :failing => true,
32
+ :reason => reason, :file => file, :snippet => formatted_snippet(file)})
33
+ end
34
+
35
+ def format_passing_test(suite, test_case, time)
36
+ add_test(suite, {:name => test_case, :time => time})
37
+ end
38
+
39
+ def finish
40
+ FileUtils.mkdir_p(File.dirname(@filepath))
41
+ write_report
42
+ end
43
+
44
+ private
45
+
46
+ def formatted_snippet(filepath)
47
+ snippet = Snippet.from_filepath(filepath)
48
+ Syntax.highlight(snippet, "-f html -O style=colorful -O noclasses")
49
+ end
50
+
51
+
52
+ def add_test(suite_name, data)
53
+ @test_count += 1
54
+ @test_suites[suite_name] ||= {:tests => []}
55
+ @test_suites[suite_name][:tests] << data
56
+ if data[:failing]
57
+ @test_suites[suite_name][:failing] = true
58
+ @fail_count += 1
59
+ end
60
+ end
61
+
62
+ def write_report
63
+ File.open(@filepath, 'w') do |f|
64
+ # WAT: get rid of these locals. BTW Cucumber fails if you remove them
65
+ test_suites = @test_suites
66
+ fail_count = @fail_count
67
+ test_count = @test_count
68
+ erb = ERB.new(File.open(TEMPLATE, 'r').read)
69
+ f.write erb.result(binding)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,58 @@
1
+ module XCPretty
2
+ class JSONCompilationDatabase
3
+
4
+ include XCPretty::FormatMethods
5
+ FILEPATH = 'build/reports/compilation_db.json'
6
+
7
+ def load_dependencies
8
+ unless @@loaded ||= false
9
+ require 'fileutils'
10
+ require 'pathname'
11
+ unless Object.const_defined?(:JSON)
12
+ begin
13
+ require 'json'
14
+ rescue LoadError
15
+ require File.expand_path(File.join(File.dirname(__FILE__),'../../../vendor/json_pure/generator'))
16
+ end
17
+ end
18
+ @@loaded = true
19
+ end
20
+ end
21
+
22
+ def initialize(options)
23
+ load_dependencies
24
+ @filepath = options[:path] || FILEPATH
25
+ @parser = Parser.new(self)
26
+ @compilation_units = []
27
+ @current_file = nil
28
+ @current_path = nil
29
+ end
30
+
31
+ def handle(line)
32
+ @parser.parse(line)
33
+ end
34
+
35
+ def format_compile(file_name, file_path)
36
+ @current_file = file_name
37
+ @current_path = File.dirname(file_path)
38
+ end
39
+
40
+ def format_compile_command(compiler_command)
41
+ @compilation_units << { :command => compiler_command,
42
+ :file => @current_file, :directory => @current_path }
43
+ end
44
+
45
+ def finish
46
+ FileUtils.mkdir_p(File.dirname(@filepath))
47
+ write_report
48
+ end
49
+
50
+ private
51
+
52
+ def write_report
53
+ File.open(@filepath, 'w') do |f|
54
+ f.write(@compilation_units.to_json)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,99 @@
1
+ module XCPretty
2
+ class JUnit
3
+
4
+ include XCPretty::FormatMethods
5
+ FILEPATH = 'build/reports/junit.xml'
6
+
7
+ def load_dependencies
8
+ unless @@loaded ||= false
9
+ require 'fileutils'
10
+ require 'pathname'
11
+ require 'rexml/document'
12
+ require 'rexml/formatters/pretty'
13
+ @@loaded = true
14
+ end
15
+ end
16
+
17
+ def initialize(options)
18
+ load_dependencies
19
+ @filepath = options[:path] || FILEPATH
20
+ @directory = `pwd`.strip
21
+ @document = REXML::Document.new
22
+ @document << REXML::XMLDecl.new('1.0','UTF-8')
23
+ @document.add_element('testsuites')
24
+ @parser = Parser.new(self)
25
+ @total_tests = 0
26
+ @total_fails = 0
27
+ end
28
+
29
+ def handle(line)
30
+ @parser.parse(line)
31
+ end
32
+
33
+ def format_passing_test(classname, test_case, time)
34
+ test_node = suite(classname).add_element('testcase')
35
+ test_node.attributes['classname'] = classname
36
+ test_node.attributes['name'] = test_case
37
+ test_node.attributes['time'] = time
38
+ @test_count += 1
39
+ end
40
+
41
+ def format_pending_test(classname, test_case)
42
+ test_node = suite(classname).add_element('testcase')
43
+ test_node.attributes['classname'] = classname
44
+ test_node.attributes['name'] = test_case
45
+ test_node.add_element('skipped')
46
+ @test_count += 1
47
+ end
48
+
49
+ def format_failing_test(classname, test_case, reason, file)
50
+ test_node = suite(classname).add_element('testcase')
51
+ test_node.attributes['classname'] = classname
52
+ test_node.attributes['name'] = test_case
53
+ fail_node = test_node.add_element('failure')
54
+ fail_node.attributes['message'] = reason
55
+ fail_node.text = file.sub(@directory + '/', '')
56
+ @test_count += 1
57
+ @fail_count += 1
58
+ end
59
+
60
+ def finish
61
+ set_test_counters
62
+ @document.root.attributes['tests'] = @total_tests
63
+ @document.root.attributes['failures'] = @total_fails
64
+ write_report_file
65
+ end
66
+
67
+ private
68
+
69
+ def write_report_file
70
+ FileUtils.mkdir_p(File.dirname(@filepath))
71
+ formatter = REXML::Formatters::Pretty.new(2)
72
+ formatter.compact = true
73
+ output_file = File.open(@filepath, 'w+')
74
+ result = formatter.write(@document, output_file)
75
+ output_file.close
76
+ result
77
+ end
78
+
79
+ def suite(classname)
80
+ return @last_suite if @last_suite && @last_suite.attributes['name'] == classname
81
+
82
+ set_test_counters
83
+ @last_suite = @document.root.add_element('testsuite')
84
+ @last_suite.attributes['name'] = classname
85
+ @last_suite
86
+ end
87
+
88
+ def set_test_counters
89
+ if @last_suite
90
+ @last_suite.attributes['tests'] = @test_count
91
+ @last_suite.attributes['failures'] = @fail_count
92
+ end
93
+ @total_fails += @fail_count || 0
94
+ @total_tests += @test_count || 0
95
+ @test_count = 0
96
+ @fail_count = 0
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,154 @@
1
+ module XCPretty
2
+ class Learn
3
+ SERVICE_URL = 'http://ironbroker.flatironschool.com'
4
+ SERVICE_ENDPOINT = '/e/flatiron_xcpretty/build'
5
+
6
+ include XCPretty::FormatMethods
7
+
8
+ def load_dependencies
9
+ unless @@loaded ||= false
10
+ require 'fileutils'
11
+ require 'pathname'
12
+ require 'json'
13
+ require 'faraday'
14
+ require 'netrc'
15
+ require 'git'
16
+ require 'oj'
17
+ @@loaded = true
18
+ end
19
+ end
20
+
21
+ def initialize(options)
22
+ load_dependencies
23
+ @formatted_output = {
24
+ username: UsernameParser.get_username,
25
+ github_user_id: UserIdParser.get_user_id,
26
+ repo_name: RepoParser.get_repo,
27
+ build: {
28
+ test_suite: [{
29
+ framework: 'xcpretty',
30
+ formatted_output: [],
31
+ duration: 0.0,
32
+ build_output: [],
33
+ }]
34
+ },
35
+ total_count: 0,
36
+ passing_count: 0,
37
+ failure_count: 0
38
+ }
39
+
40
+ @parser = Parser.new(self)
41
+
42
+ @connection = Faraday.new(url: SERVICE_URL) do |faraday|
43
+ faraday.adapter Faraday.default_adapter
44
+ end
45
+ end
46
+
47
+ def handle(line)
48
+ @parser.parse(line)
49
+ end
50
+
51
+ def format_passing_test(classname, test_case, time)
52
+ pass = {classname: classname, name: test_case, time: time}
53
+ @formatted_output[:build][:test_suite][0][:formatted_output] << pass
54
+ @formatted_output[:total_count] += 1
55
+ @formatted_output[:passing_count] += 1
56
+ end
57
+
58
+ def format_failing_test(classname, test_case, reason, file)
59
+ failure = {classname: classname, name: test_case, file: file, reason: reason}
60
+ @formatted_output[:build][:test_suite][0][:formatted_output] << failure
61
+ @formatted_output[:total_count] += 1
62
+ @formatted_output[:failure_count] += 1
63
+ end
64
+
65
+ def finish
66
+ write_report_file
67
+ end
68
+
69
+ private
70
+
71
+ def write_report_file
72
+ @connection.post do |req|
73
+ req.url SERVICE_ENDPOINT
74
+ req.headers['Content-Type'] = 'application/json'
75
+ req.body = @formatted_output.to_json
76
+ end
77
+ end
78
+ end
79
+
80
+ class UsernameParser
81
+ def self.get_username
82
+ parser = NetrcInteractor.new
83
+ username = parser.username
84
+
85
+ if !username
86
+ print "Enter your github username: "
87
+ username = gets.strip
88
+ user_id = GitHubInteractor.get_user_id_for(username)
89
+ parser.write(username, user_id)
90
+ end
91
+
92
+ username
93
+ end
94
+ end
95
+
96
+ class UserIdParser
97
+ def self.get_user_id
98
+ parser = NetrcInteractor.new
99
+ user_id = parser.user_id
100
+ end
101
+ end
102
+
103
+ class GitHubInteractor
104
+ attr_reader :username, :user_id
105
+
106
+ def self.get_user_id_for(username)
107
+ new(username).get_user_id
108
+ end
109
+
110
+ def initialize(username)
111
+ @username = username
112
+ end
113
+
114
+ def get_user_id
115
+ @user_id ||= Oj.load(
116
+ open("https://api.github.com/users/#{username}").read,
117
+ symbol_keys: true
118
+ )[:id]
119
+ end
120
+ end
121
+
122
+ class NetrcInteractor
123
+ attr_reader :username, :user_id, :netrc
124
+
125
+ def initialize
126
+ @netrc = Netrc.read
127
+ @username, @user_id = netrc["flatiron-push"]
128
+ end
129
+
130
+ def write(username, user_id)
131
+ netrc["flatiron-push"] = username, user_id
132
+ netrc.save
133
+ end
134
+ end
135
+
136
+ class RepoParser
137
+ def self.get_repo
138
+ begin
139
+ repo = Git.open(File.expand_path(".", Dir.pwd))
140
+ rescue
141
+ puts "Not a valid Git repository"
142
+ die
143
+ end
144
+
145
+ url = repo.remote.url
146
+
147
+ repo_name = url.match(/(?:https:\/\/|git@).*\/(.+)(?:\.git)/)[1]
148
+ end
149
+
150
+ def self.die
151
+ exit
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,34 @@
1
+ module XCPretty
2
+ class Snippet
3
+
4
+ def self.from_filepath(filepath)
5
+ path, line = filepath.split(':')
6
+ file = File.open(path)
7
+
8
+ text = read_snippet(file, line)
9
+
10
+ file.close
11
+ text
12
+ rescue
13
+ ''
14
+ end
15
+
16
+
17
+ private
18
+
19
+ def self.read_snippet(file, around_line)
20
+ text = ""
21
+ starting_position = around_line.to_i - 2
22
+ starting_position.times { file.gets }
23
+ 3.times { text += readline(file) }
24
+ text
25
+ end
26
+
27
+ def self.readline(file)
28
+ file.gets
29
+ $_ || ''
30
+ end
31
+
32
+ end
33
+ end
34
+
@@ -0,0 +1,20 @@
1
+ module XCPretty
2
+ class Syntax
3
+
4
+ def self.highlight(code, options="")
5
+ pygments_available? ? pygmentize(code, options) : code
6
+ end
7
+
8
+
9
+ private
10
+
11
+ def self.pygments_available?
12
+ @available = system('which pygmentize > /dev/null') if @available.nil?
13
+ @available
14
+ end
15
+
16
+ def self.pygmentize(code, options)
17
+ `echo "#{code}" | pygmentize -l objc #{options}`
18
+ end
19
+ end
20
+ end