Generando datos de prueba con Faker

A menudo, durante el desarrollo de un proyecto, es necesario disponer de datos de prueba (habitualmente en una base de datos) que nos permitan verificar que alguna parte de la misma funciona o se visualiza correctamente, hacer tests de rendimiento etc. Para que esta tarea resulte menos tediosa, podemos utilizar Faker, una librería escrita en PHP (inspirada en las librerías Data:Faker de Perl y Faker de Ruby) que permite generar datos aleatorios de prueba de una manera sencilla y extensible.

Como vamos a ver, esta librería nos proporciona varios seeders (generadores aleatorios) para generar diferentes tipos de datos (nombres, textos, teléfonos y un largo etcétera) que podremos utilizar por ejemplo para rellenar campos de una tabla en la base de datos, generar ficheros XML, etc.

Instalación

La librería puede instalarse de forma sencilla en cualquier proyecto utilizando Composer:

composer require fzaninotto/faker

Una vez instalada, podemos comenzar a utilizarla incluyendo en nuestros scripts el fichero autoload.php:

require_once '/path/to/Faker/src/autoload.php';

o simplemente indicando que vamos a utilizar el espacio de nombres de Faker si el proyecto ya dispone de un autoloader (como en el caso de frameworks como Symfony):

use Faker;

Uso básico

El primer paso es instanciar Faker con la siguiente instrucción:

<?php
 
$faker = Faker\Factory::create('es_ES');

Como se puede ver, simplemente estamos llamando al método create() de Faker\Factory para instanciar el generador aleatorio para el código regional es_ES (español de España). De esta manera, obtendremos por ejemplo nombres españoles, en vez de ingleses (si no se indica el código regional Faker utilizará por defecto en_EN).

Una vez instanciado el generador podemos obtener datos aleatorios de diferentes tipos accediendo simplemente a propiedades del mismo:

<!--?php echo 'Nombre: '    . $faker-&gt;name        . '\n';
echo 'Dirección: ' . $faker-&gt;address     . '\n';
echo 'Email: '     . $faker-&gt;email       . '\n';
echo 'Teléfono: '  . $faker-&gt;phoneNumber . '\n';
echo 'Empresa: '   . $faker-&gt;company     . '\n';
&lt;/pre&gt;
&lt;p&gt;que generará algo similar a lo siguiente:&lt;/p&gt;
&lt;p style="padding-left: 30px;"&gt;Nombre: Dr. Marcos Peralta&lt;br ?-->
Dirección: Plaça Aitor, 07, 2º D, 11802, As Vanegas
Teléfono: +34 900-208029
Email: larias@hotmail.es
Empresa: Llamas-Hidalgo

De esta manera, hemos generado datos que podrían corresponder a una persona, tales como el nombre completo ($faker->name) o la dirección ($faker->address). Cada vez que accedamos a una propiedad de $faker el generador devolverá un nuevo valor aleatorio (llamando al proveedor correspondiente). Podemos reescribir el ejemplo anterior en un bucle para generar datos de 10 personas:

<!--?php for ($i=0; $i &amp;lt; 10; $i++) { echo 'Nombre: '    . $faker-&gt;name        . '\n';
echo 'Dirección: ' . $faker-&gt;address     . '\n';
echo 'Email: '     . $faker-&gt;email       . '\n';
echo 'Teléfono: '  . $faker-&gt;phoneNumber . '\n';
echo 'Empresa: '   . $faker-&gt;company     . '\n';
}
&lt;/pre&gt;
&lt;p&gt;En este ejemplo hemos utilizado sólo algunos proveedores (tipos de datos) básicos como el de nombres ($faker-&amp;gt;name), pero en la &lt;a href="https://github.com/fzaninotto/Faker"&gt;documentación&lt;/a&gt; se puede encontrar una lista completa de todos los proveedores de los que dispone &lt;em&gt;Faker&lt;/em&gt; para generar datos aleatorios.&lt;/p&gt;
&lt;h2&gt;Integración con ORMs&lt;/h2&gt;
&lt;p&gt;Una funcionalidad muy interesante de &lt;em&gt;Faker&lt;/em&gt; es su integración con &lt;em&gt;ORMs&lt;/em&gt; como &lt;em&gt;Doctrine&lt;/em&gt;, gracias a la cual podemos "rellenar" los campos de entidades previamente definidas de manera muy sencilla. Veamos un ejemplo utilizando &lt;em&gt;Doctrine&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;Supongamos que tenemos dos entidades: autor (Author) y libro (Book) con una relación 1-N. Es decir, un autor tiene puede tener 1 o más libros y cada libro tiene un único autor:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Author.php&lt;/em&gt;:&lt;/p&gt;
&lt;pre lang="php"&gt;&lt;?php
 
use Doctrine\ORM\Mapping as ORM;
 
/**
* Author
*
* @ORM\Table(name="author")
* @ORM\Entity
*/
class Author
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
 
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=250, nullable=false)
*/
private $name;
 
/**
* @var string
*
* @ORM\Column(name="address", type="string", length=250, nullable=true)
*/
private $address;
 
/**
* @var string
*
* @ORM\Column(name="phone", type="string", length=50, nullable=true)
*/
private $phone;
 
/**
* @var string
*
* @ORM\Column(name="email", type="string", length=254, nullable=true)
*/
private $email;
 
/**
* @var \DateTime
*
* @ORM\Column(name="birth_date", type="date", nullable=true)
*/
private $birthDate;
}
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Book.php&lt;/em&gt;:&lt;/p&gt;
&lt;pre lang="php"&gt;&lt;?php
 
use Doctrine\ORM\Mapping as ORM;
 
/**
* Book
*
* @ORM\Table(name="book", indexes={@ORM\Index(name="author", columns={"author"})})
* @ORM\Entity
*/
class Book
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
 
/**
* @var string
*
* @ORM\Column(name="title", type="string", length=250, nullable=false)
*/
private $title;
 
/**
* @var string
*
* @ORM\Column(name="description", type="string", length=500, nullable=true)
*/
private $description;
 
/**
* @var string
*
* @ORM\Column(name="isbn", type="string", length=20, nullable=false)
*/
private $isbn;
 
/**
* @var string
*
* @ORM\Column(name="publisher", type="string", length=250, nullable=false)
*/
private $publisher;
 
/**
* @var \DateTime
*
* @ORM\Column(name="published", type="date", nullable=false)
*/
private $published;
 
/**
* @var \Author
*
* @ORM\ManyToOne(targetEntity="Author")
* @ORM\JoinColumns({
*   @ORM\JoinColumn(name="author", referencedColumnName="id")
* })
*/
private $author;
}
&lt;/pre&gt;
&lt;p&gt;Podemos utilizar &lt;em&gt;Faker&lt;/em&gt; para rellenar (y guardar) estas entidades utilizando el &lt;em&gt;Populator&lt;/em&gt; de &lt;em&gt;Doctrine&lt;/em&gt; de la siguiente manera:&lt;/p&gt;
&lt;pre lang="php"&gt;&lt;?php $generator = Faker\Factory::create('es_ES'); $populator = new Faker\ORM\Doctrine\Populator($generator, $entityManager); $populator-&gt;addEntity('Entity\Author', 5);
$populator-&gt;addEntity('Entity\Book',   50);
 
$inserted = $populator-&gt;execute();
&lt;/pre&gt;
&lt;p&gt;Con este fragmento de código &lt;em&gt;Faker&lt;/em&gt; generará 5 registros de la entidad &lt;em&gt;Author&lt;/em&gt; y 50 de la entidad &lt;em&gt;Book&lt;/em&gt;. Además, como hemos definido la relación entre &lt;em&gt;Author&lt;/em&gt; y &lt;em&gt;Book&lt;/em&gt;, &lt;em&gt;Faker&lt;/em&gt; es lo suficientemente inteligente como para rellenar también el campo correspondiente a dicha relación, de manera que cada libro generado quedará asociado con un autor. Utilizando &lt;em&gt;MySQL&lt;/em&gt; el resultado podría ser algo como:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Author&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;[responsive]&lt;a href="http://www.conasa.es/wp-content/uploads/2016/10/autores.png"&gt;&lt;img class="aligncenter size-full wp-image-5831" src="http://www.conasa.es/wp-content/uploads/2016/10/autores.png" alt="Autores" width="1285" height="184" ?-->[/responsive]

Book:

Libros

Como se puede ver, Faker ha rellenado los campos de la entidad (tabla en la base de datos) y en algunos casos ha acertado correctamente con el proveedor (tipo de dato) a utilizar. Por ejemplo, en la tabla Author ha rellenado correctamente los campos de dirección (address), teléfono (phone), email (email) y fecha de nacimiento (birth_date). Esto se debe a que el “rellenador” (Faker\ORM\Doctrine\Populator) intenta adivinar el proveedor a utilizar en cada caso basándose en el nombre (address, phone y email) o en el tipo de datos del campo (birth_date, fecha). Faker nos permite personalizar qué proveedor se utiliza para cada campo de la siguiente forma:

&lt;?php $generator = Faker\Factory::create('es_ES'); $populator = new Faker\ORM\Doctrine\Populator($generator, $entityManager); $populator-&gt;addEntity('Entity\Author', 5, array(
'name' =&gt; function() use ($generator) { return $generator-&gt;name(); }
));
 
$populator-&gt;addEntity('Entity\Book', 50, array(
'isbn'      =&gt; function() use ($generator) { return $generator-&gt;isbn13(); },
'publisher' =&gt; function() use ($generator) { return $generator-&gt;company(); }
));
 
$inserted = $populator-&gt;execute();

En este ejemplo le estamos indicando a Faker que utilice el proveedor name() para rellenar el campo name (nombre completo) de la entidad Author y los proveedores isbn13() (código ISBN) y company() (empresa) para los campos isbn y publisher (editorial) de la entidad Book. En caso de que no especifiquemos qué proveedor utilizar para un campo concreto, Faker tratará de adivinarlo utilizando el nombre y el tipo de campo, tal y como se ha explicado en el ejemplo anterior.

Conclusiones

Faker es una herramienta realmente útil para generar datos aleatorios de prueba que nos pueden ayudar en el proceso de desarrollo y testeo de una aplicación. Como hemos visto, su uso es realmente sencillo, sobre todo en el caso de utilizar algún ORM como Doctrine, ya que nos permite generar y rellenar entidades de forma automatizada. Aunque ha quedado fuera del alcance de este post, Faker, además, es extensible, lo que significa que es posible añadir nuestros propios proveedores para generar nuevos tipos de datos o personalizar los existentes.

En el siguiente post os hablaré de Alice, otra librería de PHP que, haciendo uso de Faker, nos permite generar datos de prueba de forma más legible mediante ficheros de configuración YAML.

The following two tabs change content below.

Mikel Pintor

Desarrollador web.

Latest posts by Mikel Pintor (see all)

Compartir: