Module: DevDoc::Test::Lints::HttpDrivenControllerTests

Defined in:
lib/dev_doc/test/lints/http_driven_controller_tests.rb

Overview

Runtime guarantee that every test under test/controllers/ actually drives the app through HTTP. Include into the project's base integration test class (a descendant of ActionDispatch::IntegrationTest):

Glib::IntegrationTest.include DevDoc::Test::Lints::HttpDrivenControllerTests

Rationale

Best practice (see AvoidUnitTest) prefers controller tests because they exercise the wiring a user actually hits. Static enforcement keyed on base class or file name is trivially evaded — and observed evasions by AI agents include: naming files ambiguously, mixing unit tests into controller test files, and inheriting the integration base class so the < ActiveSupport::TestCase heuristic never fires.

This lint closes those holes by keying on observed behavior: ActionDispatch::Integration::Runner#process is the single choke point every request helper funnels through (get/post/... — no matter how deeply wrapped in log_user_in-style helpers), so "issued at least one request" is checked per test, not per file. A unit test cannot pass it by renaming, relocating within the file, or subclassing anything.

There is deliberately NO opt-out flag: a test that never issues a request does not belong under test/controllers/. Move it to the matching directory (test/models/, test/jobs/, ...) with the justification header your project's conventions require (see DevDoc/Test/RequireUnitTestJustification).

Constant Summary collapse

CONTROLLER_TEST_PATH =
%r{(\A|/)test/controllers/}
MESSAGE =
<<~MSG.freeze
  %<location>s lives under test/controllers/ but never issued an HTTP request —
  it is a unit test in controller-test clothing. Convert it to drive the app
  through a request (the bugs live in the wiring), or move it to the directory
  matching what it exercises (test/models/, test/jobs/, ...) with a documented
  justification header.
MSG

Instance Method Summary collapse

Instance Method Details

#after_teardown ⇒ Object



58
59
60
61
62
# File 'lib/dev_doc/test/lints/http_driven_controller_tests.rb', line 58

def after_teardown
  super
ensure
  __dev_doc_check_http_driven
end

#before_setup ⇒ Object



41
42
43
44
# File 'lib/dev_doc/test/lints/http_driven_controller_tests.rb', line 41

def before_setup
  @__dev_doc_http_request_count = 0
  super
end