mountain_berry_fields 1.0.0

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 (37) hide show
  1. data/.gitignore +19 -0
  2. data/.simplecov +12 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE +22 -0
  5. data/Rakefile +30 -0
  6. data/Readme.md +184 -0
  7. data/Readme.md.mountain_berry_fields +197 -0
  8. data/bin/mountain_berry_fields +9 -0
  9. data/features/context_block.feature +73 -0
  10. data/features/cwd_is_dir_of_mbf_file.feature +16 -0
  11. data/features/rake_task.feature +46 -0
  12. data/features/setup_block.feature +36 -0
  13. data/features/step_definitions/steps.rb +46 -0
  14. data/features/support/env.rb +76 -0
  15. data/lib/mountain_berry_fields.rb +89 -0
  16. data/lib/mountain_berry_fields/command_line_interaction.rb +13 -0
  17. data/lib/mountain_berry_fields/evaluator.rb +90 -0
  18. data/lib/mountain_berry_fields/parser.rb +101 -0
  19. data/lib/mountain_berry_fields/rake_task.rb +12 -0
  20. data/lib/mountain_berry_fields/test.rb +88 -0
  21. data/lib/mountain_berry_fields/test/always_fail.rb +21 -0
  22. data/lib/mountain_berry_fields/test/always_pass.rb +19 -0
  23. data/lib/mountain_berry_fields/version.rb +3 -0
  24. data/mountain_berry_fields.gemspec +29 -0
  25. data/readme_helper.rb +205 -0
  26. data/spec/command_line_interaction_spec.rb +16 -0
  27. data/spec/evaluator_spec.rb +170 -0
  28. data/spec/mock_substitutability_spec.rb +25 -0
  29. data/spec/mountain_berry_fields_spec.rb +147 -0
  30. data/spec/parser_spec.rb +139 -0
  31. data/spec/ruby_syntax_checker_spec.rb +27 -0
  32. data/spec/spec_helper.rb +104 -0
  33. data/spec/test/always_fail_spec.rb +25 -0
  34. data/spec/test/always_pass_spec.rb +15 -0
  35. data/spec/test/strategy_spec.rb +48 -0
  36. data/spec/test/test_spec.rb +22 -0
  37. metadata +209 -0
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ features/proving_grounds
19
+ .DS_Store
@@ -0,0 +1,12 @@
1
+ SimpleCov.start do
2
+ add_filter '/spec/'
3
+ add_filter '/features/'
4
+
5
+ # this gets acceptance tested, not unit tested
6
+ add_filter 'formatter.rb'
7
+
8
+ # don't look at coverage of plugins, let them test themselves
9
+ add_filter do |source_file|
10
+ !source_file.filename[File.dirname(__FILE__)+'/']
11
+ end
12
+ end
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Josh Cheek
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+
4
+ task :rspec do
5
+ require 'rspec'
6
+ Dir.glob("spec/**/*_spec.rb").each { |filename| require File.expand_path filename }
7
+ RSpec::Core::Runner.run []
8
+ end
9
+
10
+ require 'cucumber/rake/task'
11
+ default_cucumber_opts = "features --format pretty --tags ~@not-implemented"
12
+ Cucumber::Rake::Task.new(:cucumber) { |t| t.cucumber_opts = default_cucumber_opts + " --tags ~@wip" }
13
+ Cucumber::Rake::Task.new('cucumber:wip') { |t| t.cucumber_opts = default_cucumber_opts + " --tags @wip" }
14
+
15
+
16
+ task rspec_must_be_100_percent: :rspec do
17
+ percent = SimpleCov.result.covered_percent
18
+ unless percent == 100
19
+ SimpleCov.result.format!
20
+ fail "\e[31mYo, dawg some of your shit isn't getting tested, only %0.2f%%\e[0m" % percent
21
+ end
22
+ end
23
+
24
+
25
+ require 'mountain_berry_fields/rake_task'
26
+ MountainBerryFields::RakeTask.new(:generate_readme, 'Readme.md.mountain_berry_fields')
27
+
28
+ task default: [:rspec_must_be_100_percent, :cucumber, :generate_readme]
29
+
30
+
@@ -0,0 +1,184 @@
1
+ # MountainBerryFields
2
+
3
+ Tests code in readme files, generates the readme if they are successful.
4
+
5
+ ## Usage
6
+
7
+ When you have a file with embedded code samples, rename it to include a .mountain_berry_fields suffix.
8
+ Then wrap test statements around the code samples. I've written two testing strategies: rspec and magic_comments.
9
+ You can create your own without much effort.
10
+
11
+
12
+ ### Code samples with magic comments
13
+
14
+ You will need to
15
+ `$ gem install mountain_berry_fields-magic_comments`
16
+ for this to work.
17
+
18
+ The file `Readme.mountain_berry_fields.md`
19
+
20
+ # MyLibName
21
+
22
+ <% test 'an example', with: :magic_comments do %>
23
+ MyLibName.new('some data').result # => "some cool result"
24
+ <% end %>
25
+
26
+ Run `$ mountain_berry_fields Readme.mountain_berry_fields.md` and it will generate `Readme.md`
27
+
28
+ # MyLibName
29
+
30
+ MyLibName.new('some data').result # => "some cool result"
31
+
32
+ If at some point, you change your lib to not do that cool thing, then it will not generate the file. Instead it will give you an error message:
33
+
34
+ FAILURE: an example
35
+ Expected: MyLibName.new('some data').result # => "some cool result"
36
+ Actual: MyLibName.new('some data').result # => "some unexpected result"
37
+
38
+ Now you can be confident that your code is still legit.
39
+
40
+ Realworld [example](https://github.com/JoshCheek/deject/blob/8eb0d92949318cf4ef87c2b1a2070328024b0196/Readme.md.mountain_berry_fields#L40-48).
41
+
42
+ ### Code samples with RSpec
43
+
44
+ You will need to
45
+ `$ gem install mountain_berry_fields-rspec`
46
+ for this to work.
47
+
48
+ The file `Readme.mountain_berry_fields.md`
49
+
50
+ # MyLibName
51
+
52
+ <% test 'an example', with: :rspec do %>
53
+ describe MyLibName do
54
+ it 'does what I made it do' do
55
+ described_class.new('some data').result.should == 'some cool result'
56
+ end
57
+ end
58
+ <% end %>
59
+
60
+ Run `$ mountain_berry_fields Readme.mountain_berry_fields.md` to generate `Readme.md`
61
+
62
+ # MyLibName
63
+
64
+ describe MyLibName do
65
+ it 'does what I made it do' do
66
+ described_class.new('some data').result.should == 'some cool result'
67
+ end
68
+ end
69
+
70
+ And an rspec error:
71
+
72
+ FAILURE: an example
73
+ MyLibName does what I made it do:
74
+ expected: "some cool result"
75
+ got: "some unexpected result" (using ==)
76
+
77
+ backtrace:
78
+ /spec.rb:8:in `block (2 levels) in <top (required)>'
79
+
80
+ Realworld [example](https://github.com/JoshCheek/surrogate/blob/b7ad4d3cd5ce2e3b8bf44c3743436e4d614b1991/Readme.md.mountain_berry_fields#L254-258).
81
+
82
+ ### Setup blocks
83
+
84
+ You may need to do something to setup the environment for the tests (e.g. load the lib your examples are using)
85
+ Do that with a setup block:
86
+
87
+ <% setup do %>
88
+ $LOAD_PATH.unshift File.expand_path '../lib', __FILE__
89
+ require 'my_lib_name'
90
+ <% end %>
91
+
92
+ This will not show up anywhere in the generated file. It will be prepended before each code sample when running tests.
93
+
94
+ Realworld [example](https://github.com/JoshCheek/deject/blob/8eb0d92949318cf4ef87c2b1a2070328024b0196/Readme.md.mountain_berry_fields#L22-25).
95
+
96
+ ### Context blocks
97
+
98
+ Some examples may need to be executed within a context. Use a context block for that.
99
+ Use the `__CODE__` macro to indicate where the code should go relative to this context.
100
+
101
+ <% context 'a user named Carlita' do %>
102
+ user = Struct.new(:name).new 'Carlita'
103
+ __CODE__
104
+ <% end %>
105
+
106
+ <% test 'users have a name', context: 'a user named Carlita', with: :magic_comments do %>
107
+ user.name # => "Carlita"
108
+ <% end %>
109
+
110
+ Context blocks can, themselves, be rendered into a context `<% context 'current', context: "my context's context" do %>`
111
+
112
+ Realworld [example](https://github.com/JoshCheek/surrogate/blob/b7ad4d3cd5ce2e3b8bf44c3743436e4d614b1991/Readme.md.mountain_berry_fields#L237-258).
113
+
114
+ ### Rake Task
115
+
116
+ If you want to add this as part of your build, there is a rake task:
117
+
118
+ ```ruby
119
+ require 'mountain_berry_fields/rake_task'
120
+ MountainBerryFields::RakeTask.new(:mbf, 'Readme.mountain_berry_fields.md')
121
+ ```
122
+
123
+ which will allow you to say `$ rake mbf`. You could then add it to your default task with
124
+ `task default: :mbf`, or have whatever task runs your tests just execute it at the end.
125
+
126
+ Realworld [example](https://github.com/JoshCheek/surrogate/blob/b7ad4d3cd5ce2e3b8bf44c3743436e4d614b1991/Rakefile#L13-17).
127
+
128
+ ### Creating your own test strategy
129
+
130
+ I've written the magic_comments and rspec strategies. You can write your own that do
131
+ whatever interesting thing you've thought of.
132
+
133
+ If you want it to be a gem, then the strategy needs to be in the file
134
+ `mountain_berry_fields/test/your_strategy.rb`. Mountain Berry Fields
135
+ will automatically load files at these paths. If your strategy is not a gem,
136
+ then it is up to you to ensure the code defining the strategy is loaded.
137
+
138
+ Any strategy can be made accessible to the .mountain_berry_fields file like this:
139
+ `MountainBerryFields::Test::Strategy.register :your_strategy, YourStrategy`
140
+ And then accessed by `<% test 'testname', with: :your_strategy do %>`
141
+
142
+ Strategies will be initialized with the code to test, and are expected to
143
+ implement `#pass?` which returns a boolean of whether the code passes according
144
+ to that strategy, and `#failure_message` which will used to describe why the spec
145
+ failed to users.
146
+
147
+ Realworld gem [example](https://github.com/JoshCheek/mountain_berry_fields-rspec/blob/cc6364ad106a7c65822542709bc5676bfb0b2c07/lib/mountain_berry_fields/test/rspec.rb).
148
+ Realworld non-gem [example](https://github.com/JoshCheek/mountain_berry_fields/blob/be751536c8b0f94c84b09167fa83616b94b13b12/readme_helper.rb).
149
+
150
+ ### About the name
151
+
152
+ I am often asked why I picked this name. I make things like this for me, because I have decided that they have value.
153
+ I felt the need to remind myself of that so I chose a name that no one would realisitcally choose,
154
+ to remind myself of the fact that no one could tell me I couldn't choose it.
155
+
156
+ The phrase "Mountain berry fields" is a lyric in a [song](http://www.myspace.com/joyelectric/music/songs/birds-will-sing-forever-christian-songs-album-version-34576758) that makes me happy.
157
+
158
+ If it bothers you: `$ alias mbf=mountain_berry_fields`
159
+
160
+ ## TODO
161
+ * set it up on Travis
162
+
163
+ ## Features to add for v2
164
+
165
+ Note that my use cases are to be able to test Deject and Surrogate,
166
+ which this currently does quite nicely. As a result, I have no imminent
167
+ need for any of these features, and so they are not a priority for me.
168
+ If you have a need for them (or for other features), let me know and that
169
+ will cause it to be a much higher priority for me. Alternatively,
170
+ pull requests that add them, fix bugs, or generally make it better,
171
+ are more than welcome.
172
+
173
+ * contexts should be lazy (can define context after a block that uses it)
174
+ * should be able to pass options to the initializer
175
+ * enable the test strategy to decide what should be returned
176
+ * support for multiple input files
177
+ * FLAGS:
178
+ * * -o set up input files so they don't need a .mountain_berry_fields in their name (output filename is provided, so input filename needs no naming conventions)
179
+ * * -s list all known test strategies
180
+ * * -v version
181
+ * * -c check syntax (no output, thus also no input filename restrictions)
182
+ * * -e flag for outputting erb (e.g. when it gives weird ass _buf error)
183
+ * * -h to display this menu
184
+ * * ?? to display the code that was passed to the test, along with the failure
@@ -0,0 +1,197 @@
1
+ <% load "readme_helper.rb" %>
2
+ # MountainBerryFields
3
+
4
+ Tests code in readme files, generates the readme if they are successful.
5
+
6
+ ## Usage
7
+
8
+ When you have a file with embedded code samples, rename it to include a .mountain_berry_fields suffix.
9
+ Then wrap test statements around the code samples. I've written two testing strategies: rspec and magic_comments.
10
+ You can create your own without much effort.
11
+
12
+
13
+ ### Code samples with magic comments
14
+
15
+ You will need to
16
+ `<% test('dep magic_comments', with: :install_dep) { %>$ gem install mountain_berry_fields-magic_comments<% } %>`
17
+ for this to work.
18
+
19
+ <% test 'show magic comments', with: :mbf_example do %>
20
+ The file `Readme.mountain_berry_fields.md`
21
+
22
+ # MyLibName
23
+
24
+ <%% test 'an example', with: :magic_comments do %>
25
+ MyLibName.new('some data').result # => "some cool result"
26
+ <%% end %>
27
+
28
+ Run `$ mountain_berry_fields Readme.mountain_berry_fields.md` and it will generate `Readme.md`
29
+
30
+ # MyLibName
31
+
32
+ MyLibName.new('some data').result # => "some cool result"
33
+
34
+ If at some point, you change your lib to not do that cool thing, then it will not generate the file. Instead it will give you an error message:
35
+
36
+ FAILURE: an example
37
+ Expected: MyLibName.new('some data').result # => "some cool result"
38
+ Actual: MyLibName.new('some data').result # => "some unexpected result"
39
+ <% end %>
40
+
41
+ Now you can be confident that your code is still legit.
42
+
43
+ Realworld [example](https://github.com/JoshCheek/deject/blob/8eb0d92949318cf4ef87c2b1a2070328024b0196/Readme.md.mountain_berry_fields#L40-49).
44
+
45
+ ### Code samples with RSpec
46
+
47
+ You will need to
48
+ `<% test('dep rspec', with: :install_dep) { %>$ gem install mountain_berry_fields-rspec<% } %>`
49
+ for this to work.
50
+
51
+ <% test 'show rspec', with: :mbf_example do %>
52
+ The file `Readme.mountain_berry_fields.md`
53
+
54
+ # MyLibName
55
+
56
+ <%% test 'an example', with: :rspec do %>
57
+ describe MyLibName do
58
+ it 'does what I made it do' do
59
+ described_class.new('some data').result.should == 'some cool result'
60
+ end
61
+ end
62
+ <%% end %>
63
+
64
+ Run `$ mountain_berry_fields Readme.mountain_berry_fields.md` to generate `Readme.md`
65
+
66
+ # MyLibName
67
+
68
+ describe MyLibName do
69
+ it 'does what I made it do' do
70
+ described_class.new('some data').result.should == 'some cool result'
71
+ end
72
+ end
73
+
74
+ And an rspec error:
75
+
76
+ FAILURE: an example
77
+ MyLibName does what I made it do:
78
+ expected: "some cool result"
79
+ got: "some unexpected result" (using ==)
80
+
81
+ backtrace:
82
+ /spec.rb:8:in `block (2 levels) in <top (required)>'
83
+ <% end %>
84
+
85
+ Realworld [example](https://github.com/JoshCheek/surrogate/blob/b7ad4d3cd5ce2e3b8bf44c3743436e4d614b1991/Readme.md.mountain_berry_fields#L254-258).
86
+
87
+ ### Setup blocks
88
+
89
+ You may need to do something to setup the environment for the tests (e.g. load the lib your examples are using)
90
+ Do that with a setup block:
91
+
92
+ <% test 'setup blocks', with: :requires_lib do %>
93
+ <%% setup do %>
94
+ $LOAD_PATH.unshift File.expand_path '../lib', __FILE__
95
+ require 'my_lib_name'
96
+ <%% end %>
97
+ <% end %>
98
+
99
+ This will not show up anywhere in the generated file. It will be prepended before each code sample when running tests.
100
+
101
+ Realworld [example](https://github.com/JoshCheek/deject/blob/8eb0d92949318cf4ef87c2b1a2070328024b0196/Readme.md.mountain_berry_fields#L22-25).
102
+
103
+ ### Context blocks
104
+
105
+ Some examples may need to be executed within a context. Use a context block for that.
106
+ Use the `__CODE__` macro to indicate where the code should go relative to this context.
107
+
108
+ <% test 'context block', with: :generic_mbf do %>
109
+ <%% context 'a user named Carlita' do %>
110
+ user = Struct.new(:name).new 'Carlita'
111
+ __CODE__
112
+ <%% end %>
113
+
114
+ <%% test 'users have a name', context: 'a user named Carlita', with: :magic_comments do %>
115
+ user.name # => "Carlita"
116
+ <%% end %>
117
+ <% end %>
118
+
119
+ Context blocks can, themselves, be rendered into a context `<%% context 'current', context: "my context's context" do %>`
120
+
121
+ Realworld [example](https://github.com/JoshCheek/surrogate/blob/b7ad4d3cd5ce2e3b8bf44c3743436e4d614b1991/Readme.md.mountain_berry_fields#L237-258).
122
+
123
+ ### Rake Task
124
+
125
+ If you want to add this as part of your build, there is a rake task:
126
+
127
+ ```ruby
128
+ <%# this is the only one I'm going to test here. Maybe in the future, a gem for strategies specifically targeting rake %>
129
+ <% test 'rake task', with: :task_named_mbf do %>
130
+ require 'mountain_berry_fields/rake_task'
131
+ MountainBerryFields::RakeTask.new(:mbf, 'Readme.mountain_berry_fields.md')
132
+ <% end %>
133
+ ```
134
+
135
+ which will allow you to say `$ rake mbf`. You could then add it to your default task with
136
+ `task default: :mbf`, or have whatever task runs your tests just execute it at the end.
137
+
138
+ Realworld [example](https://github.com/JoshCheek/surrogate/blob/b7ad4d3cd5ce2e3b8bf44c3743436e4d614b1991/Rakefile#L13-17).
139
+
140
+ ### Creating your own test strategy
141
+
142
+ I've written the magic_comments and rspec strategies. You can write your own that do
143
+ whatever interesting thing you've thought of.
144
+
145
+ If you want it to be a gem, then the strategy needs to be in the file
146
+ `mountain_berry_fields/test/your_strategy.rb`. Mountain Berry Fields
147
+ will automatically load files at these paths. If your strategy is not a gem,
148
+ then it is up to you to ensure the code defining the strategy is loaded.
149
+
150
+ Any strategy can be made accessible to the .mountain_berry_fields file like this:
151
+ `<% test('registering', with: :register_your_strategy){ %>MountainBerryFields::Test::Strategy.register :your_strategy, YourStrategy<%}%>`
152
+ And then accessed by `<%% test 'testname', with: :your_strategy do %>`
153
+
154
+ Strategies will be initialized with the code to test, and are expected to
155
+ implement `#pass?` which returns a boolean of whether the code passes according
156
+ to that strategy, and `#failure_message` which will used to describe why the spec
157
+ failed to users.
158
+
159
+ Realworld gem [example](https://github.com/JoshCheek/mountain_berry_fields-rspec/blob/cc6364ad106a7c65822542709bc5676bfb0b2c07/lib/mountain_berry_fields/test/rspec.rb).
160
+ Realworld non-gem [example](https://github.com/JoshCheek/mountain_berry_fields/blob/be751536c8b0f94c84b09167fa83616b94b13b12/readme_helper.rb),
161
+ and the code that [loads](https://github.com/JoshCheek/mountain_berry_fields/blob/754c3fb9d26779e38c01e15999ea6b86137372a2/Readme.md.mountain_berry_fields#L1) it.
162
+
163
+ ### About the name
164
+
165
+ I am often asked why I picked this name. I make things like this for me, because I have decided that they have value.
166
+ I felt the need to remind myself of that so I chose a name that no one would realisitcally choose,
167
+ to remind myself of the fact that no one could tell me I couldn't choose it.
168
+
169
+ The phrase "Mountain berry fields" is a lyric in a [song](http://www.myspace.com/joyelectric/music/songs/birds-will-sing-forever-christian-songs-album-version-34576758) that makes me happy.
170
+
171
+ If it bothers you: `$ alias mbf=mountain_berry_fields`
172
+
173
+ ## TODO
174
+ * set it up on Travis
175
+
176
+ ## Features to add for v2
177
+
178
+ Note that my use cases are to be able to test Deject and Surrogate,
179
+ which this currently does quite nicely. As a result, I have no imminent
180
+ need for any of these features, and so they are not a priority for me.
181
+ If you have a need for them (or for other features), let me know and that
182
+ will cause it to be a much higher priority for me. Alternatively,
183
+ pull requests that add them, fix bugs, or generally make it better,
184
+ are more than welcome.
185
+
186
+ * contexts should be lazy (can define context after a block that uses it)
187
+ * should be able to pass options to the initializer
188
+ * enable the test strategy to decide what should be returned
189
+ * support for multiple input files
190
+ * FLAGS:
191
+ * * -o set up input files so they don't need a .mountain_berry_fields in their name (output filename is provided, so input filename needs no naming conventions)
192
+ * * -s list all known test strategies
193
+ * * -v version
194
+ * * -c check syntax (no output, thus also no input filename restrictions)
195
+ * * -e flag for outputting erb (e.g. when it gives weird ass _buf error)
196
+ * * -h to display this menu
197
+ * * ?? to display the code that was passed to the test, along with the failure