Recently, for a variety of reasons, I’ve been trying to develop in Rails using, for my testing, only the stock Test::Unit as covered in the Rails Testing Guide. (I can share some of the reasons if anyone’s interested.).

While the Rails Testing Guide is a bit confusing on the subject, it turns out you can use the built-in Rails testing support to test view partials, isolated as view partials, without any reference to a controller. The Guide only mentions view testing in the context of a controller/action-based testing, and leaves out some details for testing a bare partial.

But it turns out you easily can. If your test class subclasses `ActionView::TestCase` (a class oddly not mentioned in the Testing Guide at all), then it’s got access to a render method that can render partials, as well as the `assert_select` assertions that are mentioned in the guide.

I’ve only figured out the basics, I welcome more information about what’s going on and what you can do!

require 'test_helper' class WidgetPartialTest < ActionView::TestCase def test_widget_partial_render render "widget/widget_display", :local1 => "foo" assert_select "h2" end end

It pretty much just works. But note:

The `render` that ActionView::TestCase gives you is a render whose signature is similar to the one you have in Rails views , not controllers. The first argument as a string is a partial, not a full view. So the above `render` is looking for a partial in `app/views/widget/_widget_display.something` (I’m not sure if `render` is the code from ordinary rails, or a mocked up testing version which is meant to be like the `render` you call in ActionView, which is subtly different from the render you call in a controller).

, not controllers. The first argument as a string is a partial, not a full view. So the above `render` is looking for a partial in `app/views/widget/_widget_display.something` Similarly, you can pass locals as a direct second hash arg. It doens’t appear you can actually do the ‘:locals => {}’ thing (which I think maybe you can ordinarily use even in view render of partials?)

So there’s no way I know of to test a full template rather than a partial. Or is there? Maybe you can pass `:template=>`? Haven’t tried it yet. It probably usually makes sense to test a full template using a controller-based functional test, as the guide suggests. But I won’t say you’d never want to test a full view in isolation — some would suggest you never want to test a partial view in isolation either, but I’m absolutely convinced that it often makes sense to do so (when the partial is re-useable in many places, mainly). But either way, if there’s a way to test a full view in isolation, I haven’t figured it out.

There is such a thing in Rails3 as a partial layout too (a layout that can be applied to wrap partials), but I don’t think there’s any way to test a partial layout in isolation using this technique — I’m not sure if you can render a partial with a layout with ActionView::TestCase’s render. Or render a layout by itself with a block for it’s ‘yield’.

Rails: Full vs Partial Views, Really?

This brings up a general point about Rails; I think the distinction between ‘full’ and ‘partial’ views is increasingly ridiculous. You can do pretty much the same things with either one in modern rails. (This wasn’t always the case).

Either one can take a layout.

Either one takes locals.

Either one can be rendered directly from a controller.

Not sure if either one can be rendered from inside another view or if just partials can, but you ought to be able to, IMO.

Neither one is actually neccesarily a ‘complete web page’ — even full views typically don’t include <html><head><body> tags, leaving that to a layout.

Both can have multiple .format versions, and Rails looks up the right one for current :format when you render.

But while you can do much the same things with both full and partial views, there are subtly different ways to do them. And different code paths for doing much the same thing internally in Rails, sometimes.

I don’t think there’s any reason for this. They should be interchangeable. The `render` calls in controller and view should be identical, not have subtly different signatures/semantics. (Well, except for automatic-layout being applied from controller `render` and not view render, that’s the only important semantic difference I can think of). You should be able to render full views from inside other views; it’s perfectly reasonable to have a view which sometimes will be used ‘top level’ within a layout, but other times will be nested in another view. But Rails doesn’t make it easy.

It would be awfully nice if someone wanted to take a stab at refactoring partials and views to be identical in Rails4. Which DHH’s now well known disregard for backwards compatibility, I think it might even make sense for Rails4 to disregard the _underscore convention for naming partials. A view is a view is a view, you ought to be able to call any view from the controller or another view, wrapped in a layout, or not, with `locals` or not, there’s no reason to introduce a distinction.