wrong 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/README.markdown +114 -25
  2. data/lib/predicated/Gemfile +15 -0
  3. data/lib/predicated/LICENSE +20 -0
  4. data/lib/predicated/README.markdown +191 -0
  5. data/lib/predicated/Rakefile +51 -0
  6. data/lib/predicated/lib/predicated.rb +4 -0
  7. data/lib/predicated/lib/predicated/autogen_call.rb +37 -0
  8. data/lib/predicated/lib/predicated/constrain.rb +66 -0
  9. data/lib/predicated/lib/predicated/evaluate.rb +94 -0
  10. data/lib/predicated/lib/predicated/from/callable_object.rb +108 -0
  11. data/lib/predicated/lib/predicated/from/json.rb +59 -0
  12. data/lib/predicated/lib/predicated/from/ruby_code_string.rb +73 -0
  13. data/lib/predicated/lib/predicated/from/url_part.rb +104 -0
  14. data/lib/predicated/lib/predicated/from/xml.rb +61 -0
  15. data/lib/predicated/lib/predicated/gem_check.rb +34 -0
  16. data/lib/predicated/lib/predicated/predicate.rb +111 -0
  17. data/lib/predicated/lib/predicated/print.rb +62 -0
  18. data/lib/predicated/lib/predicated/selectable.rb +102 -0
  19. data/lib/predicated/lib/predicated/simple_templated_predicate.rb +79 -0
  20. data/lib/predicated/lib/predicated/string_utils.rb +20 -0
  21. data/lib/predicated/lib/predicated/to/arel.rb +41 -0
  22. data/lib/predicated/lib/predicated/to/json.rb +48 -0
  23. data/lib/predicated/lib/predicated/to/sentence.rb +94 -0
  24. data/lib/predicated/lib/predicated/to/solr.rb +15 -0
  25. data/lib/predicated/lib/predicated/to/xml.rb +67 -0
  26. data/lib/predicated/lib/predicated/version.rb +3 -0
  27. data/lib/predicated/predicated.gemspec +22 -0
  28. data/lib/predicated/test/autogen_call_test.rb +40 -0
  29. data/lib/predicated/test/canonical_transform_cases.rb +63 -0
  30. data/lib/predicated/test/constrain_test.rb +86 -0
  31. data/lib/predicated/test/enumerable_test.rb +32 -0
  32. data/lib/predicated/test/equality_test.rb +32 -0
  33. data/lib/predicated/test/evaluate_test.rb +149 -0
  34. data/lib/predicated/test/from/callable_object_canonical_test.rb +43 -0
  35. data/lib/predicated/test/from/callable_object_test.rb +78 -0
  36. data/lib/predicated/test/from/json_test.rb +83 -0
  37. data/lib/predicated/test/from/ruby_code_string_canonical_test.rb +37 -0
  38. data/lib/predicated/test/from/ruby_code_string_test.rb +103 -0
  39. data/lib/predicated/test/from/url_part_parser_test.rb +123 -0
  40. data/lib/predicated/test/from/url_part_test.rb +48 -0
  41. data/lib/predicated/test/from/xml_test.rb +57 -0
  42. data/lib/predicated/test/json_conversion_test.rb +33 -0
  43. data/lib/predicated/test/print_test.rb +66 -0
  44. data/lib/predicated/test/selectable_test.rb +123 -0
  45. data/lib/predicated/test/simple_templated_predicate_test.rb +39 -0
  46. data/lib/predicated/test/suite.rb +2 -0
  47. data/lib/predicated/test/test_helper.rb +64 -0
  48. data/lib/predicated/test/test_helper_with_wrong.rb +6 -0
  49. data/lib/predicated/test/to/arel_test.rb +85 -0
  50. data/lib/predicated/test/to/json_test.rb +74 -0
  51. data/lib/predicated/test/to/sentence_test.rb +90 -0
  52. data/lib/predicated/test/to/solr_test.rb +39 -0
  53. data/lib/predicated/test/to/xml_test.rb +72 -0
  54. data/lib/predicated/test/xml_conversion_test.rb +34 -0
  55. data/lib/predicated/test_integration/arel_integration_test.rb +52 -0
  56. data/lib/predicated/test_integration/canonical_integration_cases.rb +66 -0
  57. data/lib/predicated/test_integration/schema.xml +83 -0
  58. data/lib/predicated/test_integration/solr_integration_test.rb +71 -0
  59. data/lib/predicated/test_integration/sqlite_db +0 -0
  60. data/lib/predicated/test_integration/suite.rb +2 -0
  61. data/lib/predicated/test_integration/usage_test.rb +252 -0
  62. data/lib/wrong.rb +3 -1
  63. data/lib/wrong/adapters/test_unit.rb +1 -3
  64. data/lib/wrong/assert.rb +81 -24
  65. data/lib/wrong/chunk.rb +145 -0
  66. data/lib/wrong/message/string_diff.rb +2 -4
  67. data/lib/wrong/message/test_context.rb +2 -2
  68. data/lib/wrong/version.rb +2 -2
  69. data/test/adapters/minitest_test.rb +16 -9
  70. data/test/adapters/test_unit_test.rb +1 -1
  71. data/test/assert_test.rb +90 -0
  72. data/test/catch_raise_test.rb +2 -2
  73. data/test/chunk_test.rb +236 -0
  74. data/test/failures_test.rb +109 -74
  75. data/test/message/array_diff_test.rb +35 -19
  76. data/test/message/string_diff_test.rb +39 -15
  77. data/test/message/test_context_text.rb +2 -2
  78. data/test/test_helper.rb +25 -7
  79. metadata +86 -33
  80. data/test/basic_assert_test.rb +0 -38
@@ -1,56 +1,145 @@
1
+ "Feels so right, it can't be Wrong"
2
+
1
3
  ## Abstract ##
2
4
 
3
- Wrong provides a general assert method that takes a predicate block. Assertion failure messages are rich in detail.
5
+ Wrong provides a general assert method that takes a predicate block. Assertion failure
6
+ messages are rich in detail. The Wrong idea is to replace all those countless assert_this,
7
+ assert_that library methods which only exist to give a more useful failure message than
8
+ "assertion failed". Wrong replaces all of them in one fell swoop, since if you can write it
9
+ in Ruby, Wrong can make a sensible failure message out of it.
4
10
 
5
- Wrong is alpha-quality - I'd very much appreciate feedback and bug reports.
11
+ Wrong is alpha-quality. We'd very much appreciate feedback and bug reports. There are plenty of things left to be done
12
+ to make the results look uniformly clean and beautiful. We want your feedback, and especially to give us cases where
13
+ either it blows up or the output is ugly or uninformative.
6
14
 
7
- It's an offshoot of predicated.
8
- [http://github.com/sconover/predicated](http://github.com/sconover/predicated)
15
+ It relies on [Predicated](http://github.com/sconover/predicated) for its main failure message.
9
16
 
10
- Inspired by assert { 2.0 }
11
- [http://assert2.rubyforge.org/](http://assert2.rubyforge.org/)
17
+ Inspired by [assert { 2.0 }](http://assert2.rubyforge.org/) but rewritten from scratch to be compatible with Ruby 1.8 and 1.9.
12
18
 
13
19
  ## Usage ##
14
20
 
15
- Wrong provides a simple assert method:
21
+ Wrong provides a simple assert method that takes a block:
16
22
 
17
23
  require "wrong"
18
24
 
19
25
  include Wrong::Assert
20
26
 
21
- assert{1==1}
27
+ assert {1==1}
22
28
  ==> nil
23
29
 
24
- assert{2==1}
25
- ==> Wrong::Assert::AssertionFailedError: 2 is not equal to 1
26
-
30
+ assert {2==1}
31
+ ==> Wrong::Assert::AssertionFailedError: Expected (2 == 1), but 2 is not equal to 1
32
+
33
+ If your assertion is more than a simple predicate, then Wrong will split it into parts and show you the values of all the relevant subexpressions.
34
+
35
+ x = 7; y = 10; assert { x == 7 && y == 11 }
36
+ ==>
37
+ Wrong::Assert::AssertionFailedError: Expected ((x == 7) and (y == 11)), but
38
+ (x == 7) is true
39
+ x is 7
40
+ (y == 11) is false
41
+ y is 10
42
+
27
43
  And a companion, 'deny':
28
44
 
29
45
  deny{'abc'.include?('bc')}
30
- ==> Wrong::Assert::AssertionFailedError: 'abc' includes 'bc'
46
+ ==> Wrong::Assert::AssertionFailedError: Didn't expect "abc".include?("bc"), but 'abc' includes 'bc'
31
47
 
32
- There's a convenience method for catching errors:
48
+ There's also a convenience method for catching errors:
33
49
 
34
- assert{ catch_raise{raise "boom!"}.message == "boom!" }
35
- ==> nil
50
+ assert{ catch_raise{raise "vanilla"}.message == "chocolate" }
51
+ ==>
52
+ Wrong::Assert::AssertionFailedError: Expected (catch_raise { raise("vanilla") }.message == "chocolate"), but 'vanilla' is not equal to 'chocolate'
53
+
54
+ ## Apology ##
55
+
56
+ So does the world need another assertion framework? In fact, it does not! We actually believe the world needs **fewer** assert methods.
57
+
58
+ The Wrong idea is to replace all those countless assert\_this, assert\_that library methods which only exist to give a more useful failure message than "assertion failed". Wrong replaces all of them in one fell swoop, since if you can write it in Ruby, Wrong can make a sensible failure message out of it.
59
+
60
+ Even the lowly workhorse `assert_equal` is bloated compared to Wrong: would you rather write this
61
+
62
+ assert_equal time, money
63
+
64
+ or this
65
+
66
+ assert { time == money }
67
+
68
+ ? The Wrong version has the advantage of being plain, transparent Ruby code, not an awkward DSL that moves "equal" out of its natural place between the comparands. Plus, WYSIWYG! You know just from looking at it that "equal" means `==`, not `eql?` or `===` or `=~`.
69
+
70
+ Moreover, much like TDD itself, Wrong encourages you to write cleaner code. If your assertion messages are not clear and "Englishy", then maybe it's time for you to refactor a bit -- extract an informatively named variable or method, maybe push some function onto its natural object *a la* the [Law of Demeter](http://en.wikipedia.org/wiki/Law_of_Demeter)...
71
+
72
+ Wrong also lets you put the expected and actual values in any order you want! Consider the failure messages for
73
+
74
+ assert { current_user == "joe" } # => Expected (current_user == "joe") but current_user is "fred"
75
+ assert { "joe" == current_user } # => Expected ("joe" == current_user) but current_user is "fred"
76
+
77
+ You get just the information you want, and none you don't want. At least, that's the plan! :-)
78
+
79
+ ## Algorithm ##
80
+
81
+ So wait a second. How do we do it? Doesn't Ruby have [poor support for AST introspection](http://blog.zenspider.com/2009/04/parsetree-eol.html)? Well, yes, it does, so we cheat: we figure out what file and line the assert block is defined in, then open the file, read the code, and parse it directly using Ryan Davis' amazing [RubyParser](http://parsetree.rubyforge.org/ruby_parser/) and [Ruby2Ruby](http://seattlerb.rubyforge.org/ruby2ruby/). You can bask in the kludge by examining `chunk.rb` and `assert.rb`. If you find some code it can't parse, please send it our way.
82
+
83
+ Before you get your knickers in a twist about how this is totally unacceptable because it doesn't support this or that use case, here are our caveats and excuses:
84
+
85
+ * It works! Tested in 1.8.6, 1.8.7, 1.9.1, and 1.9.2-rc2. (Thank you, [rvm](http://rvm.beginrescueend.com/)!)
86
+ * Your code needs to be in a file. That means it doesn't work in IRB. (If you're developing Ruby code without saving it to a mounted disk, then sorry, Wrong is not right for you.)
87
+ * It's a development-time testing library, not a production runtime library, so there are no security or filesystem issues.
88
+ * `eval` isn't evil, it's just misunderstood.
89
+ * It makes a few assumptions about the structure of your code, leading to some restrictions:
90
+ * You can't have more than one call to `assert` per line. (This should not be a problem since even if you're nesting asserts for some bizarre reason, we assume you know where your Return key is. And actually, technically you can put two asserts on a line, but it always describes the first one it sees, which means that if the second one executes, its failure message will be incorrect or broken.)
91
+ * You can't use metaprogramming to write your assert blocks.
92
+ * All variables and methods must be available in the binding of the assertion block.
36
93
 
37
94
  ## Adapters ##
38
95
 
39
96
  Adapters for various test frameworks sit under wrong/adapters.
40
- TODO
41
97
 
42
- ## Message ##
98
+ Currently we support
99
+
100
+ * Test::Unit
101
+ * Minitest
102
+
103
+ Coming soon
104
+
105
+ * RSpec
106
+ * ???
107
+
108
+ ## Explanations ##
109
+
110
+ `assert` and `deny` can take an optional explanation, e.g.
111
+
112
+ assert("since we're on Earth") { sky.blue? }
113
+
114
+ Since the point of Wrong is to make asserts self-explanatory, you should feel free to use explanations only when they would add something that you couldn't get from reading the (failed) assertion code itself. Don't bother doing things like this:
115
+
116
+ assert("the sky should be blue") { sky.blue? } # redundant
117
+
118
+ The failure message of the above would be something like "Expected sky.blue? but sky is :green" which is not made clearer by the addition of "the sky should be blue". We already know it should be blue since we see right there that we're expecting it to be blue.
119
+
120
+ And if your assertion code isn't self-explanatory, then that's a hint that you might need to do some refactoring until it is. (Yes, even test code should be clean as a whistle. **Especially** test code.)
121
+
122
+ ## Special Formatting ##
43
123
 
44
124
  Enhancements for error messages sit under wrong/message.
45
- TODO
46
125
 
47
- ## Etc ##
126
+ Currently we support special messages for
127
+
128
+ * String ==
129
+ * Enumerable ==
130
+ * including nested string elements
131
+
132
+ ## Helper Assert Methods ##
48
133
 
49
- Tracker project:
50
- [http://www.pivotaltracker.com/projects/95014](http://www.pivotaltracker.com/projects/95014)
134
+ If you really want to, you can define your procs in one method, pass it in to another method, and have that method assert it. This is very bizarre and you probably shouldn't do it. Wrong will do its best to figure out where the actual assertion code is but it might not succeed.
51
135
 
52
- “I think it's wrong that only one company makes the game Monopoly.” -Steven Wright
136
+ If you're in Ruby 1.8, you **really** shouldn't do it! But if you do, you can use the "depth" parameter to give Wrong a better hint about how far up the stack it should crawl to find the code. See `assert_test.rb` for more details, if you dare.
137
+
138
+ ## Authors ##
139
+
140
+ * Steve Conover - <sconover@gmail.com>
141
+ * Alex Chaffee - <alex@stinky.com> - <http://alexch.github.com>
142
+
143
+ ## Etc ##
53
144
 
54
- "And it really doesn't matter if I'm wrong
55
- I'm right where I belong"
56
- -Fixing a Hole
145
+ Tracker project: <http://www.pivotaltracker.com/projects/109993>
@@ -0,0 +1,15 @@
1
+ source :gemcutter
2
+ gem "ruby_parser"
3
+ gem "ruby2ruby"
4
+ gem "ParseTree"
5
+ gem "diff"
6
+ gem "diff-lcs"
7
+ gem "minitest"
8
+ gem "nokogiri"
9
+ gem "arel", "~>0.4"
10
+ gem "sqlite3-ruby"
11
+ gem "activerecord", "~>3.0.0.beta"
12
+ gem "i18n"
13
+ gem "json", "1.1.9"
14
+ gem "treetop", "~>1.4.8"
15
+
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Steve Conover
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,191 @@
1
+ ## Abstract ##
2
+
3
+ Predicated is a simple predicate model for Ruby. It provides useful predicate transformations and operations.
4
+
5
+ Tracker project:
6
+ [http://www.pivotaltracker.com/projects/95014](http://www.pivotaltracker.com/projects/95014)
7
+
8
+ ## Transformations ##
9
+
10
+ - From:
11
+ - json
12
+ - xml
13
+ - url part, ex: "!(a=1&b=2|c=3)"
14
+ - callable objects (lambdas/procs, and therefore blocks) - ruby 1.8.x only
15
+ - ruby code - ruby 1.8.x only
16
+ - To:
17
+ - json
18
+ - xml
19
+ - sql where clause via [arel](http://github.com/rails/arel)
20
+ - [solr](http://lucene.apache.org/solr/) query string
21
+ - english sentence, ex: "'a' is not equal to 'b'"
22
+
23
+ ## Usage ##
24
+
25
+ Note: The test suite acts as a comprehensive usage guide.
26
+
27
+
28
+ Evaluate a predicate:
29
+
30
+ require "predicated/evaluate"
31
+ include Predicated
32
+
33
+ Predicate { Eq(1, 2) }.evaluate == false
34
+ Predicate { Lt(1, 2) }.evaluate == true
35
+ Predicate { Or(Lt(1, 2),Eq(1, 2)) }.evaluate == true
36
+
37
+ x = 1
38
+ Predicate { Lt(x, 2) }.evaluate == true
39
+
40
+
41
+ Parse a predicate from part of a url and then turn it into a sql where clause:
42
+
43
+ require "predicated/from/url_part"
44
+ require "predicated/to/arel"
45
+
46
+ predicate = Predicated::Predicate.from_url_part("(color=red|color=green)&size=large")
47
+
48
+ predicate.inspect ==
49
+ "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
50
+
51
+ predicate.to_arel(Table(:shirt)).to_sql ==
52
+ %{(("shirt"."color" = 'red' OR "shirt"."color" = 'green') AND "shirt"."size" = 'large')}
53
+
54
+
55
+ Parse a predicate from json and then turn it into a solr query string:
56
+
57
+ require "predicated/from/json"
58
+ require "predicated/to/solr"
59
+
60
+ predicate = Predicated::Predicate.from_json_str(%{
61
+ {"and":[{"or":[["color","==","red"],["color","==","green"]]},["size","==","large"]]}
62
+ })
63
+
64
+ predicate.inspect == "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
65
+
66
+ predicate.to_solr == "((color:red OR color:green) AND size:large)"
67
+
68
+
69
+ From json:
70
+
71
+ require "predicated/from/json"
72
+
73
+ Predicated::Predicate.from_json_str(%{
74
+ {"and":[
75
+ {"or":[
76
+ ["color","==","red"],
77
+ ["color","==","green"]
78
+ ]},
79
+ ["size","==","large"]
80
+ ]}
81
+ }).inspect == "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
82
+
83
+
84
+ From xml:
85
+
86
+ require "predicated/from/xml"
87
+
88
+ Predicated::Predicate.from_xml(%{
89
+ <and>
90
+ <or>
91
+ <equal><left>color</left><right>red</right></equal>
92
+ <equal><left>color</left><right>green</right></equal>
93
+ </or>
94
+ <equal><left>size</left><right>large</right></equal>
95
+ </and>
96
+ }).inspect == "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
97
+
98
+
99
+ From url part:
100
+
101
+ require "predicated/from/url_part"
102
+
103
+ Predicated::Predicate.from_url_part("(color=red|color=green)&size=large").inspect ==
104
+ "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
105
+
106
+
107
+ From callable object:
108
+
109
+ require "predicated/from/callable_object"
110
+
111
+ Predicated::Predicate.from_callable_object{('color'=='red' || 'color'=='green') && 'size'=='large'}.inspect ==
112
+ "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
113
+
114
+
115
+ From ruby code string:
116
+
117
+ require "predicated/from/ruby_code_string"
118
+
119
+ Predicated::Predicate.from_ruby_code_string("('color'=='red' || 'color'=='green') && 'size'=='large'").inspect ==
120
+ "And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))"
121
+
122
+
123
+ To json:
124
+
125
+ require "predicated/to/json"
126
+ include Predicated
127
+
128
+ Predicate{And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))}.to_json_str ==
129
+ %{
130
+ {"and":[
131
+ {"or":[
132
+ ["color","==","red"],
133
+ ["color","==","green"]
134
+ ]},
135
+ ["size","==","large"]
136
+ ]}
137
+ }
138
+
139
+
140
+ To xml:
141
+
142
+ require "predicated/to/xml"
143
+ include Predicated
144
+
145
+ Predicate{And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))}.to_xml ==
146
+ %{
147
+ <and>
148
+ <or>
149
+ <equal><left>color</left><right>red</right></equal>
150
+ <equal><left>color</left><right>green</right></equal>
151
+ </or>
152
+ <equal><left>size</left><right>large</right></equal>
153
+ </and>
154
+ }
155
+
156
+
157
+ To arel (sql where clause):
158
+
159
+ require "predicated/to/arel"
160
+ include Predicated
161
+
162
+ Predicate{And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))}.to_arel(Table(:shirt)).to_sql ==
163
+ %{(("shirt"."color" = 'red' OR "shirt"."color" = 'green') AND "shirt"."size" = 'large')}
164
+
165
+
166
+ To solr query string:
167
+
168
+ require "predicated/to/solr"
169
+ include Predicated
170
+
171
+ Predicate{And(Or(Eq('color','red'),Eq('color','green')),Eq('size','large'))}.to_solr ==
172
+ "((color:red OR color:green) AND size:large)"
173
+
174
+
175
+ To sentence:
176
+
177
+ require "predicated/to/sentence"
178
+ include Predicated
179
+
180
+ Predicate{ And(Eq("a",1),Eq("b",2)) }.to_sentence ==
181
+ "'a' is equal to 1 and 'b' is equal to 2"
182
+
183
+ Predicate{ Gt("a",1) }.to_negative_sentence ==
184
+ "'a' is not greater than 1"
185
+
186
+
187
+ ## Testing Notes ##
188
+
189
+ Right now this project makes use of Wrong for assertions. Wrong uses this project. It's kind of neat in an eat-your-own-dogfood sense, but it's possible that this will be problematic over time (particularly when changes in this project cause assertions to behave differently - if even temporarily).
190
+
191
+ A middle ground is to make "from ruby string" and "from callable object" use minitest asserts, since these are the "interesting" parts of Predicated relied on by Wrong.
@@ -0,0 +1,51 @@
1
+ require "rubygems"
2
+ require "bundler"
3
+ Bundler.setup
4
+
5
+ def gemspec
6
+ @gemspec ||= begin
7
+ gemspec_file = File.expand_path('../predicated.gemspec', __FILE__)
8
+ gemspec = eval(File.read(gemspec_file), binding, gemspec_file)
9
+ end
10
+ end
11
+
12
+ task :default => :test
13
+
14
+ desc 'run all tests'
15
+ task :test do
16
+ sh %{ruby test/suite.rb}
17
+ end
18
+
19
+ desc "Build pkg/#{gemspec.full_name}.gem"
20
+ task :build => "gemspec:validate" do
21
+ sh %{gem build predicated.gemspec}
22
+ FileUtils.mkdir_p "pkg"
23
+ FileUtils.mv gemspec.file_name, "pkg"
24
+ end
25
+
26
+ desc "Install the latest built gem"
27
+ task :install => :build do
28
+ sh "gem install --local pkg/#{gemspec.file_name}"
29
+ end
30
+
31
+ namespace :release do
32
+ task :tag do
33
+ release_tag = "v#{gemspec.version}"
34
+ sh "git tag -a #{release_tag} -m 'Tagging #{release_tag}'"
35
+ sh "git push origin #{release_tag}"
36
+ end
37
+
38
+ task :gem => :build do
39
+ sh "gem push pkg/#{gemspec.file_name}"
40
+ end
41
+ end
42
+
43
+ desc "Release the current branch to GitHub and Gemcutter"
44
+ task :release => %w(release:tag release:gem)
45
+
46
+ namespace :gemspec do
47
+ desc 'Validate the gemspec'
48
+ task :validate do
49
+ gemspec.validate
50
+ end
51
+ end