what_weve_got_here_is_an_error_to_communicate 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +4 -0
- data/.travis.yml +7 -0
- data/Gemfile +2 -0
- data/Rakefile +6 -0
- data/Readme.md +34 -0
- data/acceptance +29 -0
- data/experiments/formatting/5_potential_structure_dsls.rb +88 -0
- data/experiments/formatting/half_thoughtout_dsl_for_toplevel_structure_of_argument_error.rb +43 -0
- data/experiments/formatting/haml_like_structure.rb +139 -0
- data/experiments/formatting/other_structures +156 -0
- data/lib/error_to_communicate.rb +3 -0
- data/lib/error_to_communicate/at_exit.rb +11 -0
- data/lib/error_to_communicate/config.rb +32 -0
- data/lib/error_to_communicate/exception_info.rb +41 -0
- data/lib/error_to_communicate/format.rb +132 -0
- data/lib/error_to_communicate/format/terminal_helpers.rb +97 -0
- data/lib/error_to_communicate/parse/backtrace.rb +34 -0
- data/lib/error_to_communicate/parse/exception.rb +21 -0
- data/lib/error_to_communicate/parse/no_method_error.rb +27 -0
- data/lib/error_to_communicate/parse/registry.rb +30 -0
- data/lib/error_to_communicate/parse/wrong_number_of_arguments.rb +35 -0
- data/lib/error_to_communicate/rspec_formatter.rb +46 -0
- data/lib/error_to_communicate/version.rb +3 -0
- data/lib/what_weve_got_here_is_an_error_to_communicate.rb +3 -0
- data/screenshot.png +0 -0
- data/spec/acceptance/argument_error_spec.rb +55 -0
- data/spec/acceptance/exception_spec.rb +29 -0
- data/spec/acceptance/no_error_spec.rb +44 -0
- data/spec/acceptance/no_methood_error_spec.rb +50 -0
- data/spec/acceptance/spec_helper.rb +41 -0
- data/spec/parse/backtrace_spec.rb +101 -0
- data/spec/parse/exception_spec.rb +14 -0
- data/spec/parse/no_method_error_spec.rb +23 -0
- data/spec/parse/registered_parsers_spec.rb +68 -0
- data/spec/parse/spec_helper.rb +23 -0
- data/spec/parse/wrong_number_of_arguments_spec.rb +77 -0
- data/spec/rspec_formatter_spec.rb +95 -0
- data/spec/spec_helper.rb +20 -0
- data/what_weve_got_here_is_an_error_to_communicate.gemspec +19 -0
- 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
|
data/spec/spec_helper.rb
ADDED
@@ -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:
|