Functional test means: test one useful feature, but do not go through a real browser. This sits between unit and integration.
Summary: Test one feature flow inside the app.
Here is the app flow, which we want to test:
$app = TestAppFactory::create();
$response = $app->handle('GET', '/api/lessons');
$lessonResponse = $app->handle('GET', '/api/lessons/api-testing');Now we can create a test like this:
// $response is the array returned by $app->handle(...).
// $response['body'] is the JSON string inside that response.
$decoded = json_decode($response['body'], true);
$lesson = json_decode($lessonResponse['body'], true);
$this->assertSame(200, $response['status']);
$this->assertTrue(count($decoded['lessons']) > 0);
$this->assertSame('Integration Test (API)', $lesson['title']);Why this test works
- The main class here is App in src/App.php.
- That class is also inside the SmallLearning namespace.
- App needs LearningService. LearningService needs LessonRepository.
- TestAppFactory builds those objects for us, so the test file stays small.
- The response comes from this line: $response = $app->handle(...).
- In this project, handle() returns a simple PHP array with keys like status, headers, and body.
- So $response["body"] is just the JSON text returned by App::handle().
- json_decode($response["body"], true) converts that JSON text into a PHP array so the test can assert values inside it.
- Put this file in tests/functional/FunctionalFlowTest.php because it tests one app feature.
- The test knows the app class because the file loads tests/Support/TestAppFactory.php.
- TestAppFactory creates the App object for us.
- Simple rule: create app, call handle(), assert response.
Real-life examples
- Example: on a support website, call the app handler for /contact and check that the page data contains the contact form section.
- Example: on a profile website, call the app handler for /api/profile and check that the returned JSON includes the user name.
Remember this
- Open tests/Support/TestAppFactory.php
- Let the factory build the app
- Put file in tests/functional
- Use TestAppFactory
- Run with php tests/run.php functional