Do You Test Your Views?

Posted by jeff Friday, January 23, 2009 01:45:00 GMT

Those of you following me on twitter already know that I’m learning Cucumber.

Traditionally I don’t test my views or controllers all that much. I know, I know, it’s heresy. But I’ve just never gotten much value from writing Rails functional tests nor integration tests.

Yet those of you who have been reading my articles or new book know that I’ve been immersed in TDD for a long time and can’t imagine writing any application without a decent test suite to go with it.

So what do I test? I test the models like no one’s business. I use test/unit or shoulda to drive the design of all the models I write, and I write a lot of tests covering every possible edge case I can think of.

But the controllers and views? Up until now it’s seemed like a waste of time, for several reasons.

First, most of my controllers are stupid-simple RESTful controllers. They’re as skinny as possible, because I move almost all of the real logic into the models. That way I can test my models with unit tests without trying to simulate a browser, and I find it easier to use script/console to play with models than with controllers.

Secondly, once the application gets to its first stabilization point, I find that HTML and CSS change way more often than 80% of the core application logic ever will. Writing tests for the views just means they’ll break after inconsequential layout changes. After all, views are just supposed to be a representation of your models (generally speaking), and other stuff (navigation, ajax effects, etc.) just aren’t worth my time writing a regression suite for.

As much as I’m digging Cucumber’s syntax, I’m desparately close to just going back to test/unit and forgetting about the controllers again.

Convince me otherwise. Do you test your controllers and views? If so, with what – Rails functional tests in test/unit? RSpec? Cucumber? What are you trying to verify in your tests, and why?


Is your team switching to Rails? Sign up for a fun-filled, one-day class in your own office: SwitchingToRails.com

Comments

Leave a response

  1. josh   January 23, 2009 @ 04:25 AM

    I have tested views ..er, web pages (webforms) using watir but that was a while ago. I don’t generally test controllers or views, but I feel I should. At least the controllers. It’s a matter of tooling and friction.

    I find my testing of views and controllers is basically walking through manually to see if they do what they’re supposed to. Just like the F5 style testing in Visual Studio. Really not a good way to test your app especially if you dont have QA people to cover your tracks for you.

    Not sure if that’s convincing, but its part of why I intend to improve that are this year.

  2. Antares Trader   January 23, 2009 @ 06:51 AM

    You are not the only one using and learning cucumber. I’ve got three posts so far on the subject. In response to your question about model vs controller testing, I still test my models with RSpec. I’m using Cucumber for controller/views. I three things, important content (The users name should appear on the user page), Structure (do the div’s match the expectations of my CSS and JavaScript files) and Form submission (does submitting a form actually change the model the right way).

    Finally, I highly recommend Yehuda Katz Merb Camp Presentation on the subject of testing. He gives a very good rational for full stack testing. There are certainly ways to disagree with his premise, but it is an excellent video none the less.

    I would love to see more blog posts about how you are using Cucumber as well.

  3. JP   January 23, 2009 @ 07:09 AM

    I do light controller and view testing through functional tests using test/unit + shoulda. The functional tests exercise the entire stack (minus the occasional external dependency which gets mocked). The tests addressing the view are deliberately abstract to avoid the brittleness associated with dependency on the layout.

    The real benefit I’ve derived from exercising the controllers and views in functional tests is the reasonable assurance that things are playing well together. I test the bejesus out of my models with unit tests, but unless I have functional tests proving that the different components are interacting correctly it doesn’t feel complete.

  4. Kevin Berridge   January 23, 2009 @ 11:47 AM

    I don’t do much web development, but the patterns are similar enough. And I don’t test my views or controllers. Testing the model where the real logic and algorithm resides is worthwhile. But I’ve always found that its significantly faster to just click test the view. You’re going to be click testing it anyway as you make your changes. And then you’ll hand it off to be “tested” (ideally) as well. And unlike the model, problems with the view/controller tend to be pretty obvious. Finally, its very rare for anything other than your view/controller to depend on your view/controller. So, you don’t have to worry as much about changes in one area breaking another.

  5. Brian   January 23, 2009 @ 12:53 PM

    Cucumber is like rSpec used to be – lots of hype, not much leadership and solid examples available from its evangelists. There’s a lot of “this is the best thing ever”, and yet everyone blogs the same thing: a simple story with a couple of steps to implement it. Of course, you have to expect that from new stuff. Docs get better as projects grow.

    I use rspec and test::unit to test views and controllers. I just started looking into Cucumber and I don’t really think it works well as a way to test your views in the traditional sense, but it does add a level of communication to the project that may be missing – strucured stories that can be tested.

    Cucumber’s one level away from “acceptance testing”. My biggest beef with it right now is that it’s a time sink. I can test controllers and models pretty quickly, but with Cucumber I’m writing the steps to make my cleartext stories actually do something. I find I spend more time doing that than implementing features. That may change, or it may not. We’ll see.

    Regardless, I believe testing the app from the OUTSIDE with Selenium is probably the best way to ensure that things work. You’re testing everything here. Integration tests (and Cucumber with Webrat) still work inside of Rails rather than working through the browser. I may look into using Cucumber with Selenium or Watir next.

  6. Matt Darby   January 23, 2009 @ 01:08 PM

    I test my views religiously. This is what the user sees and interacts with; why wouldn’t you ensure that everything is in place? Testing views are easy so long as you only spec what should be there, not necessarily where, nor how. (I care that a ‘new’ link is there, not that it is bold text)

  7. Patrick Huesler   January 23, 2009 @ 01:37 PM

    I tend to use integrate_views when testing my controller with RSpec to make sure that the views render without any errors. This already covers most of the bugs that get introduced in views (syntax errors, method calls on nil, undefined_methods, etc.).

    I find selenium quit useful to do acceptance testing. I know its slow and sometimes buggy. Therefore I test only the most important features with it, like signup or login. This way, the core functionality is documented and the stakeholders can watch selenium clicking through their application.

  8. Josh Clayton   January 23, 2009 @ 06:25 PM

    I don’t test my views for the sole reason that you mentioned above; classes, elements, layout… they all change fairly regularly after the meat and potatoes of the app (models and controllers) is done. I must say that I know I should test my views for id attributes on elements when there’s AJAX involved, but that would really be the only time I write tests.

    In lieu of writing tests, I use Tarantula. Setting it up is pretty easy, and it spits out a list of 404s, 500s, 304s, etc. You can even have it ensure your HTML tags are closed properly. If I get a 500, I know that there’s something wrong and I need to fix it.

    As for controller testing, I also agree that, if you’re following fat models/skinny controllers, writing tests are pretty irrelevant. However, if there is something that’s outside of the general RESTful methods, I’ll typically test that in some manner.

    Cheers!

  9. Jon Collier   January 23, 2009 @ 06:59 PM

    I use assert_tag and response.body.match// to ensure that critical information is being displayed. But I second the problem that our page layouts and UI details change often enough that it’s not necessary to get overly detailed in our testing. I don’t usually bother to test proper nesting or placement of a tag and it’s contents – just that they are present on the page.

  10. Justin   January 24, 2009 @ 08:53 AM

    I have a lot of controllers and it wound take way to long to manually test them in the browser. So I tend to test the index and show actions just to catch exceptions. Assert_response success is all I do.

  11. Nathan   January 25, 2009 @ 02:13 AM

    One thing I find particularly helpful about testing controllers and views is the reassurance you get when backpedaling. Say we remove the ‘street_address’ field from the Apartment model. You could modify the unit test, say using shoulda, and remove the should_have_db_column field, etc. But how are you sure that removing that field doesn’t break a form associated with that model? If you have some functional tests they will at least break if a form_for is trying to use that field and resulting in a 500.

    Does anyone know of a better way of handling this just within the unit test?

  12. masone   January 25, 2009 @ 01:39 PM

    I do heavy controller and model testing with Rspec. I’m testing views quite rarely and very selective but using Selenium instead. This also allows me to test most of the AJAX stuff.

  13. Jaime Iniesta   January 27, 2009 @ 10:38 PM

    I don’t test views, but I do test controllers. Mostly, what I test in controllers are user permissions, most of the times. Like, in a multiuser blog: test a user can create, edit and destroy posts; but only if she’s logged in, and that also can’t modify other user’s posts. Things like that, mostly, that you can’t test on the model side alone.

  14. Alistair Holt   January 29, 2009 @ 05:21 PM

    I’ve just finished writing tests for a Merb app I’ve been working on and I haven’t bothered to write the request tests although I may do in the future. I find writing really good model tests sufficient as I like to keep the controllers as simple as possible ala the “fat model, skinny controller” principle.

    I can see writing request tests being useful as it’s really horrible to see things breaking in production because you didn’t realise that the code you changed was going to affect something elsewhere in the app, it’s better to know that everything is going to work when you deploy but I’m still undecided on the matter.

  15. Richie Vos   January 30, 2009 @ 06:35 PM

    I’d separate out xml views from html views in testing. I think xml views generally are used for service integration and as such should be tested (plus they’re usually more straightforward so its easier to test them).

    Html views I think more selective testing is appropriate. I think if its just a straightforward html view, testing that given a set of data it renders itself is all you’d need, but if there’s anything complex in a view I care about (like this field gets written to the page if this flag is set) I think that should be tested.

    Once you write a couple view tests they’re not really that hard to continue to write, so I don’t see why you wouldn’t want some coverage.

    That being said, I think once the complexities you want to try out are tested (ignoring any that get moved into Helpers), having some Watir tests are nice to fall back on.

    Except watir/selenium tests are really slowww, so I think leaning on them too much leads to bugs that don’t get caught til someone decides to run the full tests (or the nightly build catches them).

  16. James Stewart   January 31, 2009 @ 10:43 AM

    I do some view testing, though it’s far from comprehensive. I mostly use them to make sure that there aren’t any glaring syntax errors in my views (a quick success test) and also if there’s any conditional logic I do some simple checks in my specs:

    response.should have_text(“whatever”)

    Controllers I spec more tightly, to make sure various potential edge cases are covered (mostly unwanted nils).

    I then use cucumber sparingly to cover particularly complex or critical processes. Coupled with webrat I’ve found it usually a pretty quick job to write the stories and it gives me some confidence that apps flow as expected.

  17. Kumar McMillan   February 02, 2009 @ 04:53 PM

    I used to do a lot of “full stack” testing where I’d insert a bunch of db fixtures and test the HTML response for each URL. The biggest problem here is that you waste time with all that db setup, especially if you already have unit tests for you models. Also, testing HTML is pretty easy with a forgiving xpath tool but interpreting failures is cumbersome.

    I like this strategy better: use mock objects for everything that is already tested elsewhere (like the model layer) then test for context variables that are used in the view (i.e. instead of the HTML itself). That gives you some coverage over decisions your controllers might make for displaying errors or whatever.

    Finally, I think you need to test ajax, especially if your site depends on it as Gmail or something similar would. A cheap and effective way to do this is to simply stub out your whole server. That’s right, create custom routes just for ajax tests that point to stub controllers that return static JSON. Fire up Watir, Selenium, or Windmill and you now have super fast tests for your ajax that do not depend on a full stack application (you may also be able to do this with HTML and a javascript test framework like qUnit for jQuery or doh for Dojo). fwiw, I plan to give a talk about how I’ve been testing ajax at PyCon http://us.pycon.org/2009/conference/talks/?filter=ajax :)

  18. Brandon   February 04, 2009 @ 07:43 AM

    But you can not do this all the time, we should look for the new ways to check our views!

  19. Stephen Boisvert   February 05, 2009 @ 02:55 PM

    You all test your views! Some of you just do it manually.

  20. Amos King   February 12, 2009 @ 05:28 AM

    I use shoulda, webrat, an factory_girl to test my views. I even have a selenium build. I think it is crazy not to test the views. So much of your customer value comes from the views. Now I don’t test that I have an h3 tag with a certain content. I might test that the page contains whatever is in the h3 tag, but the h3 itself is style, and not functionality. I will also sometimes check that and error message is inside an element with a certain id. The styles are all with classes, and ids are used to determine specific elements. You can use things like assert_have_selector(webrat) to test for a certain class. ie. assert_have_selector ’#error’ #this finds any element with the id error.

    Happy Testing