|
| 1 | +--- |
| 2 | +title: RSpec 3.3 has been released! |
| 3 | +author: Myron Marston |
| 4 | +--- |
| 5 | + |
| 6 | +RSpec 3.2 has just been released! Given our commitment to |
| 7 | +[semantic versioning](http://semver.org/), this should be a trivial |
| 8 | +upgrade for anyone already using RSpec 3.0, 3.1 or 3.2, but if we did introduce |
| 9 | +any regressions, please let us know, and we'll get a patch release |
| 10 | +out with a fix ASAP. |
| 11 | + |
| 12 | +RSpec continues to be a community-driven project with contributors |
| 13 | +from all over the world. This release includes 638 commits and 169 |
| 14 | +merged pull requests from over 40 different contributors! |
| 15 | + |
| 16 | +Thank you to everyone who helped make this release happen! |
| 17 | + |
| 18 | +## Notable Changes |
| 19 | + |
| 20 | +### Core: Unique IDs for every Example and Example Group |
| 21 | + |
| 22 | +Historically, RSpec examples have been identified primarily by _file |
| 23 | +location_. For example, this command: |
| 24 | + |
| 25 | +~~~ |
| 26 | +$ rspec spec/unit/baseball_spec.rb:23 |
| 27 | +~~~ |
| 28 | + |
| 29 | +...would run an example or example group defined on line 23 of |
| 30 | +`spec/unit/baseball_spec.rb`. Location-based identification generally |
| 31 | +works well, but does not always uniquely identity a particular example. |
| 32 | +For example, if you use shared examples, your spec suite may |
| 33 | +have multiple copies of the example defined at |
| 34 | +`spec/support/shared_examples.rb:47`. |
| 35 | + |
| 36 | +RSpec 3.3 introduces a new way to identify examples and example groups: |
| 37 | +unique IDs. The IDs are scoped to a particular file and are based on the |
| 38 | +index of the example or group. For example, this command: |
| 39 | + |
| 40 | +~~~ |
| 41 | +$ rspec spec/unit/baseball_spec.rb[1:2,1:4] |
| 42 | +~~~ |
| 43 | + |
| 44 | +...would run the 2nd and 4th example or group defined under the 1st |
| 45 | +top-level group defined in `spec/unit/baseball_spec.rb`. |
| 46 | + |
| 47 | +For the most part, the new example IDs are primarily used internally by |
| 48 | +RSpec to support some of the new 3.3 features, but you're free to use |
| 49 | +them from the command line, and the re-run command printed by RSpec for |
| 50 | +each failure will use them if the file location does not uniquely |
| 51 | +identify the failed example. Copying and pasting the re-run command |
| 52 | +for a particular failed example will always run just that example now! |
| 53 | + |
| 54 | +### Core: New `--only-failures` option |
| 55 | + |
| 56 | +Now that RSpec has a robust way to uniquely identify every example, we've |
| 57 | +added new filtering capabilities to allow you to run only the failures. To |
| 58 | +enable this feature, you first have to configure RSpec so it knows where |
| 59 | +to persist the status of each example: |
| 60 | + |
| 61 | +~~~ ruby |
| 62 | +RSpec.configure do |c| |
| 63 | + c.example_status_persistence_file_path = "./spec/examples.txt" |
| 64 | +end |
| 65 | +~~~ |
| 66 | + |
| 67 | +Once you've configured that, RSpec will begin persisting the status of each |
| 68 | +example after every run of your suite. You'll probably want to add this file |
| 69 | +to `.gitignore` (or whatever the equivalent for your source control system is), |
| 70 | +as it's not intended to be kept under source control. With that configuration |
| 71 | +in place, you can use the new CLI option: |
| 72 | + |
| 73 | +~~~ |
| 74 | +$ rspec --only-failures |
| 75 | +# or apply it to a specific file or directory: |
| 76 | +$ rspec spec/unit --only-failures |
| 77 | +~~~ |
| 78 | + |
| 79 | +It's worth noting that this option filters to the examples that failed |
| 80 | +the last time they ran, not just to the failures from the last run of |
| 81 | +`rspec`. That means, for example, that if there's a slow acceptance spec |
| 82 | +that you don't generally run locally (leaving it to your CI server to |
| 83 | +run it), and it failed the last time it ran locally, even if it was weeks ago, |
| 84 | +it'll be included when you run `rspec --only-failures`. |
| 85 | + |
| 86 | +See our [relish |
| 87 | +docs (TODO)](https://relishapp.com/rspec-staging/rspec-core/docs/command-line/only-failures) |
| 88 | +for an end-to-end example of this feature. |
| 89 | + |
| 90 | +### Core: New `--next-failure` option |
| 91 | + |
| 92 | +When making a change that causes many failures across my spec suite---such |
| 93 | +as renaming a commonly used method---I've often used a specific work flow: |
| 94 | + |
| 95 | +1. Run the entire suite to get the failure list. |
| 96 | +2. Run each failure individually in sequence using the re-run command |
| 97 | + that RSpec printed, fixing each example before moving on to the next failure. |
| 98 | + |
| 99 | +This allows me to systematically work through all of the failures, |
| 100 | +without paying the cost of repeatedly running the entire suite. RSpec |
| 101 | +3.3 includes a new option that vastly simplifies this work flow: |
| 102 | + |
| 103 | +~~~ |
| 104 | +rspec --next-failure |
| 105 | +# or apply it to a specific file or directory: |
| 106 | +$ rspec spec/unit --next-failure |
| 107 | +~~~ |
| 108 | + |
| 109 | +This option is the equivalent of `--only-failures --fail-fast --order defined`. |
| 110 | +It filters to only failures, and will abort as soon as one fails. It |
| 111 | +applies `--order defined` in order to ensure that you keep getting the same |
| 112 | +failing example when you run it multiple times in a row without fixing |
| 113 | +the example. |
| 114 | + |
| 115 | +### Core: Stable Random Ordering |
| 116 | + |
| 117 | +RSpec's random ordering has always allowed you to pass a particular |
| 118 | +`--seed` to run the suite in the same order as a prior run. However, |
| 119 | +this only worked if you ran the same set of examples as the original |
| 120 | +run. If you apply the seed to a subset of examples, their ordering |
| 121 | +wouldn't necessarily be consistent relative to each other. This is |
| 122 | +a consequence of how `Array#shuffle` works: `%w[ a b c d ].shuffle` may |
| 123 | +order `c` before `b`, but `%w[ b c d ].shuffle` may order `c` _after_ |
| 124 | +`b` even if you use the same random seed. |
| 125 | + |
| 126 | +This may not seem like a big deal, but it makes `--seed` far less |
| 127 | +useful. When you are trying to track down the source of an ordering |
| 128 | +dependency, you have to keep running the entire suite to reproduce |
| 129 | +the failure. |
| 130 | + |
| 131 | +RSpec 3.3 addresses this. We no longer use `shuffle` for random |
| 132 | +ordering. Instead, we combine the `--seed` value with the id of each |
| 133 | +example, hash it, and sort by the produced values. This ensures that |
| 134 | +if a particular seed orders example `c` before example `b`, `c` will |
| 135 | +always come before `b` when you re-use that seed no matter what subset |
| 136 | +of the suite you are running. |
| 137 | + |
| 138 | +While stable random ordering is useful in its own right, the big win |
| 139 | +here is a new feature that it enables: bisect. |
| 140 | + |
| 141 | +### Core: Bisect |
| 142 | + |
| 143 | +RSpec has supported random ordering (with a `--seed` option to reproduce |
| 144 | +a particular ordering) since RSpec 2.8. These features help surface |
| 145 | +ordering dependencies between specs, which you'll want to quickly |
| 146 | +isolate and fix. |
| 147 | + |
| 148 | +Unfortunately, RSpec provided little to help with isolating |
| 149 | +an ordering dependency. That's changing in RSpec 3.3. We now provide |
| 150 | +a `--bisect` option that narrows an ordering dependency down to a |
| 151 | +minimal reproduction case. The new bisect flag repeatedly runs subsets |
| 152 | +of your suite in order to isolate the minimal set of examples that |
| 153 | +reproduce the same failures when you run your whole suite. |
| 154 | + |
| 155 | +Stable random ordering makes it possible for you to run various subsets |
| 156 | +of the suite to try to narrow an ordering dependency down to a minimal |
| 157 | +reproduction case. |
| 158 | + |
| 159 | +See our [relish |
| 160 | +docs (TODO)](https://relishapp.com/rspec-staging/rspec-core/docs/command-line/bisect) |
| 161 | +for an end-to-end example of this feature. |
| 162 | + |
| 163 | +### Core: Thread Safe `let` and `subject` |
| 164 | + |
| 165 | +Historically, `let` and `subject` have [never been |
| 166 | +thread safe](http://rspec.info/documentation/3.2/rspec-core/RSpec/Core/MemoizedHelpers/ClassMethods.html#let-instance_method). |
| 167 | +That's changing in RSpec 3.3, thanks to the [great |
| 168 | +work](https://github.com/rspec/rspec-core/pull/1858) of Josh Cheek. |
| 169 | + |
| 170 | +Note that the thread safety synchronization does add a bit of overhead, |
| 171 | +as you'd expect. If you're not spinning up any threads in your examples |
| 172 | +and want to avoid that overhead, you can configure RSpec to |
| 173 | +[disable](TODO) the thread safety. |
| 174 | + |
| 175 | +### Expectations: New `aggregrate_failures` API |
| 176 | + |
| 177 | +### Expectation: Improved Failure Output |
| 178 | + |
| 179 | +### Mocks: Improved Failure Output |
| 180 | + |
| 181 | +### Mocks: Stubbing `MyClass.new` Verifies Against `MyClass#initialize` |
| 182 | + |
| 183 | +### Rails: ? |
| 184 | + |
| 185 | +## Stats |
| 186 | + |
| 187 | +### Combined: |
| 188 | + |
| 189 | +* **Total Commits**: 638 |
| 190 | +* **Merged pull requests**: 169 |
| 191 | +* **44 contributors**: Aaron Kromer, Alex Kwiatkowski, Andrey Botalov, Anton Davydov, Ben Axnick, Benjamin Fleischer, Bradley Schaefer, ChrisArcand, David Daniell, Eugene Kenny, Fabian Wiesel, Fabien Schurter, Fabio Napoleoni, Gabe Martin-Dempesy, Gavin Miller, Igor Zubkov, Jared Beck, Jean van der Walt, Joe Grossberg, Johannes Gorset, John Ceh, Jon Rowe, Josh Cheek, Leo Arnold, Lucas Mazza, Mark Swinson, Melissa Xie, Myron Marston, Nicholas Chmielewski, Nicholas Henry, Orien Madgwick, Pavel Shpak, Raymond Sanchez, Ryan Mulligan, Ryan Ong, Sam Phippen, Samnang Chhun, Samuel Esposito, Siva Gollapalli, Tim Wade, Tony Ta, Vít Ondruch, charlierudolph, raymond sanchez |
| 192 | + |
| 193 | +### rspec-core: |
| 194 | + |
| 195 | +* **Total Commits**: 264 |
| 196 | +* **Merged pull requests**: 55 |
| 197 | +* **16 contributors**: Alex Kwiatkowski, Ben Axnick, Benjamin Fleischer, Eugene Kenny, Fabien Schurter, Fabio Napoleoni, Jon Rowe, Josh Cheek, Leo Arnold, Mark Swinson, Melissa Xie, Myron Marston, Raymond Sanchez, Ryan Ong, Samuel Esposito, raymond sanchez |
| 198 | + |
| 199 | +### rspec-expectations: |
| 200 | + |
| 201 | +* **Total Commits**: 129 |
| 202 | +* **Merged pull requests**: 33 |
| 203 | +* **10 contributors**: Andrey Botalov, ChrisArcand, Fabien Schurter, Gavin Miller, Jared Beck, Jon Rowe, Myron Marston, Ryan Mulligan, Tim Wade, charlierudolph |
| 204 | + |
| 205 | +### rspec-mocks: |
| 206 | + |
| 207 | +* **Total Commits**: 107 |
| 208 | +* **Merged pull requests**: 32 |
| 209 | +* **11 contributors**: Bradley Schaefer, Fabien Schurter, John Ceh, Jon Rowe, Myron Marston, Nicholas Henry, Pavel Shpak, Sam Phippen, Samnang Chhun, Siva Gollapalli, Tim Wade |
| 210 | + |
| 211 | +### rspec-rails: |
| 212 | + |
| 213 | +* **Total Commits**: 63 |
| 214 | +* **Merged pull requests**: 20 |
| 215 | +* **14 contributors**: Aaron Kromer, Anton Davydov, David Daniell, Gabe Martin-Dempesy, Igor Zubkov, Jean van der Walt, Joe Grossberg, Johannes Gorset, Jon Rowe, Lucas Mazza, Myron Marston, Orien Madgwick, Tony Ta, Vít Ondruch |
| 216 | + |
| 217 | +### rspec-support: |
| 218 | + |
| 219 | +* **Total Commits**: 75 |
| 220 | +* **Merged pull requests**: 29 |
| 221 | +* **7 contributors**: Benjamin Fleischer, Fabian Wiesel, Gavin Miller, Jon Rowe, Myron Marston, Nicholas Chmielewski, Siva Gollapalli |
| 222 | + |
| 223 | +## Docs |
| 224 | + |
| 225 | +### API Docs |
| 226 | + |
| 227 | +* [rspec-core](/documentation/3.2/rspec-core/) |
| 228 | +* [rspec-expectations](/documentation/3.2/rspec-expectations/) |
| 229 | +* [rspec-mocks](/documentation/3.2/rspec-mocks/) |
| 230 | +* [rspec-rails](/documentation/3.2/rspec-rails/) |
| 231 | + |
| 232 | +### Cucumber Features |
| 233 | + |
| 234 | +* [rspec-core](http://relishapp.com/rspec/rspec-core) |
| 235 | +* [rspec-expectations](http://relishapp.com/rspec/rspec-expectations) |
| 236 | +* [rspec-mocks](http://relishapp.com/rspec/rspec-mocks) |
| 237 | +* [rspec-rails](http://relishapp.com/rspec/rspec-rails) |
| 238 | + |
| 239 | +## Release Notes |
| 240 | + |
| 241 | +TODO |
0 commit comments