carlescliment/handy-tests-bundle
Installation:
composer require carlescliment/handy-tests-bundle
Add to config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 3):
BladeTester\HandyTestsBundle\BladeTesterHandyTestsBundle::class => ['test' => true],
First Use Case: Truncate a table before a test:
use BladeTester\HandyTestsBundle\Model\TableTruncator;
use Doctrine\ORM\EntityManagerInterface;
public function testSomething(EntityManagerInterface $em)
{
TableTruncator::truncate(['users', 'posts'], $em);
// Test logic here...
}
Fine-Grained Truncation:
Use TableTruncator for isolated tests where full fixtures are overkill:
// Before test
TableTruncator::truncate(['orders', 'order_items'], $em);
// After test (via tearDown)
TableTruncator::truncate(['orders', 'order_items'], $em);
Factory Girl Integration:
Create reusable entity factories in a Test/DataFixtures directory:
// src/Test/DataFixtures/UserFactory.php
class UserFactory
{
public static function create(array $overrides = []): User
{
$user = new User();
$user->setEmail('test@example.com');
$user->setPassword('password');
foreach ($overrides as $key => $value) {
$user->{'set' . ucfirst($key)}($value);
}
return $user;
}
}
Use in tests:
$user = UserFactory::create(['email' => 'new@example.com']);
$em->persist($user);
$em->flush();
Setup/TearDown:
public function setUp(): void
{
parent::setUp();
TableTruncator::truncate(['users'], $this->em);
}
public function tearDown(): void
{
TableTruncator::truncate(['users'], $this->em);
parent::tearDown();
}
Data Isolation:
Use TableTruncator for tests requiring clean state:
public function testUserCreation()
{
TableTruncator::truncate(['users'], $this->em);
$user = UserFactory::create();
$this->assertDatabaseHas('users', ['email' => $user->getEmail()]);
}
MySQL Only:
TableTruncator uses TRUNCATE TABLE, which is MySQL-specific. For PostgreSQL/SQLite, use DELETE FROM or Doctrine’s createQueryBuilder()->delete().
Foreign Key Constraints: Truncating tables with foreign key dependencies may fail. Either:
order_items before orders).EntityManager Scope:
Ensure the passed EntityManager is the same used in your test (e.g., injected via EntityManagerInterface $em).
Truncate Failures:
Check for errors in TRUNCATE syntax or permissions. Use raw SQL queries to debug:
$connection = $em->getConnection();
$connection->executeStatement('TRUNCATE TABLE users');
Factory Issues: Validate entity state after creation:
$user = UserFactory::create();
$this->assertInstanceOf(User::class, $user);
$this->assertNotNull($user->getId()); // If auto-incremented
Custom Factories:
Extend FactoryGirl pattern for complex entities:
class PostFactory
{
public static function create(array $overrides = []): Post
{
$post = new Post();
$post->setTitle('Test Post');
$post->setContent('Content...');
// Handle relationships
$post->setAuthor(UserFactory::create());
foreach ($overrides as $key => $value) {
$post->{'set' . ucfirst($key)}($value);
}
return $post;
}
}
Bulk Operations: Combine with Doctrine extensions for bulk inserts:
$em->getConnection()->beginTransaction();
$stmt = $em->getConnection()->prepare('INSERT INTO users (email) VALUES (?)');
foreach ($emails as $email) {
$stmt->execute([$email]);
}
$em->getConnection()->commit();
Test Traits: Create reusable traits for common setups:
trait DatabaseCleanupTrait
{
public function cleanupDatabase(EntityManagerInterface $em, array $tables)
{
TableTruncator::truncate($tables, $em);
}
}
How can I help you explore Laravel packages today?