After reading up on rspec 2 and capybara 2 I'm slightly confused regarding best practices as far as structural directory layout is concerned. There seems to be some overlap between the various specs (such as request specs and controller specs for instance), and I was wondering what is the "best practice" way of organising these files, and what should each spec test?
What I've gathered so far (which may be wrong) is the following:
spec/factories
Factories used by Factory Girl (if used)
spec/features
Capybara tests, which emulate the interaction between a user and your application.
spec/models
Tests for model validation
spec/controllers
Testing controller actions (#new, #edit, #create etc.)
spec/requests
Tests for integration between various controllers (one level 'higher' than controller specs)
spec/support
Files which define modules that could be useful to include in some of the specs.
spec/acceptance
Acceptance tests.
spec/views
Tests concerned with whether views were rendered correctly
I personally feel that for instance spec/views seems unnecessary in the sense that the capybara tests also are concerned with views (and how they look) and controller tests could easily also test whether or not a certain view is rendered.
What are your thoughts?
from my point of view spec/acceptance and spec/features are the same.
spec/views is something completely different, as you can test specific views or partials in isolation. this is very helpful for complex views and you don't need to have any browser simulator.
in regards to capybara spec, i use a different approach that you can read about here: https://gist.github.com/phoet/6683280#file-readme-md
Related
While rspec automatically creates specs for any helpers created by the Rails generators, I was wondering if other Rails developers find it important/useful to spec the helpers in real-world or if they often don't bother, since the helpers are often tested by proxy through testing of the components that use them?
Personally I do test helper methods, because I like to test them in isolation. If the following feature specs fails I know I probably made a mistake in my test setup because I already ensured that the helper method works.
It is also easier to test all possible scenarios. If you want to test all possibilities as part of a whole you need more test setup and sacrifice performance.
Ideally, you want to write tests for everything, but in real world with time constraints, it is not uncommon to skip simple helper method tests because you implicitly test them while building the actual test. In the same way some developers may skip private method tests.
I'm fairly new to rails and trying to do things the "right" way by implementing tests from the get go. Yesterday I used the scaffolding generator to create my first model/view/controller configuration. While I've been told that you really shouldn't be using scaffolding, it was useful so that I could learn how Rails code is structured.
The one thing I noticed was that the automatically generated RSpec was mostly placed in the spec/controllers folder. However when I watched this episode of Railscasts, I noticed that he used the
rails generate integration_test [test_name]
command which placed a single test file in the spec/requests folder. However all of his tests that he wrote interacted with the controllers. What I'm trying to determine is the best practice for where to store these tests.
When should one store tests in the spec/requests folder and when should one store tests in the spec/controllers folder? Any feedback would be greatly appreciated!
Actually those are 2 types of tests. In the controller folder you should create tests to test the controller actions, in the request folder you should place tests to interact with views, wich will actually test all your application parts, and that's why it's named integration test.
Here are some articles about those two types of tests.
http://everydayrails.com/2012/04/07/testing-series-rspec-controllers.html
http://everydayrails.com/2012/04/24/testing-series-rspec-requests.html
Controller specs test the invocation of a single controller action. Typically you won't render views (although you can turn this on), it's also pretty common to stub out a lot of model code. The only interaction you have with the code under test is to invoke a single controller action. You could think of these as unit tests for controllers.
Request specs on the other hand test the whole stack (routing, controllers, views, models etc). Rather than just invoking a single controller action you perform actions closer to what a user would do: visit a page, fill in a form, click a button. Often this will span multiple actions/controllers. For example you might write a request spec that takes a user through the process of adding a product to a cart and then going through the various steps involved in checking out.
You typically use capybara (i think you can still use webrat) to interact with the pages you generate. With a suitable capybara driver javascript on the page will also be executed so, for example, you could test that your client side javascript does the right thing with the json produced by your controller (although you might want to consider writing javascript specs if you have a lot of that)
After some time of doing Cucumber & RSpec BDD, I realized that many of my Cucumber features are just higher level view tests.
When I start writing my scenario and then go down to RSpec, I don't ever write view specs, since I could just copy and paste part of the scenario, which would be ugly dupliacation.
Take this scenario for example
Scenario: New user comes to the site
Given I am not signed in
When I go to the home page
Then I should see "Sign up free"
I know that this isn't directly testing the view, but writing separate view spec to check for the same thing seems redundant to me.
Am I approaching Cucumber wrong? What exactly should I test in view specs?
Should I write them for every single view, for example testing views for actions like
def show
#project = current_user.projects.first
end
or should I just test more complex views?
It's a widely-accepted (and in my opinion, incorrect) Cucumber philosophy that views should never be tested within RSpec. The argument goes that since the behavior of the view can be described in Cucumber, RSpec should stick to what it knows best -- Models and Controllers.
I argue that the "human-readable" aspect of Cucumber makes some aspects of view-speccing important. For instance, I find view specs to work very well when working in parallel with a front-end developer. If a JavaScript developer knows that he'll want to hook into a selector on your page, it's important that your view provides that selector.
For example:
describe 'gremlins/show.html.haml' do
context 'given it is after midnight' do
it 'has a #gremlin_warning selector' do
Time.stub!(:now).and_return(Time.parse '2010-12-16 00:01:00')
rendered.should have_selector '#gremlin_warning'
end
end
context 'it is before midnight' do
it 'does not have a #gremlin_warning selector' do
Time.stub!(:now).and_return(Time.parse '2010-12-16 23:59:00')
rendered.should_not have_selector '#gremlin_warning'
end
end
end
Note that the specs do not describe the content, they are willfully brief, and they do not describe interaction behaviors. Because the view is the portion of your application that will change the most, view specs should be used sparingly.
tl;dr: View specs are for communicating a contract to other developers and should be used sparingly (but nonetheless should be used).
Personally, I never use view specs when using Cucumber. To me, acceptance tests make a lot more sense, and my complex views are generally Javascript-focused and cannot be tested using view specs.
Don't use view specs for anything, ever. Cucumber stories -- or even RSpec integration tests -- do that better. The examples bobocopy gives are good ones for the case he postulates, but they should be rolled into Cucumber stories/integration tests, not left on their own.
I use RSpec to test my lovely little web app. For integration tests I use Steak. When using Rails generators (yep, I know that this is not the Zen way of doing TDD) there are also some files in spec/requests generated. As stated on link text it is something similiar to integration test (but I couldn't find much more info).
Are those request specs still recommended when using something like Steak and Cucumber?
It all depends on what you need and want. The goal of testing is to prove that your app works once, not twice or more times.
I personally write rspec tests for models and helpers. I use cucumber to test that my views and controllers are working the way I expect them to. With this I can prove that my entire app works as I expect it to, so no, I don't use spec/requests.
Occasionally I do use spec/requests to test APIs, but you can do that with cucumber as well.
Some don't like the BDD-way cucumber works and stick with spec/requests. In the end it's all a matter of taste.
In view pages, people use form tag helpers and link helpers etc.
If I then rename a controller, or a action, my view pages may break.
How can I unit test view related tags for this kind of a breakage?
So the term "unit test" is usually reserved for tests that only test one piece of an application at a time-- you test one view and you test it independently of the associated controller and model.
But as you have found, if you isolate the tests, you can break the interaction between the two and still have all your unit tests passing.
That's why it's important to have tests that exercise your whole application working together. These are sometimes called functional, integration, or acceptance tests (I don't find it very useful to distinguish between these terms but YMMV).
This is usually done using a browser simulator like capybara or webrat so that you are using the application exactly how a user would in the browser. They demand different techniques than unit tests do, so that you don't end up with very brittle tests or tests that take a long time to run without providing additional value for the time spent.
You can use various test frameworks to drive capybara, including RSpec. Many people use RSpec for unit tests and use Cucumber for integration tests. I highly recommend The RSpec Book, which also covers Cucumber and the different methods of testing and when you should use them.