Functional Testing Concepts
When to Use
Use functional tests when the feature involves configuration, routing, permissions, or multi-request workflows that integration tests cannot easily exercise. Do not use them for logic variants — those belong in unit tests.
Decision
| Term | Scope | Browser? | Real DB? |
|---|---|---|---|
| Integration | Two or more components in the same process | No | Typically yes (test DB) |
| Functional / System | Feature-level behavior, full stack in-process | No | Yes (test DB) |
| E2E | User journey through real browser + real stack | Yes | Yes |
Functional tests are the right choice when: - The feature requires Drupal's permission system (access callbacks, route requirements) - The workflow spans multiple HTTP requests (wizard-style forms, OAuth redirects) - You need to test routing or middleware that integration tests cannot reach - You want to test an entire user story without the overhead of a real browser
Pattern
// Drupal functional test (PHPUnit BrowserTestBase)
// Tests the feature from the outside: HTTP → Drupal → DB
class UserRegistrationTest extends BrowserTestBase {
public function testRegistrationCreatesUserAndSendsEmail(): void {
$this->drupalGet('user/register');
$this->submitForm([
'mail' => 'alice@example.com',
'pass[pass1]' => 'S3cretPass!',
'pass[pass2]' => 'S3cretPass!',
], 'Create new account');
$this->assertSession()->statusCodeEquals(200);
$this->assertSession()->pageTextContains('Registration successful');
$user = user_load_by_mail('alice@example.com');
$this->assertNotNull($user);
}
}
Common Mistakes
- Wrong: Using functional tests for logic that unit tests can cover → Right: Functional tests are slow; logic belongs at the unit level
- Wrong: Testing every logic variant through a functional test → Right: Test variants with unit tests; use functional for the integration wire-up
- Wrong: Not cleaning up state between functional tests → Right: Use proper setup/teardown; leftover state causes intermittent failures
- Wrong: Conflating "functional" with "E2E" → Right: Functional runs in-process; E2E uses a real browser — different costs and failure modes
See Also
- Integration Testing Concepts | Next: E2E Testing Concepts
- Related: drupal/testing — Drupal functional and FunctionalJavascript test setup
- Related: drupal/tdd — TDD per Drupal feature type