riot 0.12.5 → 0.12.6
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.
- data/.gitignore +2 -0
- data/.travis.yml +10 -0
- data/CHANGELOG +286 -245
- data/Gemfile +4 -0
- data/README.markdown +284 -217
- data/lib/riot/context.rb +14 -3
- data/lib/riot/message.rb +1 -1
- data/lib/riot/middleware.rb +20 -20
- data/lib/riot/reporter.rb +5 -4
- data/lib/riot/reporter/io.rb +6 -14
- data/lib/riot/reporter/pretty_dot_matrix.rb +0 -1
- data/lib/riot/rr.rb +5 -0
- data/lib/riot/runnable.rb +2 -0
- data/lib/riot/situation.rb +1 -1
- data/lib/riot/version.rb +1 -1
- data/test/core/assertion_macros/raises_kind_of_test.rb +1 -1
- data/test/core/assertion_macros/raises_test.rb +1 -1
- data/test/core/middleware/context_middleware_test.rb +20 -0
- data/test/core/reports/basic_reporter_test.rb +6 -0
- data/test/core/reports/dot_matrix_reporter_test.rb +7 -1
- data/test/core/reports/story_reporter_test.rb +4 -6
- data/test/core/runnable/erroring_gracefully_test.rb +47 -0
- data/test/teststrap.rb +3 -1
- metadata +40 -39
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.markdown
    CHANGED
    
    | @@ -8,16 +8,18 @@ A fast, expressive, and contextual ruby unit testing framework. Protest the slow | |
| 8 8 |  | 
| 9 9 | 
             
            ## Usage
         | 
| 10 10 |  | 
| 11 | 
            +
            [](http://travis-ci.org/thumblemonks/riot)
         | 
| 12 | 
            +
             | 
| 11 13 | 
             
            In contrast to other popular Ruby testing frameworks such as Test::Unit, [Shoulda](http://github.com/thoughtbot/shoulda) and [RSpec](http://rspec.info/), Riot does not run a `setup` and `teardown` sequence before and after each test. This speeds up test execution quite a bit, but also changes how you write your tests. In general and in my opinion, you should avoid mutating any objects under test and if you use Riot you're pretty much going to have to.
         | 
| 12 14 |  | 
| 13 15 | 
             
            In Riot, tests reside in `contexts`. Within these, a `topic` object is defined through a `setup` block. The actual assertions are then made with an `asserts` or `denies` block.
         | 
| 14 16 |  | 
| 15 17 | 
             
            ```ruby
         | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 18 | 
            +
            context "An empty Array" do
         | 
| 19 | 
            +
              setup { Array.new }
         | 
| 20 | 
            +
              asserts("it is empty") { topic.empty? }
         | 
| 21 | 
            +
              denies("it has any elements") { topic.any? }
         | 
| 22 | 
            +
            end # An Array
         | 
| 21 23 | 
             
            ```
         | 
| 22 24 |  | 
| 23 25 | 
             
            As you can see, the setup block doesn't use any instance variables to save the object under test — rather, the return value of the block is used as the `topic`. This object can then be accessed in the assertions using the `topic` attribute. Furthermore, at their very basic level, assertions need only return a boolean. When using `asserts`, `true` indicates a pass while `false` indicates a fail; subsequently, when using `denies`, `true` indicates a failure whereas `false` indicates success.
         | 
| @@ -25,22 +27,22 @@ As you can see, the setup block doesn't use any instance variables to save the o | |
| 25 27 | 
             
            Of course, you can nest contexts as well; the `setup` blocks are executed outside-in; as in, the parents' setups are run before the current context allowing for a setup hierarchy. `teardown` blocks are run inside out; the current context's teardowns are run before any of its parents'. This is what you would expect from other frameworks as well.
         | 
| 26 28 |  | 
| 27 29 | 
             
            ```ruby
         | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            +
            context "An Array" do
         | 
| 31 | 
            +
              setup { Array.new }
         | 
| 30 32 |  | 
| 31 | 
            -
             | 
| 33 | 
            +
              asserts("is empty") { topic.empty? }
         | 
| 32 34 |  | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 35 | 
            +
              context "with one element" do
         | 
| 36 | 
            +
                setup { topic << "foo" }
         | 
| 37 | 
            +
                asserts("array is not empty") { !topic.empty? }
         | 
| 38 | 
            +
                asserts("returns the element on #first") { topic.first == "foo" }
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end # An Array
         | 
| 39 41 | 
             
            ```
         | 
| 40 42 |  | 
| 41 43 | 
             
            By the way, you can put any kind of ruby object in your context description. Riot will call `to_s` on the actual value before it is used in a reporting context. This fact will become [useful later](http://thumblemonks.github.com/riot/hacking.html#context-middleware) ;)
         | 
| 42 44 |  | 
| 43 | 
            -
             | 
| 45 | 
            +
            ## Assertions
         | 
| 44 46 |  | 
| 45 47 | 
             
            Well, how useful would Riot be if you could only return true/false from an assertion? Pretty useful, actually; but, we can make it more useful! No; that's not crazy. No it isn't. Yes; I'm sure.
         | 
| 46 48 |  | 
| @@ -49,11 +51,11 @@ We can do this with assertion macros. You can think of these as special assertio | |
| 49 51 | 
             
            Let's take this little for instance:
         | 
| 50 52 |  | 
| 51 53 | 
             
            ```ruby
         | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            +
            context "Yummy things" do
         | 
| 55 | 
            +
              setup { ["cookies", "donuts"] }
         | 
| 54 56 |  | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            +
              asserts("#first") { topic.first }.equals("cookies")
         | 
| 58 | 
            +
            end # Yummy things
         | 
| 57 59 | 
             
            ```
         | 
| 58 60 |  | 
| 59 61 | 
             
            First, how's that for a readable test? Second, you should notice that the assertion block will return the `first` item from the `topic` (which is assumed to be `Enumerable` in this case); if it isn't `Enumerable`, then you have other problems. Since the first element in the array is "cookies", the assertion will pass. Yay!
         | 
| @@ -61,205 +63,266 @@ First, how's that for a readable test? Second, you should notice that the assert | |
| 61 63 | 
             
            But wait, there's more. Riot is about helping you write faster and more readable tests. Notice any duplication in the example above (besides the value "cookies")? I do. How about that `first` notation in the assertion name and reference in the assertion block. Riot provides a shortcut which allows you to reference methods on the topic through the assertion name. Here's another way to write the same test:
         | 
| 62 64 |  | 
| 63 65 | 
             
            ```ruby
         | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            +
            context "Yummy things" do
         | 
| 67 | 
            +
              setup { ["cookies", "donuts"] }
         | 
| 66 68 |  | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            +
              asserts(:first).equals("cookies")
         | 
| 70 | 
            +
            end # Yummy things
         | 
| 69 71 | 
             
            ```
         | 
| 70 72 |  | 
| 71 73 | 
             
            Now that's real yummy. Want some more? Perhaps you just want to test the topic itself — not a method or attribute of it. You could do this:
         | 
| 72 74 |  | 
| 73 75 | 
             
            ```ruby
         | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            +
            context "Yummy things" do
         | 
| 77 | 
            +
              setup { ["cookies", "donuts"] }
         | 
| 76 78 |  | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            +
              asserts("topic") { topic }.size(2)
         | 
| 80 | 
            +
            end # Yummy things
         | 
| 79 81 | 
             
            ```
         | 
| 80 82 |  | 
| 81 83 | 
             
            But, as you can probably already guess, that's gross and redundant. To solve this, Riot provides the `asserts_topic` shortcut which is a helper that pretty much just does `asserts("topic") { topic }` for you.
         | 
| 82 84 |  | 
| 83 85 | 
             
            ```ruby
         | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            +
            context "Yummy things" do
         | 
| 87 | 
            +
              setup { ["cookies", "donuts"] }
         | 
| 86 88 |  | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            +
              asserts_topic.size(2)
         | 
| 90 | 
            +
            end # Yummy things
         | 
| 89 91 | 
             
            ```
         | 
| 90 92 |  | 
| 91 93 | 
             
            Yep, more readable.
         | 
| 92 94 |  | 
| 93 | 
            -
             | 
| 95 | 
            +
            ### Negative Assertions
         | 
| 94 96 |  | 
| 95 97 | 
             
            Way back in the first code example we saw a reference to `denies`; this is what is called the negative assertion. You could probably also call it a counter assertion, but I don't. You can use `denies` with any assertion macro that you can use `asserts` with; it's just that `denies` expects the assertion to fail for the test to pass. For instance:
         | 
| 96 98 |  | 
| 97 99 | 
             
            ```ruby
         | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 100 | 
            +
            context "My wallet" do
         | 
| 101 | 
            +
              setup do
         | 
| 102 | 
            +
                Wallet.new(1000) # That's 1000 cents, or $10USD yo
         | 
| 103 | 
            +
              end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
              asserts(:enough_for_lunch?)
         | 
| 106 | 
            +
              denies(:enough_for_lunch?)
         | 
| 107 | 
            +
            end # My wallet
         | 
| 106 108 | 
             
            ```
         | 
| 107 109 |  | 
| 108 110 | 
             
            One of those will pass and the other will fail. If $10 is not enough for lunch the `denies` statement will pass; and then you should move to Chicago where it is enough (if only barely).
         | 
| 109 111 |  | 
| 110 | 
            -
             | 
| 112 | 
            +
            ### Built-in Assertion Macros
         | 
| 111 113 |  | 
| 112 114 | 
             
            There are a bunch of built-in assertion macros for your everyday use. Be sure to [write your own](http://thumblemonks.github.com/riot/hacking.html#writing-assertion-macros) if these don't satisfy your every need. You will notice the two varying mechanisms for passing arguments into the macros: one is the conventional form of message passing (via actual arguments) and the other is derived from a provided block. If the macro expects one argument, you can use either form (but not both). If the macro accepts multiple arguments, the last argument you want to pass in can be provided via the block.
         | 
| 113 115 |  | 
| 114 116 | 
             
            The advantage of using the block is that its innards are evaluated against the same scope that the assertion was evaluated against. This means you can use the same helpers and instance variables in the macro block to generate an expected value (if you so desire). It's also useful if you have a fairly complex routine for generating the expected value.
         | 
| 115 117 |  | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 161 | 
            -
             | 
| 162 | 
            -
             | 
| 163 | 
            -
             | 
| 164 | 
            -
             | 
| 165 | 
            -
             | 
| 166 | 
            -
             | 
| 167 | 
            -
             | 
| 168 | 
            -
             | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
             | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 118 | 
            +
            #### Equals
         | 
| 119 | 
            +
             | 
| 120 | 
            +
            Compares equality of the actual value to the expected value using the `==` operator 
         | 
| 121 | 
            +
             | 
| 122 | 
            +
            ```ruby
         | 
| 123 | 
            +
            asserts.equals(Object)
         | 
| 124 | 
            +
            denies.equals(Object)
         | 
| 125 | 
            +
            asserts.equals { Object }
         | 
| 126 | 
            +
            denies.equals { Object }
         | 
| 127 | 
            +
            ```
         | 
| 128 | 
            +
             | 
| 129 | 
            +
            #### Equivalent To
         | 
| 130 | 
            +
             | 
| 131 | 
            +
            Compares equivalence of actual value to the expected value using the `===` operator
         | 
| 132 | 
            +
             | 
| 133 | 
            +
            ```ruby
         | 
| 134 | 
            +
            asserts.equivalent_to(Object)
         | 
| 135 | 
            +
            denies.equivalent_to(Object)
         | 
| 136 | 
            +
            asserts.equivalent_to { Object }
         | 
| 137 | 
            +
            denies.equivalent_to { Object }
         | 
| 138 | 
            +
            ```
         | 
| 139 | 
            +
             | 
| 140 | 
            +
            #### Assigns
         | 
| 141 | 
            +
             | 
| 142 | 
            +
            Checks that the actual value has an instance variable defined within it's scope. You can also validate the value of that variable. Very much mimicing the `assigns` found in Rails-ish tests from way back in form, function, and need.
         | 
| 143 | 
            +
             | 
| 144 | 
            +
            ```ruby
         | 
| 145 | 
            +
            asserts("a person") { Person.new }.assigns(:email)
         | 
| 146 | 
            +
            denies("a person") { Person.new }.assigns(:email)
         | 
| 147 | 
            +
            asserts("a person") { Person.new(:email => "a@b.com") }.assigns(:email, "a@b.com")
         | 
| 148 | 
            +
            denies("a person") { Person.new(:email => "a@b.com") }.assigns(:email, "a@b.com")
         | 
| 149 | 
            +
            asserts.assigns { :email }
         | 
| 150 | 
            +
            denies.assigns { :email }
         | 
| 151 | 
            +
            asserts.assigns(:email) { "a@b.com" }
         | 
| 152 | 
            +
            denies.assigns(:email) { "a@b.com" }
         | 
| 153 | 
            +
            ```
         | 
| 154 | 
            +
             | 
| 155 | 
            +
            #### Nil
         | 
| 156 | 
            +
             | 
| 157 | 
            +
            Simply checks the actual value for its nil-ness. Expects no arguments.
         | 
| 158 | 
            +
             | 
| 159 | 
            +
            ```ruby
         | 
| 160 | 
            +
            asserts.nil
         | 
| 161 | 
            +
            denies.nil
         | 
| 162 | 
            +
            ```
         | 
| 163 | 
            +
             | 
| 164 | 
            +
            #### Matches
         | 
| 165 | 
            +
             | 
| 166 | 
            +
            Compares the actual value to a provided regular expression
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            ```ruby
         | 
| 169 | 
            +
            asserts.matches(%r{Regex})
         | 
| 170 | 
            +
            denies.matches(%r{Regex})
         | 
| 171 | 
            +
            asserts.matches { /Regex/ }
         | 
| 172 | 
            +
            denies.matches { /Regex/ }
         | 
| 173 | 
            +
            ```
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            #### Raises
         | 
| 176 | 
            +
             | 
| 177 | 
            +
            Validates the type of exception raised from the assertion block. Optionally, you can give it the message you expected in the form of a literal string or even a portion of it.
         | 
| 178 | 
            +
             | 
| 179 | 
            +
            ```ruby
         | 
| 180 | 
            +
            asserts.raises(ExceptionClass)
         | 
| 181 | 
            +
            denies.raises(ExceptionClass)
         | 
| 182 | 
            +
            asserts.raises(ExceptionClass, "Expected message")
         | 
| 183 | 
            +
            denies.raises(ExceptionClass, "Expected message")
         | 
| 184 | 
            +
            asserts.raises(ExceptionClass) { "ted mess" }
         | 
| 185 | 
            +
            denies.raises(ExceptionClass) { "ted mess" }
         | 
| 186 | 
            +
            ```
         | 
| 187 | 
            +
             | 
| 188 | 
            +
            #### Kind Of
         | 
| 189 | 
            +
             | 
| 190 | 
            +
            Validates the type of object returned from the assertion block
         | 
| 191 | 
            +
             | 
| 192 | 
            +
            ```ruby
         | 
| 193 | 
            +
            asserts.kind_of(Class)
         | 
| 194 | 
            +
            denies.kind_of(Class)
         | 
| 195 | 
            +
            asserts.kind_of { Class }
         | 
| 196 | 
            +
            denies.kind_of { Class }
         | 
| 197 | 
            +
            ```
         | 
| 198 | 
            +
             | 
| 199 | 
            +
            #### Responds To
         | 
| 200 | 
            +
             | 
| 201 | 
            +
            Checks that the actual object `respond_to?` to a particular message
         | 
| 202 | 
            +
             | 
| 203 | 
            +
            ```ruby
         | 
| 204 | 
            +
            asserts.respond_to(:foo)
         | 
| 205 | 
            +
            denies.respond_to(:foo)
         | 
| 206 | 
            +
            asserts.respond_to { "foo" }
         | 
| 207 | 
            +
            denies.respond_to { "foo" }
         | 
| 208 | 
            +
            asserts.responds_to("foo")
         | 
| 209 | 
            +
            denies.responds_to("foo")
         | 
| 210 | 
            +
            asserts.responds_to { :foo }
         | 
| 211 | 
            +
            denies.responds_to { :foo }
         | 
| 212 | 
            +
            ```
         | 
| 213 | 
            +
             | 
| 214 | 
            +
            #### Includes
         | 
| 215 | 
            +
             | 
| 216 | 
            +
            Checks for the existence of: a character or sequence of characters in a string, an element in an array, or a key in a hash.
         | 
| 217 | 
            +
             | 
| 218 | 
            +
            ```ruby
         | 
| 219 | 
            +
            asserts("this string") { "barbie q" }.includes("foo")
         | 
| 220 | 
            +
            denies("this string") { "barbie q" }.includes("foo")
         | 
| 221 | 
            +
            asserts("this array") { [1,2,3] }.includes(2)
         | 
| 222 | 
            +
            denies("this array") { [1,2,3] }.includes(2)
         | 
| 223 | 
            +
            asserts("this hash") { {:key1 => "foo"} }.includes(:key2)
         | 
| 224 | 
            +
            denies("this hash") { {:key1 => "foo"} }.includes(:key2)
         | 
| 225 | 
            +
            asserts.includes { "foo" }
         | 
| 226 | 
            +
            denies.includes { "foo" }
         | 
| 227 | 
            +
            asserts.includes { 2 }
         | 
| 228 | 
            +
            denies.includes { 2 }
         | 
| 229 | 
            +
            asserts.includes { :key }
         | 
| 230 | 
            +
            denies.includes { :key }
         | 
| 231 | 
            +
            ```
         | 
| 232 | 
            +
             | 
| 233 | 
            +
            #### Size
         | 
| 234 | 
            +
             | 
| 235 | 
            +
            Compares the size of the actual object to the number you provide. Works with anything that responds to `size(Numeric)` (strings, arrays, hashes, etc).
         | 
| 236 | 
            +
             | 
| 237 | 
            +
            ```ruby
         | 
| 238 | 
            +
            asserts.size(Numeric)
         | 
| 239 | 
            +
            denies.size(Numeric)
         | 
| 240 | 
            +
            asserts.size { Numeric }
         | 
| 241 | 
            +
            denies.size { Numeric }
         | 
| 242 | 
            +
            ```
         | 
| 243 | 
            +
             | 
| 244 | 
            +
            #### Empty
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            Checks the result of calling `empty?` on the actual value. Expects no arguments.
         | 
| 247 | 
            +
             | 
| 248 | 
            +
            ```ruby
         | 
| 249 | 
            +
            asserts.empty
         | 
| 250 | 
            +
            denies.empty
         | 
| 251 | 
            +
            ```
         | 
| 252 | 
            +
             | 
| 253 | 
            +
            #### Same Elements
         | 
| 254 | 
            +
             | 
| 255 | 
            +
            Compares actual to expected to see if they contain the same elements. Uses `Set` under-the-hood, just so you know.
         | 
| 256 | 
            +
             | 
| 257 | 
            +
            ```ruby
         | 
| 258 | 
            +
            asserts.same_elements(Array)
         | 
| 259 | 
            +
            denies.same_elements(Array)
         | 
| 260 | 
            +
            asserts.same_elements { Array }
         | 
| 261 | 
            +
            denies.same_elements { Array }
         | 
| 262 | 
            +
            ```
         | 
| 263 | 
            +
             | 
| 264 | 
            +
            ### Setups, Hookups, and Helpers
         | 
| 204 265 |  | 
| 205 266 | 
             
            We're not even close to done yet; there's a lot more cool stuff for you to know about. You know about `setup` already; but you may not know that you can call `setup` multiple times within a Context. Well, you can. They run in the order you write them (top-down) and the result of a prior `setup` will be the `topic` for the next setup. In this way you **could** chain together some partitioned setup criteria without ever explicitly setting a variable (instance or local).
         | 
| 206 267 |  | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 210 | 
            -
              
         | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 268 | 
            +
            ```ruby
         | 
| 269 | 
            +
            context "A cheesey order" do
         | 
| 270 | 
            +
              setup { Cheese.create!(:name => "Blue") }
         | 
| 271 | 
            +
              setup { Order.create!(:cheese => topic, :purchase_order => "123-abc") }
         | 
| 272 | 
            +
             | 
| 273 | 
            +
              asserts_topic.kind_of(Order) # I love tests that are readable
         | 
| 274 | 
            +
            end # A cheesey order
         | 
| 275 | 
            +
            ```
         | 
| 213 276 |  | 
| 214 277 | 
             
            This notion about a prior `setup` being the `topic` for a latter `setup` is true even when the `setup` is called from a parent Context.
         | 
| 215 278 |  | 
| 216 279 | 
             
            More than likely, however, you'll want to modify something about the topic without changing what the topic for the context is. To do this, Riot provides the `hookup` block, which is just like a `setup` block except that `hookup` will always return the `topic` that was provided to it. It's kind of like calling `Object#tap`. Here's a for-instance:
         | 
| 217 280 |  | 
| 218 281 | 
             
            ```ruby
         | 
| 219 | 
            -
             | 
| 220 | 
            -
             | 
| 282 | 
            +
            context "A Person" do
         | 
| 283 | 
            +
              setup { Person.new(:name => "Master Blasterr") }
         | 
| 221 284 |  | 
| 222 | 
            -
             | 
| 285 | 
            +
              denies(:valid?) # :(
         | 
| 223 286 |  | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 287 | 
            +
              context "with valid email" do
         | 
| 288 | 
            +
                hookup { topic.email = "master@blast.err" }
         | 
| 289 | 
            +
                asserts(:valid?) # Yay!
         | 
| 290 | 
            +
              end # with valid email
         | 
| 291 | 
            +
            end # A complex thing
         | 
| 229 292 | 
             
            ```
         | 
| 230 293 |  | 
| 231 294 | 
             
            If the point didn't smack you in the face there, think about using `setup` instead of `hookup` in the sub-context. Had you written that as a `setup` block, you'd have to return `topic` after setting the email address, or else the new topic would be the actual email address; and you probably don't want to actually be calling `"master@blast.err".valid?` in the assertion.
         | 
| 232 295 |  | 
| 233 296 | 
             
            You can also call `hookup` as many times as you like; the great part is that the `topic` never changes.
         | 
| 234 297 |  | 
| 235 | 
            -
            #### Helpers | 
| 298 | 
            +
            #### Helpers
         | 
| 236 299 |  | 
| 237 300 | 
             
            You remember how you used to — or currently do — create instance variables to hold some data that you're going to use in your tests? Well, Riot allows you to still do that yucky stuff, but would rather you use a helper to encapsulate it. For instance, you could do this:
         | 
| 238 301 |  | 
| 239 302 | 
             
            ```ruby
         | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 303 | 
            +
            context "A greedy monkey" do
         | 
| 304 | 
            +
              setup do
         | 
| 305 | 
            +
                @a_ripe_banana = Banana.new(:ripe => true)
         | 
| 306 | 
            +
                Monkey.new
         | 
| 307 | 
            +
              end
         | 
| 245 308 |  | 
| 246 | 
            -
             | 
| 309 | 
            +
              hookup { topic.takes(@a_ripe_banana) }
         | 
| 247 310 |  | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 311 | 
            +
              asserts(:bananas).size(1)
         | 
| 312 | 
            +
            end # A greedy monkey
         | 
| 250 313 | 
             
            ```
         | 
| 251 314 |  | 
| 252 315 | 
             
            Or, you could do this
         | 
| 253 316 |  | 
| 254 317 | 
             
            ```ruby
         | 
| 255 | 
            -
             | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 318 | 
            +
            context "A greedy monkey" do
         | 
| 319 | 
            +
              helper(:a_ripe_banana) { Banana.new(:ripe => true) }
         | 
| 320 | 
            +
              setup { Monkey.new }
         | 
| 258 321 |  | 
| 259 | 
            -
             | 
| 322 | 
            +
              hookup { topic.takes(a_ripe_banana) }
         | 
| 260 323 |  | 
| 261 | 
            -
             | 
| 262 | 
            -
             | 
| 324 | 
            +
              asserts(:bananas).size(1)
         | 
| 325 | 
            +
            end # A greedy monkey
         | 
| 263 326 | 
             
            ```
         | 
| 264 327 |  | 
| 265 328 | 
             
            "So! What's the difference?", you ask. Nothing really. It's all aesthetic; but, it's a better aesthetic for a couple of reasons. Let me tell you why:
         | 
| @@ -272,73 +335,75 @@ Or, you could do this | |
| 272 335 | 
             
            What's that about (4)? Yes, helpers are really just over-glorified methods, which means you can pass arguments to them. Which means you can build factories with them. Which means those factories can go away when the context is no longer used and they're no longer cluttering up your object space. You want another for instance, eh?
         | 
| 273 336 |  | 
| 274 337 | 
             
            ```ruby
         | 
| 275 | 
            -
             | 
| 276 | 
            -
             | 
| 277 | 
            -
             | 
| 278 | 
            -
             | 
| 279 | 
            -
             | 
| 280 | 
            -
             | 
| 281 | 
            -
             | 
| 282 | 
            -
             | 
| 283 | 
            -
             | 
| 284 | 
            -
             | 
| 285 | 
            -
             | 
| 286 | 
            -
             | 
| 287 | 
            -
             | 
| 288 | 
            -
             | 
| 289 | 
            -
             | 
| 290 | 
            -
             | 
| 338 | 
            +
            context "A greedy monkey" do
         | 
| 339 | 
            +
              helper(:make_a_banana) do |color|
         | 
| 340 | 
            +
                Banana.new(:color => color)
         | 
| 341 | 
            +
              end
         | 
| 342 | 
            +
             | 
| 343 | 
            +
              setup { Monkey.new }
         | 
| 344 | 
            +
             | 
| 345 | 
            +
              hookup do
         | 
| 346 | 
            +
                topic.takes(make_a_banana("green"))
         | 
| 347 | 
            +
                topic.takes(make_a_banana("blue"))
         | 
| 348 | 
            +
              end
         | 
| 349 | 
            +
             | 
| 350 | 
            +
              asserts(:bananas).size(2)
         | 
| 351 | 
            +
              asserts("green bananas") { topic.bananas.green }.size(1)
         | 
| 352 | 
            +
              asserts("blue bananas") { topic.bananas.blue }.size(1)
         | 
| 353 | 
            +
            end # A greedy monkey
         | 
| 291 354 | 
             
            ```
         | 
| 292 355 |  | 
| 293 356 | 
             
            Or you could `make_many_bananas` or whatever. There are also lots of clever ways to get helpers included into a context which you will hopefully see when you read up on Context Middleware and look through the Recipes. Riot Rails makes liberal use of helpers when [setting up a context](http://github.com/thumblemonks/riot-rails/master/lib/riot/action_controller/context_middleware.rb) to test controllers.
         | 
| 294 357 |  | 
| 295 358 | 
             
            Again, you define as many helpers as you like; you can also replace existing helpers by simply defining a helper with the same name (*that's because they're just methods defined within the context instance ... shhh*).
         | 
| 296 359 |  | 
| 297 | 
            -
            ### Running Riot | 
| 360 | 
            +
            ### Running Riot
         | 
| 298 361 |  | 
| 299 362 | 
             
            Running your Riot tests is pretty simple. You can put your test files wherever you want, but it's generally a good idea to put them in a "test" directory. You can run individual test files using the normal ruby command:
         | 
| 300 363 |  | 
| 301 | 
            -
             | 
| 302 | 
            -
             | 
| 303 | 
            -
             | 
| 304 | 
            -
             | 
| 364 | 
            +
            ```plain
         | 
| 365 | 
            +
            ruby test/units/monkey_test.rb
         | 
| 366 | 
            +
            # or
         | 
| 367 | 
            +
            ruby -Itest test/units/monkey_test.rb
         | 
| 368 | 
            +
            ```
         | 
| 305 369 |  | 
| 306 370 | 
             
            I like the latter and use it often. It means the test directory is loaded into the load path, which means I  don't have to be explicit about where to find my `teststrap.rb` file (which you might have named `test_helper.rb` in other projects even though it's a silly name). In your teststrap file you'll put all your common setup; maybe even including your Riot hacks. An out-of-the-box teststrap might look like this:
         | 
| 307 371 |  | 
| 308 372 | 
             
            ```ruby
         | 
| 309 | 
            -
             | 
| 310 | 
            -
             | 
| 311 | 
            -
             | 
| 373 | 
            +
            require 'rubygems'
         | 
| 374 | 
            +
            require '<my-library>'
         | 
| 375 | 
            +
            require 'riot'
         | 
| 312 376 | 
             
            ```
         | 
| 313 377 |  | 
| 314 378 | 
             
            Of course, you probably want to use rake to run your tests. Here's a basic Rakefile that will find our tests in the test directory or its subdirectories if the filename ends in `_test.rb`:
         | 
| 315 379 |  | 
| 316 380 | 
             
            ```ruby
         | 
| 317 | 
            -
             | 
| 381 | 
            +
            require 'rubygems'
         | 
| 318 382 |  | 
| 319 | 
            -
             | 
| 320 | 
            -
             | 
| 383 | 
            +
            require 'rake'
         | 
| 384 | 
            +
            require 'rake/testtask'
         | 
| 321 385 |  | 
| 322 | 
            -
             | 
| 323 | 
            -
             | 
| 324 | 
            -
             | 
| 325 | 
            -
             | 
| 326 | 
            -
             | 
| 327 | 
            -
             | 
| 328 | 
            -
             | 
| 329 | 
            -
             | 
| 386 | 
            +
            desc "Run all our tests"
         | 
| 387 | 
            +
            task :test do
         | 
| 388 | 
            +
              Rake::TestTask.new do |t|
         | 
| 389 | 
            +
                t.libs << "test"
         | 
| 390 | 
            +
                t.pattern = "test/**/*_test.rb"
         | 
| 391 | 
            +
                t.verbose = false
         | 
| 392 | 
            +
              end
         | 
| 393 | 
            +
            end
         | 
| 330 394 |  | 
| 331 | 
            -
             | 
| 395 | 
            +
            task :default => :test
         | 
| 332 396 | 
             
            ```
         | 
| 333 397 |  | 
| 334 398 | 
             
            And then on the command line you simply run:
         | 
| 335 399 |  | 
| 336 | 
            -
             | 
| 337 | 
            -
             | 
| 338 | 
            -
             | 
| 339 | 
            -
             | 
| 400 | 
            +
            ```plain
         | 
| 401 | 
            +
            rake
         | 
| 402 | 
            +
            # or
         | 
| 403 | 
            +
            rake test
         | 
| 404 | 
            +
            ```
         | 
| 340 405 |  | 
| 341 | 
            -
            ### Mocking | 
| 406 | 
            +
            ### Mocking
         | 
| 342 407 |  | 
| 343 408 | 
             
            Mocking seems to be all the rage this decade. I try very hard to avoid it altogether through judicious use of anonymous classes, but sometimes you just need to mock. For Riot, [RR](http://github.com/btakita/rr) seemed to fit the bill nicely because it's:
         | 
| 344 409 |  | 
| @@ -356,28 +421,28 @@ However, there are a number of things you expect from a test framework when mock | |
| 356 421 | 
             
            But enough of this hemming and hawing. What's it look like?! In your `teststrap.rb` you need to require in `riot/rr`:
         | 
| 357 422 |  | 
| 358 423 | 
             
            ```ruby
         | 
| 359 | 
            -
             | 
| 424 | 
            +
            # I'm teststrap.rb
         | 
| 360 425 |  | 
| 361 | 
            -
             | 
| 362 | 
            -
             | 
| 426 | 
            +
            require 'rubygems'
         | 
| 427 | 
            +
            require 'riot/rr'
         | 
| 363 428 | 
             
            ```
         | 
| 364 429 |  | 
| 365 430 | 
             
            Then, in your tests, you use standard RR syntax for all of your mocking needs:
         | 
| 366 431 |  | 
| 367 432 | 
             
            ```ruby
         | 
| 368 | 
            -
             | 
| 369 | 
            -
             | 
| 370 | 
            -
             | 
| 371 | 
            -
             | 
| 372 | 
            -
             | 
| 373 | 
            -
             | 
| 374 | 
            -
             | 
| 375 | 
            -
             | 
| 376 | 
            -
             | 
| 377 | 
            -
             | 
| 378 | 
            -
             | 
| 379 | 
            -
             | 
| 380 | 
            -
             | 
| 433 | 
            +
            require 'teststrap.rb'
         | 
| 434 | 
            +
             | 
| 435 | 
            +
            context "A nice Person" do
         | 
| 436 | 
            +
              setup do
         | 
| 437 | 
            +
                Nice::Person.new
         | 
| 438 | 
            +
              end
         | 
| 439 | 
            +
             | 
| 440 | 
            +
              should("find a nice thing to say") do
         | 
| 441 | 
            +
                mock(topic).make_network_request { "Nice haircut" }
         | 
| 442 | 
            +
                topic.say_something_nice
         | 
| 443 | 
            +
              end.equals("Nice haircut")
         | 
| 444 | 
            +
             | 
| 445 | 
            +
            end # A nice Person
         | 
| 381 446 | 
             
            ```
         | 
| 382 447 |  | 
| 383 448 | 
             
            So, if `#say_something_nice` never calls `#make_network_request`, that assertion will fail for that reason first. If it does call `#make_network_request`, but for some reason "Nice haircut" is not returned, the tests will fail for that reason instead. It's like catching two birds with one test.
         | 
| @@ -391,11 +456,13 @@ Riot is slowly solidifying its internal and external API. That being said, we wo | |
| 391 456 | 
             
            Source code is hosted on [GitHub](http://github.com), and can be fetched with
         | 
| 392 457 | 
             
            [Git](http://git-scm.com) by running:
         | 
| 393 458 |  | 
| 394 | 
            -
             | 
| 395 | 
            -
             | 
| 459 | 
            +
            ```plain
         | 
| 460 | 
            +
            git clone git://github.com/thumblemonks/riot.git
         | 
| 461 | 
            +
            ```
         | 
| 396 462 |  | 
| 397 463 | 
             
            If you want to make changes, please feel free to do so. The best process is to fork, fix, and send a pull request.
         | 
| 398 464 |  | 
| 399 465 | 
             
            ## License
         | 
| 400 466 |  | 
| 401 467 | 
             
            Riot is released under the MIT license. See [MIT LICENSE](https://github.com/thumblemonks/riot/blob/master/MIT-LICENSE). 
         | 
| 468 | 
            +
             |