Should I test that?

Should I test views?

Verdict

Yes

Yes, test server-rendered views minimally: render each page once in a request test with realistic records and assert the text users need, and write no separate view specs for templates that only print fields.

Why

Test views minimally: render each page once in a request test. For a Rails, Django or ASP.NET Core MVC template that prints a record and has a few conditionals, Blast radius is users and Change frequency is regularly, because templates change with most features. Detectability is same-day, because a template error returns a 500 that the error tracker reports within hours, and Reversibility is trivial, because a view stores nothing. Test cost is moderate: a request test needs records in a test database and changes with the page's text.

When the decision changes
WhenDecisionWhy
The template prints fields with no conditionals, and its author opens the page after each changeDo not test the view; look at the page in a browser before mergingDetectability moves to immediately, because the author sees a broken page at once, and Reversibility stays trivial
A request test for the page runs in CI with records that take each branch of the template, such as a project with an owner and one withoutDo not add separate view specs for the pageDetectability moves to immediately, because a template error in any branch fails CI before merge, and Reversibility stays trivial
The template shows some fields only to some roles, such as customer email addresses that only admins may seeTest mandatory: render the page as each role and assert the hidden fields are absentBlast radius rises to safety-or-legal and Detectability to never, because personal data shown to the wrong role raises no error
The view renders a form whose input names bind to model fields, such as a profile edit formTest: submit the form in a request test and assert every field reaches the saved recordDetectability moves to eventually and Reversibility rises to with-effort, because a renamed input saves an empty field without an error
The view formats prices or an order total that customers payTest mandatory: assert the exact amount and currency shown for each pricing caseBlast radius rises to money and Reversibility to costly, because customers buy at the amount on the page
The view is an Android screen in an app that users update only through the storeTest: assert what the screen shows in its loaded, empty and error states with Espresso or RobolectricReversibility rises to costly, because every fix waits for a store release

What breaks if you don't test

A template breaks on the branch its author never opened: @project.owner.name raises NoMethodError for the first project without an owner, and its users get an error page until a fix ships. RSpec controller tests stay green, because controller specs stub views by default.

What you lose if you over-test

A view spec for each template assigns the variables itself and asserts on CSS selectors, so moving a heading into a card breaks it while the page still works. A view spec also passes when the controller stops setting a variable the template reads, because the spec assigns that variable, so the page fails in production with a green suite.

How to test

Test views at the request level, one test per page: integration tests in Rails, the Django test client with assertContains, or WebApplicationFactory in ASP.NET Core.

  1. Create the records the page shows, including one for the rarer branch of each conditional, such as a missing association.
  2. Request the page and assert status 200.
  3. Assert the text users need, such as the record's name, without CSS selectors.

Add a regression test when a template bug reaches production.

When the answer changes

  • The template decides which role sees which fields.
  • The page shows prices or totals.
  • The view builds a form whose fields the app saves.

Real incident + Code example

The project page with no owner

On a Rails project tracker I worked on, a nightly job that archived departed staff set owner_id to null on their projects. The project page printed @project.owner.name, and its controller spec passed because RSpec stubbed the view. By morning, customers had hit 500 errors on 37 projects; an hour after the alert, the page printed "No owner" instead. We added this request spec:

RSpec.describe "Project page", type: :request do
  it "renders a project whose owner has left" do
    project = Project.create!(name: "Q3 roadmap", owner: nil)

    get project_path(project)

    expect(response).to have_http_status(:ok)
    expect(response.body).to include("Q3 roadmap", "No owner")
  end
end

The spec runs the real controller and template, so a nil owner fails CI.

FAQ

When should ASP.NET MVC views be unit tested?

Unit test an ASP.NET MVC view only when it holds logic, such as fields hidden by role; cover other views with one integration test per page through WebApplicationFactory. ASP.NET Core compiles Razor views at build time, so a syntax error fails the build, but a null model property throws only when the page renders.

Should I test view attributes in unit tests?

Test only the view attributes that your code changes at runtime, such as an empty-state message that appears when a list is empty. An assertion on an attribute declared in the layout file, such as a text colour, repeats the declaration.

When should I test views separately in a Cucumber and RSpec workflow?

Test a view separately only for template branches that no Cucumber scenario reaches, such as a page that differs by role. For each such branch, a request spec with the matching records costs less than a new scenario.

Should I test a generic DetailView in Django?

Test your Django DetailView with one request, not the generic class: request its URL for a real record and assert the page contains the record's fields. Django's own tests cover the generic view code, so that request checks your URL pattern, queryset and template.