I was just wondering how others organise large spec files (especially for models) with many contexts and sections organised in describe blocks for validations and other specs that can be grouped in some meaningful way.
Do you guys keep all the specs concerning a model in the same spec file for that model, or do you split into modules in a way or another?
I have never cared too much about this so far but I am wondering what others do, as there doesn't seem to be some sort of agreement around a best practice or such.
I've got some pretty large spec files for some models that I'd like to organise into smaller files, and there is little to no functionality shared across different models so I am not sure whether shared examples would be the way to go about this (regardless reusability) or whether there is some better way. Any suggestions?
Thanks in advance.
RSpec is a testing tool for Ruby, created for behavior-driven development (BDD). It is the most frequently used testing library for Ruby in production applications. Even though it has a very rich and powerful DSL (domain-specific language), at its core it is a simple tool which you can start using rather quickly.
RSpec is a unit test framework for the Ruby programming language. RSpec is different than traditional xUnit frameworks like JUnit because RSpec is a Behavior driven development tool.
The word it is another RSpec keyword which is used to define an “Example”. An example is basically a test or a test case. Again, like describe and context, it accepts both class name and string arguments and should be used with a block argument, designated with do/end.
Installing RSpecBoot up your terminal and punch in gem install rspec to install RSpec. Once that's done, you can verify your version of RSpec with rspec --version , which will output the current version of each of the packaged gems. Take a minute also to hit rspec --help and look through the various options available.
Nested contexts can help you here, but keep it shallow (typically one level deep). There are two variables to consider in each example: givens (starting state) and what method is being invoked. You can group things by method or state:
# by method describe Stack do describe "#push" do it "adds an element to an empty stack" it "adds an element to a non-empty stack" end describe "#pop" do it "returns nil from an empty stack" it "returns the last element of a non-empty stack" it "removes the last element from a non-empty stack" end end # by state describe Stack do context "when empty" do specify "push adds an element" specify "pop returns nil" end context "when not empty" do specify "push adds an element" specify "pop returns last element" specify "pop removes last element" end end
I've used both approaches and seen them both work really well and really badly. The key to either approach is that the examples tell a story as you read from top to bottom. As requirements evolve, this means you need to review this file, just as you do your implementation code. An easy way to check that the spec makes sense is to run it with the documentation formatter:
rspec stack_spec.rb --format documentation
This spits out all the names in order (provided you're not using --order rand):
Stack #push adds an element to an empty stack adds an element to a non-empty stack #pop returns nil from an empty stack returns the last element of a non-empty stack removes the last element from a non-empty stack
or
Stack when empty push adds an element pop returns nil when not empty push adds an element pop returns last element pop removes last element
Once you see this output, it'll be pretty clear to you whether the organization you're using makes sense or not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With