Install Dependencies
composer require benblub/ftg "dev-main" zenstruck/foundry
Configure Bundles
Add to config/bundles.php:
Benblub\Ftg\BenblubFtgBundle::class => ['dev' => true],
Register Maker Command
Add to config/services.yaml:
Benblub\Ftg\Bundle\Maker\MakeFunctionalTest:
tags: ['maker.command']
Generate a Factory
php bin/console make:factory User --test
Define myDefaults() in your factory (e.g., UserFactory.php):
public static function myDefaults(): array
{
return (new self())->getDefaults();
}
First Test Generation
php bin/console make:ftg:test User
This creates a test class extending ApiTestCase with basic CRUD operations.
Define Factory First
Ensure factories exist for all tested entities. Use --test flag for test-specific factories.
php bin/console make:factory Post --test
Generate Test Skeleton
php bin/console make:ftg:test Post
Outputs a test class (e.g., PostFunctionalTest) with:
Extend Test Logic Manually add custom assertions or edge cases:
public function testCustomValidation(): void
{
$post = $this->createPost(['title' => '']); // Missing title
$this->assertResponseStatusCode(400);
}
Authentication Integration
Implement AuthHelperInterface in a custom helper (e.g., CustomAuthHelper):
class CustomAuthHelper extends AuthHelper implements AuthHelperInterface
{
public function authenticateAsUser(): void
{
// Custom logic (e.g., JWT, OAuth)
}
}
Reference it in your test:
use App\Test\CustomAuthHelper;
class PostFunctionalTest extends ApiTestCase
{
use CustomAuthHelper;
public function testAuthenticatedEndpoint(): void
{
$this->authenticateAsUser();
// ...
}
}
Reuse Factories Inject factories via constructor or static methods:
public function testRelatedEntities(): void
{
$user = UserFactory::new()->create();
$post = PostFactory::new(['user_id' => $user->id])->create();
// ...
}
ApiTestCase is available. Ensure api bundle is configured in bundles.php.--test flag) to avoid polluting production factories.Missing Factory Defaults
Call to undefined method if myDefaults() is missing.myDefaults() in test factories:
public static function myDefaults(): array { return (new self())->getDefaults(); }
Auth Configuration Not Implemented
custom_auth: true config is referenced but not functional.AuthHelperInterface and bypass config.Bundle Autoloading
Class not found for BenblubFtgBundle.config/bundles.php includes the bundle before running commands.Foundry Dependency
make:factory --test).Test Isolation
create() (persists) vs. new() (in-memory) judiciously.-v for verbose logs:
php bin/console make:ftg:test User -v
var_dump(UserFactory::myDefaults());
$response = $this->client->request('GET', '/api/posts');
$this->assertJson($response->getContent());
Custom Test Templates Override the default test template by publishing and modifying:
php bin/console make:ftg:resources
Edit templates/test/TestFunctionalTest.txt.twig.
Dynamic Factory States
Extend factories to support dynamic states (e.g., withPublishedStatus()):
public function withPublishedStatus(): static
{
return $this->state([...]);
}
Hooks for Pre/Post Test Actions
Use PHPUnit’s @before/@after annotations or trait methods:
trait TestSetup
{
protected function setupDatabase(): void { /* ... */ }
}
Parallel Testing
FTG tests are PHPUnit-compatible. Use --parallel flag:
phpunit -c phpunit.xml.dist --testdox-html report.html --parallel
How can I help you explore Laravel packages today?