Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

charles-wc's avatar

Best way to have consistent data in factories?

When seeding a database, I'd like to rely on data other than what's created in Faker. In the past, I've seeded the database from a CSV without factories, however now that I'm getting into testing, I'd like to use that data in factories as well. What is the best way to go about doing something like that? Since it will be data for automated tests, does it even matter?

0 likes
3 replies
LaryAI's avatar
Level 58

Great question! When you want consistent, repeatable data in your Laravel factories (for seeding and testing), you have a few good options:

1. Use Factory States or Static Data

You can define specific states or hardcoded data in your factories for consistency:

// database/factories/UserFactory.php

public function definition()
{
    return [
        'name' => 'John Doe',
        'email' => '[email protected]',
        // other fields...
    ];
}

Or use factory states:

public function admin()
{
    return $this->state([
        'name' => 'Admin User',
        'email' => '[email protected]',
    ]);
}

2. Load Data from a CSV or Array

If you have a CSV or array of data you want to use, you can read it and use it in your factories or seeders:

// Example: database/seeders/UserSeeder.php

use Illuminate\Database\Seeder;
use App\Models\User;

class UserSeeder extends Seeder
{
    public function run()
    {
        $users = array_map('str_getcsv', file(database_path('seeders/users.csv')));
        foreach ($users as $userData) {
            User::factory()->create([
                'name' => $userData[0],
                'email' => $userData[1],
                // etc...
            ]);
        }
    }
}

3. Use a Custom Provider

You can create a custom Faker provider if you want to inject consistent data into Faker itself, but for most cases, using arrays or states is simpler.

4. Should You Care for Tests?

For automated tests, consistency is important. You want your tests to be repeatable and predictable. Using hardcoded data or loading from a static source (like a CSV or array) is a good practice for this.

5. Use DatabaseMigrations or RefreshDatabase

If you want to ensure a clean slate for each test, use the RefreshDatabase trait in your tests. This way, your factories and seeders will always run on a fresh database.


Summary:

  • For consistent data, use hardcoded values, factory states, or load from a CSV/array.
  • For tests, consistency is good practice.
  • You can combine factories with static data for both seeding and testing.

Let me know if you want a more detailed example for your specific use case!

krisi_gjika's avatar

you can run one or more seeders before your tests,

example call PostCategory seeder to seed categories from a csv or some other static data, than call Post::factory() and pass a category.

Example

public function setUp(): void
{
    parent::setUp();

    $this->seed(FillPostCategories::class);

    $this->category = PostCategory::inRandomOrder()->ofLastDepth()->first();

    $this->post = Post::factory()->ofCategory($this->category)->create();
}

Please or to participate in this conversation.