Generate unique data with Fzaninotto/Faker

Fzaninotto/Faker is a package for generating all sorts of random data. This tip shows you how you can use it to generate unique data for usage in tests.

What is Faker?

With the help of Faker, it is possible to generate random data. Not only random numbers and Lorem ipsum. What makes Faker so great is that you can make (localized) names, telephone numbers, email addresses, postal codes and much much more.

Have a look at the GitHub page to see the whole repetoire.

Using Faker in your tests

This is really great, but when you use it in tests you will run into some problems. Consider the following scenario:

You want to generate 3 comments that should be visible on your blog. Then you generate 3 different comments that should not be visible to users. You verify this using the see() method that is available by default in Laravel 5.2

$blog = factory(Barryvanveen\Blogs\Blog::class, 'published')->create();

$online_comments = factory(Barryvanveen\Comments\Comment::class,
     'online', 3)->create(['blog_id' => $blog->id]);

$offline_comments = factory(Barryvanveen\Comments\Comment::class, 
     'offline', 3)->create(['blog_id' => $blog->id]);

$this->visit(route('blog-item', ['id' => $blog->id, 'slug' => $blog->slug]))
     ->see(trans('comments.title'));

foreach ($online_comments as $comment) {
    $this->see($comment->text);
}

foreach ($offline_comments as $comment) {
    $this->dontSee($comment->text);
}

This setup might lead to problems if you don’t configure the ModelFactory in the correct way. The text property for a comment could be generated by $faker->paragraph. But, this does not guarantee that each text is unique, so once in a while, your test might fail because a comment that is online and a comment that is offline both have the same text.

To counter this we can use Faker’s unique() method

Faker’s unique method

The unique() method is a chainable method that can be used to make any format (ie. any type of data) unique. This is done by keeping a list of generated data and re-generating new data until a unique value is found. A maximum number of retries is used to prevent never-ending loops.

Usage it like so:

$faker->unique()->paragraph;
$faker->unique()->name;
$faker->unique()->randomNumber(5);

It is no surprise that you cannot generate more than 2 unique Boolean values, so use this method with care. In much the same way it is very hard to generate 10.000 unique sentences, so don’t push it.