Are there strong reasons for using Rspec for controllers and views too?
My views are heavily dependent on Javascript, and as far as I know, Rspec doesn't handle javascript/ajax on views. Also im using Cucumber + Selenium for that.
And should I use it for controllers?
Isn't it enough to just use Cucumber + Selenium for the application behavior? Cause if a cucumber test passes, then it passes, why should I bother with Rspec view and controller tests?
Could someone enlighten me on this topic?
I use a combination of Cucumber + Shoulda, but what I'm about to tell you still applies to the setup you have.
When testing a controller I use Shoulda in a functional test to hit all of my "negative auth" situations. For example:
A logged in user trying to access an admin page.
A logged out user trying to access protected content.
User A trying to delete User B's post.
I use Shoulda for this, because what I'm generally looking for is that I was kicked to the login page, and that whatever model was trying to be accessed maliciously wasn't actually changed. I could use Cucumber for this, but I find it easier and less cumbersome to do with a handful of Shoulda macros and some functional tests. Shoulda contexts are a great fit here.
Then for the "good auth" situations, I use Cucumber. Things like:
A user accessing his own preferences page.
An admin pulling up reports.
These types of tests require that I check some actual page content, and not just check for "access denied" over and over again. I find the descriptiveness of Cucumber to be a great match here.
If you build a full enough set of tests, you can just use selenium, but if you want to test the behaviour of your javascript seperate from the rest of the app, you might consider using a javascript test framework, like QUnit.
Related
Rails supports several types of tests:
Model tests
Controller tests
Functional tests
Integration tests
And, with capybara, it can also support:
Acceptance/integration/feature (depends on the author) tests
On some sites I see that these acceptance/integration/feature tests should only test particular flows, leaving edge cases for other kinds of tests. For example:
Integration tests are used to test the interaction among any number of controllers. They are generally used to test important work flows within your application.
http://guides.rubyonrails.org/testing.html#integration-testing
While these are great for testing high level functionality, keep in mind that feature specs are slow to run. Instead of testing every possible path through your application with Capybara, leave testing edge cases up to your model, view, and controller specs.
http://robots.thoughtbot.com/how-we-test-rails-applications
But I also see things like:
Your goal should be to write an integration test for every flow through your app: make sure every page gets visited, that every form gets submitted correctly one time and incorrectly one time, and test each flow for different types of users who may have different permissions (to make sure they can visit the pages they're allowed to, and not visit the pages they're not allowed to). You should have a lot of integration tests for your apps!
https://www.learnhowtoprogram.com/lessons/integration-testing-with-capybara
So, that's my question: In rails, should I include user input form error flows on capybara (or integration) tests?
Or do you think it should be enough to write view tests to test for the existance of flash messages, test failure flows via controller tests with the assigns helper, and only test successful flows through acceptance/integration/feature tests?
Edit The accepted answer was due to the comments.
User input form errors are handled by Active Record validations in Rails. So you could cover these with unit tests. But those kinds of tests only verify that you have validations present on your model. I'm not sure how much utility these types of tests offer other than allowing you to recreate your models in another framework or language and still have your tests pass.
Rspec noob here, just trying to improve my test coverage.
One very basic yet important question I have is just: What kinds of tests go where?
Model tests are straight forward. I just need to test the functionality of the models methods and validations. View tests seem simple. That would just be testing that each view renders the desired data.
What confuses me is what exactly goes in my Request Specs. Most of my rails experience is from following Michael Hartle's Rails Tutorial. His Request specs seem to be based around a series of actions that the user could take in the application. But he also includes test which seem like they should be in the View Specs that I am considering moving elsewhere.
If someone could help me understand what kinds of tests go in Request, that would be helpful.
From the RSpec docs:
Request specs provide a thin wrapper around Rails' integration tests, and are
designed to drive behavior through the full stack, including routing
(provided by Rails) and without stubbing (that's up to you).
With request specs, you can:
specify a single request
specify multiple requests across multiple controllers
specify multiple requests across multiple sessions
Check the rails documentation on integration tests for more information.
From Rails' docs on integration tests:
Integration tests are used to test the interaction among any number of controllers. They are generally used to test important work flows within your application.
If your test has to do with how a single view is rendered (which should be completely decoupled from any actual HTTP request), then it's probably better as a view test. If it has to do with multiple views or multiple requests, then an integration test is probably more appropriate.
I am still new to rails, but I went through Michael Hartl's book (super hepful, btw).
However, I started using Devise (also super helpful) and I had a question about testing with rspec. In Hartl's book, there are all these tests for user validations like uniqueness of email or just whether or not a user is created with valid attributes.
Are simple tests like this needed if I am using Devise?
Part of the reason I am asking is I can't figure out how to write the tests even though I know they are working. In general do you need to test gems to see if their internal functionality is working? Or can I just assume that will work and only test that a user can be created and logged in and be done with it?
I do test how I CanCan in that I test if I was redirected or not, but that seems more like testing that the rules I created are right. Testing the inner functions of Devise seems excessive?
I would consider testing the inner functions of devise to be excessive. However, if you make changes to devise, either the views, controllers, or validations, it would be appropriate then to test your changes.
I also always have request/acceptance tests that test the sign in/up part of my app.
You also asked:
In general do you need to test gems to see if their internal functionality is working?
No, this is generally not done. Things I like to look for: on the gem's github or webpage, do they link to TravisCI --- you can see if their current test suite works. In general, test at your level, not one beneath. For example, don't test that Rails works, just use Rails.
I want to start diving into BDD. I have never used TDD before and am
not sure if I should start by learning RSpec and then jump to Cucumber
or just go straight to using Cucumber.
I have been reading on the internet about both and it seems to me that
Cucumber could be a 'replacement' for RSpec. Am I right or should be
one used for certain things and the other one for others?
Cucumber and RSpec are both used for BDD but have different uses.
Think of Cucumber as describing what happens from the user's perspective, through interaction with the web browser. So you can have steps like:
Given I'm not logged in
When I login
Then I should be on the user dashboard page
Pretty broad, but there's a lot going on under the hood there. Cucumber is good for making sure all these sort of high-level features and functionality are covered (e.g., that when your user logs in, they're taken to the right page). But it's not a good tool for testing lower-level code. That's where RSpec comes in.
Take the login example above. Your user may be logging in with an email address or username. You probably want to ensure the email address is valid or that the username is a certain length...or that the thing they're using to login with is unique. You'd do this in your User model with a validation.
It's a trivial example, but this is the kind of thing you'd test using RSpec (in your spec/models/user_spec.rb file). This is not something you'd test using Cucumber.
So bottom line is:
Cucumber for higher-level tests describing broad functionality as viewed from the user's perspective
RSpec for lower-level tests describing details for how your classes, methods, models, controller, etc should actually work.
This post actually does a really good job of explaining when to transition from one tool to another:
http://www.sarahmei.com/blog/2010/05/29/outside-in-bdd/
I also recommend "The RSpec Book" and "Rails Test Prescriptions" for good resources on both tools and testing in general.
P.S. - Not to confuse things, but you can actually use RSpec for the high-level stuff too. But some of that decision is a matter of which tool you prefer or maybe whether or not you're working with a non-technical client who would benefit more from Cucumber's user-friendly syntax for describing scenarios.
Yes, cucumber and rspec are both used for BDD.
I personally prefer Cucumber, but some people find it offputting, and
prefer
their tests to be less english, more code. Both are great tools, though.
Kenton did a great job with this answer. Here is how the authors of RSpec and Cucumber see it:
We use Cucumber to describe the behavior of applications and use RSpec to describe the behavior of objects.
Although we use Cucumber to focus on high-level behavior and use RSpec
to focus on more granular behavior, each can be used for either
purpose.
I have a Rails 2.3.5 app which is serving a card game. I've been a bit lax in writing tests for it (read: I haven't written any :embarrassed:), and I'd like to make a start now.
From reading other questions, I think I probably want to be using Shoulda extending Test::Unit for unit testing.
I wondered about using Capybara extending RSpec for functional testing, but the majority of users' interaction with the app is via POST, which I understand Capybara doesn't handle.
Since this is a card game, I obviously need the ability to control rand; I also definitely need the framework to handle Javascript.
Is Test::Unit + Shoulda suitable?
Am I correct that Capybara can't handle POST? Can I work around that?
Is there a better option instead of Capybara?
Can these methods handle the randomness involved in a card-game? Presumably, for Test::Unit at least, I can just call srand at some early stage to fix the generator, but I don't know if that's doable for Capybara/RSpec/anything else.
Can anyone point me to resources dealing specifically with setting up Shoulda, Capybara and RSpec for Rails 2.3.5? It's a little hard to tell what's Rails 3 specific and what isn't.
Would I gain anything from adding Watir / Firewatir into the mix?
I realise the above questions are manifold, but they basically boil down to "does this work, or have you any better suggestions?"
If the majority of the users' interactions are via POST, is it via an API (as opposed to filling out forms or something)?
Just about any combination of RSpec/Shoulda/Capybara/Test Unit/Rack::Test could work for you depending on your need. They're all capable. However, these are my recommendations:
If you've decided you want integration testing via HTML pages, use Cucumber and Capybara
If you've decided you want integration testing via HTTP API, use RSpec and Rack::Test
You probably want to fake out randomness.
You probably don't need Watir/Firewatir.
It does look like you can make POST requests via some Capybara drivers:
http://suffix.be/blog/capybara-post-requests
When Rails moved to 3.0, RSpec went to 2.0 so for at least RSpec, you'd want RSpec and RSpec Rails 1.3.2.
By "fake out randomess", I mean redefine srand in your tests so you can predictably run them.
module Kernel
def rand
YourApp.rand
end
end
module MyApp
class << self
attr_accessor :rand
end
end
Then, before you have the user press the button, run a step definition like "When random returns 6", which will set MyApp.rand = 6.