what_weve_got_here_is_an_error_to_communicate 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +4 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +2 -0
  6. data/Rakefile +6 -0
  7. data/Readme.md +34 -0
  8. data/acceptance +29 -0
  9. data/experiments/formatting/5_potential_structure_dsls.rb +88 -0
  10. data/experiments/formatting/half_thoughtout_dsl_for_toplevel_structure_of_argument_error.rb +43 -0
  11. data/experiments/formatting/haml_like_structure.rb +139 -0
  12. data/experiments/formatting/other_structures +156 -0
  13. data/lib/error_to_communicate.rb +3 -0
  14. data/lib/error_to_communicate/at_exit.rb +11 -0
  15. data/lib/error_to_communicate/config.rb +32 -0
  16. data/lib/error_to_communicate/exception_info.rb +41 -0
  17. data/lib/error_to_communicate/format.rb +132 -0
  18. data/lib/error_to_communicate/format/terminal_helpers.rb +97 -0
  19. data/lib/error_to_communicate/parse/backtrace.rb +34 -0
  20. data/lib/error_to_communicate/parse/exception.rb +21 -0
  21. data/lib/error_to_communicate/parse/no_method_error.rb +27 -0
  22. data/lib/error_to_communicate/parse/registry.rb +30 -0
  23. data/lib/error_to_communicate/parse/wrong_number_of_arguments.rb +35 -0
  24. data/lib/error_to_communicate/rspec_formatter.rb +46 -0
  25. data/lib/error_to_communicate/version.rb +3 -0
  26. data/lib/what_weve_got_here_is_an_error_to_communicate.rb +3 -0
  27. data/screenshot.png +0 -0
  28. data/spec/acceptance/argument_error_spec.rb +55 -0
  29. data/spec/acceptance/exception_spec.rb +29 -0
  30. data/spec/acceptance/no_error_spec.rb +44 -0
  31. data/spec/acceptance/no_methood_error_spec.rb +50 -0
  32. data/spec/acceptance/spec_helper.rb +41 -0
  33. data/spec/parse/backtrace_spec.rb +101 -0
  34. data/spec/parse/exception_spec.rb +14 -0
  35. data/spec/parse/no_method_error_spec.rb +23 -0
  36. data/spec/parse/registered_parsers_spec.rb +68 -0
  37. data/spec/parse/spec_helper.rb +23 -0
  38. data/spec/parse/wrong_number_of_arguments_spec.rb +77 -0
  39. data/spec/rspec_formatter_spec.rb +95 -0
  40. data/spec/spec_helper.rb +20 -0
  41. data/what_weve_got_here_is_an_error_to_communicate.gemspec +19 -0
  42. metadata +168 -0
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.shared_examples 'an exception parser' do |attributes|
4
+ let(:message) { attributes.fetch :sample_message }
5
+ let(:explanation) { attributes.fetch :sample_explanation, message }
6
+
7
+ let :exception do
8
+ FakeException.new message: message,
9
+ backtrace: ["/Users/someone/a/b/c.rb:123:in `some_method_name'"]
10
+ end
11
+
12
+ it 'records the exception, class name, and explanation comes from the message' do
13
+ info = parse exception
14
+ expect(info.exception ).to equal exception
15
+ expect(info.classname ).to eq 'FakeException'
16
+ expect(info.explanation).to eq explanation
17
+ end
18
+
19
+ it 'records the backtrace locations' do
20
+ info = parse exception
21
+ expect(info.backtrace.map &:linenum).to eq [123]
22
+ end
23
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+ require 'parse/spec_helper'
3
+ require 'error_to_communicate/parse/wrong_number_of_arguments'
4
+
5
+ RSpec.describe 'parsing wrong number of arguments', parse: true do
6
+ def parse(exception)
7
+ WhatWeveGotHereIsAnErrorToCommunicate::Parse::WrongNumberOfArguments.parse(exception)
8
+ end
9
+
10
+ it_behaves_like 'an exception parser',
11
+ sample_message: "wrong number of arguments (1 for 0) (ArgumentError)",
12
+ sample_explanation: "Wrong number of arguments"
13
+
14
+ describe 'parse?' do
15
+ def will_parse?(exception)
16
+ WhatWeveGotHereIsAnErrorToCommunicate::Parse::WrongNumberOfArguments.parse?(exception)
17
+ end
18
+
19
+ def will_parse!(exception)
20
+ expect(will_parse? exception).to be_truthy
21
+ end
22
+
23
+ def wont_parse!(exception)
24
+ expect(will_parse? exception).to be_falsy
25
+ end
26
+
27
+ it 'is true when given an MRI style wrong number of arguments message' do
28
+ will_parse! ArgumentError.new "wrong number of arguments (1 for 0)"
29
+ end
30
+
31
+ it 'is true when given an RBX style wrong number of arguments message' do
32
+ will_parse! ArgumentError.new "method 'a': given 1, expected 0"
33
+ end
34
+
35
+ it 'is true when given an JRuby style wrong number of arguments message' do
36
+ will_parse! ArgumentError.new "wrong number of arguments calling `a` (1 for 0)"
37
+ end
38
+
39
+ it 'is true when given an MRI style wrong number of arguments message' do
40
+ will_parse! ArgumentError.new "wrong number of arguments (1 for 0)"
41
+ end
42
+
43
+ it 'is false for ArgumentErrors that are not "wrong number of arguments"' do
44
+ wont_parse! ArgumentError.new "Some other kind of ArgumentError"
45
+ end
46
+
47
+ it 'is false when the message is contained within some other message (not overeager)' do
48
+ wont_parse! RSpec::Expectations::ExpectationNotMetError.new(<<-MESSAGE)
49
+ expected: "wrong number of arguments (1 for 0) (ArgumentError)"
50
+ got: "Wrong number of arguments"
51
+
52
+ (compared using ==)
53
+ MESSAGE
54
+ end
55
+ end
56
+
57
+ describe 'parse' do
58
+ let(:mri_message) { "wrong number of arguments (1 for 0)" }
59
+ let(:mri_parsed) { parse FakeException.new(message: mri_message) }
60
+
61
+ let(:rbx_message) { "method 'a': given 1, expected 0" }
62
+ let(:rbx_parsed) { parse FakeException.new(message: rbx_message) }
63
+
64
+ let(:jruby_message) { "wrong number of arguments calling `a` (1 for 0)" }
65
+ let(:jruby_parsed) { parse FakeException.new(message: "wrong number of arguments calling `a` (1 for 0)") }
66
+
67
+ it 'extracts the number of arguments that were passed' do
68
+ expect(rbx_parsed.num_expected).to eq 0
69
+ expect(mri_parsed.num_expected).to eq 0
70
+ end
71
+
72
+ it 'extracts the number of arguments that were received' do
73
+ expect(rbx_parsed.num_received).to eq 1
74
+ expect(mri_parsed.num_received).to eq 1
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,95 @@
1
+ require 'stringio'
2
+ require 'spec_helper'
3
+
4
+ RSpec.describe ErrorToCommunicate::RSpecFormatter, formatter: true do
5
+ let(:substring_that_would_only_be_in_full_backtrace) { 'lib/rspec/core' }
6
+
7
+ def formatter_for(attributes)
8
+ outstream = attributes.fetch(:outstream) { StringIO.new }
9
+ described_class.new(outstream)
10
+ end
11
+
12
+ def new_formatter
13
+ formatter_for({})
14
+ end
15
+
16
+ # The interfaces mocked out here were taken from RSpec 3.2.2
17
+ # They're all private, but IDK how else to test it :/
18
+ def run_specs_against(formatter, *describe_args, &describe_block)
19
+ # Create the example group
20
+ # define some methods to decouple it from the global test suite
21
+ group = RSpec::Core::ExampleGroup.describe(*describe_args, &describe_block)
22
+ class << group
23
+ alias filtered_examples examples
24
+ def fail_fast?() false end
25
+ end
26
+
27
+ # The reporter calls into our formatter
28
+ reporter = RSpec::Core::Reporter.new(RSpec::Core::Configuration.new)
29
+
30
+ # Register the formatter for all notifications it would actually receive
31
+ registered_notifications = formatter.class.ancestors.flat_map do |ancestor|
32
+ RSpec::Core::Formatters::Loader.formatters.fetch(ancestor, [])
33
+ end
34
+ registered_notifications.each do |notification|
35
+ reporter.register_listener formatter, notification
36
+ end
37
+
38
+ # Fake out the runner
39
+ # ordering comes from: http://rspec.info/documentation/3.2/rspec-core/RSpec/Core/Formatters.html
40
+ reporter.start(expected_example_count=123)
41
+ group.run(reporter)
42
+ reporter.finish
43
+ end
44
+
45
+ def this_line_of_code
46
+ file, line = caller[0].split(":").take(2)
47
+ File.read(file).lines[line.to_i].strip
48
+ end
49
+
50
+ def get_printed(formatter)
51
+ # FIXME: hack until we get it respecting colour on/off
52
+ formatter.output.string.gsub(/\e\[\d+(;\d+)*?m/, '')
53
+ end
54
+
55
+ it 'uses our lib to print the details of failing examples.' do
56
+ formatter = new_formatter
57
+ context_around_failure = this_line_of_code
58
+ run_specs_against formatter do
59
+ example('will fail') { fail }
60
+ end
61
+ expect(get_printed formatter).to include context_around_failure
62
+
63
+ formatter = new_formatter
64
+ context_around_success = this_line_of_code
65
+ run_specs_against formatter do
66
+ example('will pass') { }
67
+ end
68
+ expect(get_printed formatter).to_not include context_around_success
69
+ end
70
+
71
+ it 'numbers the failure and prints the failure descriptions' do
72
+ formatter = new_formatter
73
+ run_specs_against formatter, 'GroupName' do
74
+ example('hello') { fail }
75
+ example('world') { fail }
76
+ end
77
+ expect(get_printed formatter).to match /1\)\s*GroupName\s*hello/
78
+ expect(get_printed formatter).to match /2\)\s*GroupName\s*world/
79
+ end
80
+
81
+ it 'respects the backtrace formatter (ie the --backtrace flag)' do
82
+ # only need to check a failing example to show it uses RSpec's backtrace formatter
83
+ formatter = new_formatter
84
+ run_specs_against(formatter) { example { fail } }
85
+ expect(get_printed formatter)
86
+ .to_not include substring_that_would_only_be_in_full_backtrace
87
+ end
88
+
89
+ it 'respects colour enabling/disabling' do
90
+ # https://github.com/rspec/rspec-core/blob/2a07aa92560cf6d4ae73ab04ff3b9b565451e83f/spec/rspec/core/formatters/console_codes_spec.rb#L35
91
+ # allow(RSpec.configuration).to receive(:color_enabled?) { true }
92
+ pending 'We don\'t yet have the ability to turn color printing on/off'
93
+ fail
94
+ end
95
+ end
@@ -0,0 +1,20 @@
1
+ class FakeException
2
+ attr_reader :message, :backtrace
3
+
4
+ def initialize(attributes)
5
+ @message = attributes.fetch :message, 'default message'
6
+ @backtrace = attributes.fetch(:backtrace, [])
7
+ end
8
+
9
+ def exception
10
+ self
11
+ end
12
+ end
13
+
14
+ RSpec.configure do |config|
15
+ # Stop testing after first failure
16
+ config.fail_fast = true
17
+
18
+ # Don't define should/describe on Object
19
+ config.disable_monkey_patching!
20
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'lib/error_to_communicate/version'
2
+ Gem::Specification.new do |s|
3
+ s.name = 'what_weve_got_here_is_an_error_to_communicate'
4
+ s.version = WhatWeveGotHereIsAnErrorToCommunicate::VERSION
5
+ s.licenses = ['MIT']
6
+ s.summary = "Readable, helpful error messages"
7
+ s.description = "Hooks into program lifecycle to display error messages to you in a helpufl way, with inlined code, colour, and helpful heuristics about what might be the cause."
8
+ s.authors = ["Josh Cheek", "Ben Voss"]
9
+ s.email = 'josh.cheek@gmail.com'
10
+ s.files = `git ls-files`.split("\n")
11
+ s.homepage = 'https://github.com/JoshCheek/what-we-ve-got-here-is-an-error-to-communicate'
12
+
13
+ s.add_runtime_dependency 'coderay', '~> 1.1'
14
+
15
+ s.add_development_dependency 'rspec', '~> 3.2'
16
+ s.add_development_dependency 'haiti', '< 0.3', '>= 0.2.0'
17
+ s.add_development_dependency 'pry', '< 0.11', '>= 0.10.0'
18
+ s.add_development_dependency 'rake', '~> 10.4'
19
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: what_weve_got_here_is_an_error_to_communicate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Josh Cheek
8
+ - Ben Voss
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-04-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: coderay
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '3.2'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '3.2'
42
+ - !ruby/object:Gem::Dependency
43
+ name: haiti
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "<"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.3'
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 0.2.0
52
+ type: :development
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - "<"
57
+ - !ruby/object:Gem::Version
58
+ version: '0.3'
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.2.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "<"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.11'
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 0.10.0
72
+ type: :development
73
+ prerelease: false
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - "<"
77
+ - !ruby/object:Gem::Version
78
+ version: '0.11'
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 0.10.0
82
+ - !ruby/object:Gem::Dependency
83
+ name: rake
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '10.4'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '10.4'
96
+ description: Hooks into program lifecycle to display error messages to you in a helpufl
97
+ way, with inlined code, colour, and helpful heuristics about what might be the cause.
98
+ email: josh.cheek@gmail.com
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - ".gitignore"
104
+ - ".rspec"
105
+ - ".travis.yml"
106
+ - Gemfile
107
+ - Rakefile
108
+ - Readme.md
109
+ - acceptance
110
+ - experiments/formatting/5_potential_structure_dsls.rb
111
+ - experiments/formatting/half_thoughtout_dsl_for_toplevel_structure_of_argument_error.rb
112
+ - experiments/formatting/haml_like_structure.rb
113
+ - experiments/formatting/other_structures
114
+ - lib/error_to_communicate.rb
115
+ - lib/error_to_communicate/at_exit.rb
116
+ - lib/error_to_communicate/config.rb
117
+ - lib/error_to_communicate/exception_info.rb
118
+ - lib/error_to_communicate/format.rb
119
+ - lib/error_to_communicate/format/terminal_helpers.rb
120
+ - lib/error_to_communicate/parse/backtrace.rb
121
+ - lib/error_to_communicate/parse/exception.rb
122
+ - lib/error_to_communicate/parse/no_method_error.rb
123
+ - lib/error_to_communicate/parse/registry.rb
124
+ - lib/error_to_communicate/parse/wrong_number_of_arguments.rb
125
+ - lib/error_to_communicate/rspec_formatter.rb
126
+ - lib/error_to_communicate/version.rb
127
+ - lib/what_weve_got_here_is_an_error_to_communicate.rb
128
+ - screenshot.png
129
+ - spec/acceptance/argument_error_spec.rb
130
+ - spec/acceptance/exception_spec.rb
131
+ - spec/acceptance/no_error_spec.rb
132
+ - spec/acceptance/no_methood_error_spec.rb
133
+ - spec/acceptance/spec_helper.rb
134
+ - spec/parse/backtrace_spec.rb
135
+ - spec/parse/exception_spec.rb
136
+ - spec/parse/no_method_error_spec.rb
137
+ - spec/parse/registered_parsers_spec.rb
138
+ - spec/parse/spec_helper.rb
139
+ - spec/parse/wrong_number_of_arguments_spec.rb
140
+ - spec/rspec_formatter_spec.rb
141
+ - spec/spec_helper.rb
142
+ - what_weve_got_here_is_an_error_to_communicate.gemspec
143
+ homepage: https://github.com/JoshCheek/what-we-ve-got-here-is-an-error-to-communicate
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.4.1
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: Readable, helpful error messages
167
+ test_files: []
168
+ has_rdoc: