Статьи

Упрощение генерации тестовых данных с помощью Faker

Тестирование — это итеративная часть процесса разработки, которую мы проводим для обеспечения качества нашего кода. Большая часть этого влечет за собой написание тестовых случаев и тестирование каждого модуля нашего приложения с использованием случайных тестовых данных.

Фактические данные для нашего приложения поступают, когда мы выпускаем его в производство, но в процессе разработки нам нужны поддельные данные, аналогичные реальным данным для целей тестирования. Популярная библиотека с открытым исходным кодом Faker предоставляет нам возможность генерировать различные данные, подходящие для широкого спектра сценариев.

Здесь мы сосредоточимся на генерации случайных тестовых данных с использованием Faker для тестирования наших тестовых случаев.

Как работает Faker

Faker поставляется с набором встроенных поставщиков данных, к которым можно легко получить доступ для генерации тестовых данных. Кроме того, мы можем определить наши собственные типы тестовых данных, что делает его чрезвычайно расширяемым. Но сначала давайте рассмотрим базовый пример, который показывает, как работает Faker:

<?php
require "vendor/autoload.php";

$faker = FakerFactory::create();

// generate data by accessing properties
for ($i = 0; $i < 10; $i++) {
    echo "<p>" . $faker->name . "</p>";
    echo "<p>" . $faker->address . "</p>";
}

В этом примере предполагается, что Faker был установлен с использованием Composer и использует автозагрузчик Composer, чтобы сделать определения классов доступными. Вы также можете использовать Faker, клонируя его из репозитория GitHub и используя включенный автозагрузчик, если вы не используете Composer.

Чтобы использовать Faker, нам сначала нужно получить экземпляр из FakerFactory Все поставщики данных по умолчанию автоматически загружаются в объект $faker Затем мы генерируем случайные данные, просто вызывая имя средства форматирования. Окончательный вывод приведенного выше кода будет содержать список из десяти случайных имен и адресов из доступных источников данных.

Поставщики — это классы, которые содержат данные и необходимые методы форматирования для генерации данных. Форматеры — это методы внутри классов провайдеров, которые генерируют тестовые данные непосредственно из источника или с использованием комбинации других форматеров. Faker поставляется со следующими встроенными провайдерами: PersonAddressPhoneNoCompanyLoremInternetDateTimeMiscellaneousUserAgent

Давайте посмотрим на класс Person

 <?php
namespace FakerProvider;

class Person extends FakerProviderBase
{
    protected static $formats = array(
           "{{firstName}} {{lastName}}",
    );
    protected static $firstName = array("John", "Jane");
    protected static $lastName = array("Doe");

    public function name() {
           $format = static::randomElement(static::$formats);
        return $this->generator->parse($format);
    }

    public static function firstName() {
        return static::randomElement(static::$firstName);
    }
}

PersonFakerProviderBase firstName()firstName Форматировщики могут объединять другие форматеры и возвращать данные также в определенном формате, что и делает name() Все провайдеры и форматеры работают на основе этой структуры.

Встроенные поставщики содержат базовые средства форматирования с очень ограниченными данными. Если вы используете Faker для автоматизации процесса генерации тестовых данных, вам может потребоваться создать свои собственные наборы данных и реализации форматирования путем расширения базовых поставщиков.

 <?php
namespace FakerProvider;

class Student extends FakerProviderPerson
{
    protected static $formats = array(
        "{{lastName}} {{firstName}}",
        "{{firstName}} {{lastName}}"
    );
    protected static $firstName = array("Mark", "Adam");
    protected static $lastName = array("Clark", "Stewart");
    private static $prefix = array("Mr.", "Mrs.", "Ms.", "Miss", "Dr.");

    public static function prefix() {
        return static::randomElement(static::$prefix);
    }

    public static function firstName() {
        return static::prefix() . " " .
            static::randomElement(static::$firstName);
    }
}

Так как Student Если один и тот же метод определен для нескольких поставщиков, последний добавленный поставщик имеет приоритет над остальными.

 <?php
$faker = new FakerGenerator();
$faker->addProvider(new FakerProviderStudent($faker));

echo $faker->firstName; // invokes Student::firstName()

Более сложный пример

Встроенные поставщики содержат базовые типы данных для тестирования, но реальные случаи использования часто требуют большей сложности. В таких ситуациях нам необходимо создать наших собственных поставщиков данных и пользовательских наборов данных для автоматизации процедуры тестирования. Давайте создадим провайдера Faker с нуля, обслуживающего сценарий реального мира.

Предположим, мы разрабатываем почтовый маркетинговый сервис, который отправляет тысячи писем, содержащих различные виды рекламы от клиентов. Какие поля данных нам понадобятся для тестирования? В основном нам нужно по электронной почте, тему, имя. и контент для проверки электронной почты.

Давайте также предположим, что есть три типа шаблонов электронной почты:

  • реклама с текстовым / HTML контентом
  • реклама с одним полноразмерным изображением
  • реклама, содержащая ссылки на другие сайты

Поле содержимого будет одним из этих шаблонов, поэтому нам также понадобятся поля тестирования, текстовое содержимое, изображение и ссылки.

Поняв основные требования, мы можем создать провайдера следующим образом:

 <?php
namespace FakerProvider;

class EmailTemplate extends FakerProviderBase
{
    protected static $formats = array(
        '<p>Hello {{name}} </p>
        <p>{{text}}</p>
        <p>Newsletter by Exmaple</p>',

        '<p>{{adImage}}</p>
        <p>Newsletter by Exmaple</p>',

        '<p>Hello {{name}} </p>
        <p>{{link}}</p>
        <p>{{link}}</p>
        <p>{{link}}</p>
        <p>Newsletter by Exmaple</p>'
    );
    protected static $toEmail = array(
        "[email protected]",
        "[email protected]"
    );
    protected static $name = array("Mark", "Adam");
    protected static $subject = array("Subject 1", "Subject 2");
    protected static $adImage = array("img1.png", "img2.jpg");
    protected static $link = array("link1", "link2");
    protected static $text = array("text1", "text2");

    public static function toEmail() {
        return static::randomElement(static::$toEmail);
    }

    public static function name() {
        return static::randomElement(static::$name);
    }
    
    public function template() {
        $format = static::randomElement(static::$formats);
        return $this->generator->parse($format);
    }
}

Мы определили три формата для соответствия трем различным шаблонам, а затем создали наборы данных для каждого из полей, которые мы используем в процессе генерации тестовых данных. Все поля должны содержать методы форматирования, аналогичные toEmail()name() Метод template()

Мы можем получить тестовые данные, используя приведенный ниже код, и передать их в наше почтовое приложение.

 <?php
$faker = new FakerGenerator();
$faker->addProvider(new FakerProviderEmailTemplate($faker));

$email = $faker->toEmail; 
$subject =  $faker->subject;
$template = $faker->template;

Преимущество описанного выше метода заключается в том, что мы можем тестировать все три формата случайным образом, используя одного поставщика с прямым вызовом функции форматирования. Но что, если один из этих методов форматирования не работает или у нас есть сценарий, в котором нам нужно постоянно тестировать только один из форматов? Комментирование или удаление форматов вручную не является привлекательным вариантом.

В этом случае я бы рекомендовал создавать отдельные реализации для каждого формата. Мы можем определить базовый класс EmailTemplate Дочерние классы будут содержать только уникальный формат, и средства форматирования будут унаследованы от родительского класса. Затем мы можем по-разному использовать каждый шаблон электронной почты, загружая его отдельно в генератор Faker.

Согласованность данных испытаний

Обычно мы запускаем тесты много раз и записываем данные и результаты. Мы проверяем базу данных или файлы журналов, чтобы выяснить, какие были соответствующие данные при обнаружении ошибки. После того, как мы исправили ошибку, важно запустить тестовые случаи с теми же данными, которые вызвали ошибку. Faker использует заполнение, поэтому мы можем повторить предыдущие данные, заполнив его генератор случайных чисел.

Рассмотрим следующий код:

 <?php
$faker = FakerFactory::create();
$faker->seed(1000);
$faker->name;

Мы присвоили начальное значение 1000. Теперь, независимо от того, сколько раз мы выполняем вышеуказанный скрипт, имена будут одинаковой последовательностью случайных значений для всех тестов.

При тестировании приложения вы должны назначить начальное число для каждого теста и записывать его в свои журналы. Как только ошибки исправлены, вы можете получить начальные номера тестовых случаев, которые вызвали ошибки, и снова протестировать их с теми же данными, используя начальный номер, чтобы сделать его согласованным.

Вывод

Генерация тестовых данных — это то, что вы должны автоматизировать, чтобы избежать ненужной траты времени. Faker — это простое и мощное решение для генерации случайных тестовых данных. Настоящая сила Faker заключается в его способности расширять функциональные возможности по умолчанию для более сложных реализаций.

Какова ваша стратегия генерации тестовых данных? Вам нравится использовать Faker для автоматизации генерации тестовых данных? Дайте мне знать через раздел комментариев.

Изображение через Fotolia