Тестирование приложений PHP

Эта статья была первоначально написана
Мауро Чойрин в блоге разработчиков Honeybadger.

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

Что такое автоматизированное тестирование?

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

Почему автоматизированное тестирование является хорошей идеей?

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

Вы можете быть скептически настроены, если никогда не использовали инструменты автоматизированного тестирования. В конце концов, если инструменты тестирования являются программным обеспечением, как уберечь их от ошибок? Справедливо. Хитрость здесь заключается в том, чтобы написать тесты таким образом, чтобы в случае обнаружения в них ошибки, ее было бы просто найти и исправить. Обычно это означает написание небольших тестов и объединение их в наборы тестов.

В итоге автоматизированное тестирование поначалу может показаться пустой тратой времени, поскольку в начале проекта оно отнимает много ресурсов, но долгосрочная отдача того стоит. Поверьте мне в этом вопросе.

Какие виды автоматизированного тестирования существуют?

Теперь, когда мы рассмотрели основные понятия, давайте сделаем еще один шаг вперед. Как вы, возможно, уже догадались (или где-то слышали), существует несколько типов автоматизированных тестов. Основное различие заключается в том, что именно тестируется. Вы можете думать об этом как о том, насколько близко к коду вы хотите видеть объектив. На самом крайнем этапе вы найдете юнит-тесты, а дальше всего, оставаясь актуальным, можно продвинуться в приемочном тестировании.

Другой способ классифицировать тесты — по тому, сколько знаний о тестируемой системе вы имеете. В этой схеме вы найдете то, что называется тестированием «белого ящика» и тестированием «черного ящика». В первом случае у вас есть доступ и возможность понять код, а во втором — наоборот.

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

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

В следующих разделах я покажу вам, как применить некоторые конкретные инструменты в реальном проекте. Эти примеры были построены и протестированы на php 8.0 на компьютере Ubuntu, а в качестве веб-браузера я использовал Google Chrome. Если ваша установка не совсем соответствует этим спецификациям, вам может потребоваться немного подправить команды.

Юнит-тесты

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

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

  • add
  • вычесть
  • умножить
  • делить

В случае метода add ожидание довольно ясно: он должен возвращать результат сложения двух чисел.

Поэтому наш класс должен выглядеть следующим образом:

declare(strict_types=1);

class Calculator
{
    public function add(int $a, int $b): int
    {
        return $a + $b;
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Существует множество инструментов, которые можно использовать для доказательства правильности работы этого метода. Самый популярный из них (на сегодняшний день!) — phpUnit.

Первое, что вы должны сделать, чтобы добавить его в свой проект, это установить инструмент. Лучший способ сделать это — добавить его в качестве зависимости от проекта. Предполагая, что ваш проект собран с помощью composer, все, что вам нужно сделать, это выполнить команду composer require --dev phpunit/phpunit, которая создаст новый файл в вашей директории vendor/bin: phpunit.

Итак, прежде чем двигаться дальше, убедитесь, что все на месте. Запустите vendor/bin/phpunit --version. Если все прошло успешно, вы должны увидеть что-то вроде этого:

PHPUnit 9.5.10 by Sebastian Bergmann and contributors.
Вход в полноэкранный режим Выход из полноэкранного режима

Отлично! Вы готовы протестировать свой код!

Конечно… это мало о чем говорит, если вы не написали ни одного теста, верно?

Итак, как написать свой первый юнит-тест с помощью phpUnit?

Начните с создания нового каталога tests в корне вашего проекта.

В ней создайте файл CalculatorTest.php и поместите в него следующее:

<?php

declare(strict_types=1);

use PHPUnitFrameworkTestCase;

final class CalculatorTest extends TestCase
{
        public function testAddAdds()
        {
                $sut = new Calculator();
                $this->assertEquals(8, $sut->add(5, 3));
        }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Перед запуском теста необходимо сделать несколько вещей:

  1. Файл конфигурации phpUnit (phpunit.xml.dist) в корне проекта.
  2. Скрипт bootstrap для введения автозагрузки.
  3. Определение автозагрузки.

Не беспокойтесь об этой части; она звучит гораздо хуже, чем есть на самом деле.

Конфиг phpUnit — это просто ярлык, чтобы избежать явного ввода опций каждый раз, когда вы запускаете команду phpunit. В нашем случае подойдет простой вариант, например, такой:

<phpunit
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/3.7/phpunit.xsd"
        backupGlobals="true"
        backupStaticAttributes="false"
        bootstrap="tests/bootstrap.php">
</phpunit>
Войти в полноэкранный режим Выйти из полноэкранного режима

Наиболее важной частью этого файла является определение bootstrap="tests/bootstrap.php", которое устанавливает tests/bootstrap.php в качестве точки входа в наш набор тестов, отсюда и необходимость создания такого файла.

Содержимое tests/bootstrap.php также не обязательно должно быть очень сложным. Этого будет вполне достаточно:

<?php

require_once __DIR__.'/../vendor/autoload.php';
Войти в полноэкранный режим Выйти из полноэкранного режима

Наконец, нам нужно сообщить composer о нашем отображении классов, чтобы автозагрузка прошла успешно. Просто добавьте следующее в ваш composer.json:

  "autoload": {
        "psr-4": {
            "" : "."
        }
    },
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем выполните команду composer dump-autoload для создания файла vendor/autoload.php, и вы будете готовы запускать свои тесты без сюрпризов.

Выполните команду vendor/bin/phpunit tests в корне вашего проекта, и вы увидите нечто подобное:

PHPUnit 9.5.10 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:00.003, Memory: 4.00 MB
OK (1 test, 1 assertion)
Вход в полноэкранный режим Выход из полноэкранного режима

Это означает, что утверждение (тот факт, что 8 равно результату Calculator::add(5, 3)) было проверено во время выполнения теста.

В phpUnit существует МНОГО нюансов. На самом деле, на эту тему написаны целые книги, и идея этой статьи не в том, чтобы рассмотреть один конкретный инструмент, а в том, чтобы дать вам обзор, чтобы вы могли прочитать дальше о тех, которые покажутся вам интересными. Тем не менее, один маленький самородок о phpUnit показался мне очень интересным, и я надеюсь, что он вызовет у вас любопытство. Посмотрите, что произойдет, если вы запустите свой тест, используя ./vendor/bin/phpunit tests --testdox:

PHPUnit 9.5.10 by Sebastian Bergmann and contributors.

Calculator
 ✔ Add adds

Time: 00:00.003, Memory: 4.00 MB

OK (1 test, 1 assertion)
Войти в полноэкранный режим Выход из полноэкранного режима

Неплохо, верно? Но… откуда взялся этот текст? Он был взят прямо из названия метода тестирования, так что … следите за названиями своих тестов!

Интеграционные тесты

Следующий шаг на нашем пути — интеграционные тесты. Эти тесты призваны доказать, насколько хорошо одни компоненты работают вместе с другими.

Сначала этот тип тестирования может показаться излишним. В конце концов, если каждый отдельный модуль выполняет свою работу, зачем нужны дополнительные тесты? Что ж… позвольте мне дать вам наглядное объяснение:

Вы определенно не хотите оказаться в такой ситуации.

Это может быть неожиданностью, но, несмотря на свое название, phpUnit также может быть использован для написания такого рода тестов.

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

Это будет выглядеть примерно так:

<?php

declare(strict_types=1);

class NumberCollection
{
    private array $numbers;
    private Calculator $calculator;

    public function __construct(array $numbers, Calculator $calculator)
    {
        $this->numbers = $numbers;
        $this->calculator = $calculator;
    }

    public function sum() : int
    {
        $acum = 0;

        foreach ($this->numbers as $number) {
            $acum = $this->calculator->add($acum, $number);
        }

        return $acum;
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

В этом примере видно, как Калькулятор внедряется в Коллекцию чисел. Хотя мы могли бы написать код так, чтобы конструктор создавал экземпляр Calculator, это, помимо прочих проблем, значительно усложнило бы написание наших тестов, особенно юнит-тестов.

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

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

Как я это сделаю? Ну… не очень отличается от того, что я делал до сих пор. Вот как будет выглядеть тест:

<?php

use PHPUnitFrameworkTestCase;

class NumberCollectionTest extends TestCase
{
    public function testSum()
    {
        $numbersList = [6, 5, 6, 9];
        $numberCollection = new NumberCollection($numbersList, new Calculator());

        $this->assertEquals(array_sum($numbersList), $numberCollection->sum(), 'Sum doesn't match');
    }
}
Войти в полноэкранный режим Выход из полноэкранного режима

А затем, запустив vendor/bin/phpunit tests/NumberCollectionTest.php я получу следующее:

PHPUnit 9.5.10 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:00.003, Memory: 4.00 MB

OK (1 test, 1 assertion)
Вход в полноэкранный режим Выход из полноэкранного режима

Разница между этим и модульным тестом заключается в том, что в последнем случае я использую макет вместо реального класса Calculator, поскольку я хочу протестировать только NumberCollection, предполагая, что Calculator работает так, как ожидается.

Приемочные тесты

Еще одна категория тестов, которые вы можете использовать, — это приемочные тесты. Эти тесты предназначены для выполнения нетехническими людьми, что означает, что пользователь просто нажимает на кнопки и улыбается результатам (или плачет, или кричит, как знать).

Такой тип тестов явно не будет очень воспроизводимым и тем более эффективным, верно? Цель такого теста — имитировать действия реального пользователя.

В случае с PHP-приложением есть шанс, что мы говорим о веб-приложении. Поэтому для его тестирования, безусловно, пригодится веб-браузер.

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

Давайте начнем с внедрения его в наш проект.

Начнем с запуска composer require "codeception/codeception" --dev. Это загрузит и установит все необходимые библиотеки в вашу директорию vendor.

Затем инициализируйте среду CodeCeption командой php vendor/bin/codecept bootstrap, которая должна выдать следующий результат:

❯ php vendor/bin/codecept bootstrap
 Bootstrapping Codeception 

File codeception.yml created       <- global configuration
 Adding codeception/module-phpbrowser for PhpBrowser to composer.json
 Adding codeception/module-asserts for Asserts to composer.json
2 new packages added to require-dev
? composer.json updated. Do you want to run "composer update"? (y/n)
Вход в полноэкранный режим Выйти из полноэкранного режима

Ответьте y и дождитесь завершения загрузки всех вспомогательных пакетов.

Теперь, чтобы действительно воспользоваться преимуществами CodeCeption, нужно многое сделать. На данный момент давайте сосредоточимся на создании приемочного теста. Для этого нам понадобится приложение, которое можно тестировать через браузер.

Давайте вернемся к нашему маленькому калькулятору и добавим к нему веб-интерфейс.

Создайте каталог web в корне вашего проекта и поместите следующий код в файл index.php:

<?php
require_once '../vendor/autoload.php';

session_start();

if ('post' === strtolower($_SERVER['REQUEST_METHOD'])) {
    $_SESSION['numbers'][] = (int)$_POST['newNumber'];
}

$numbers = $_SESSION['numbers'] ?? [];
$numbersCollection = new NumberCollection($numbers, new Calculator());
?>
<html>
<body>
    <p>Numbers entered: <b><?php echo implode(', ', $numbers); ?></b></p>
    <p>Sum: <b><?php echo $numbersCollection->sum();?></b></p>
    <hr/>
    <form method="post">
        <label for="newNumber">Enter a number between 1 and 100:</label>
        <input type="number" min="1" max="100" name="newNumber" id="newNumber"/>
        <input type="submit" value="Add it!"/>
    </form>
</body>
</html>
Вход в полноэкранный режим Выйти из полноэкранного режима

Теперь запустите встроенный веб-браузер, выполнив php -S localhost:8000 -t web, и вуаля, у вас есть красивый веб-интерфейс по адресу http://localhost:8000, который должен выглядеть примерно так, как показано ниже:

Теперь, когда у нас все готово, давайте вернемся к нашей первоначальной цели: составить приемочный тест.

Для этого нам нужно немного подправить конфигурацию по умолчанию.

Откройте файл tests/acceptance.suite.yml и отредактируйте его так, чтобы он выглядел следующим образом:

# Codeception Test Suite Configuration
#
# Suite for acceptance tests.
# Perform tests in browser using the WebDriver or PhpBrowser.
# If you need both WebDriver and PHPBrowser tests - create a separate suite.

actor: AcceptanceTester
modules:
    enabled:
        - WebDriver:
            url: http://localhost:8000
            browser: chrome
        - HelperAcceptance
step_decorators: ~        
Войти в полноэкранный режим Выйти из полноэкранного режима

Здесь мы просим CodeCeption запустить наши тесты в реальном веб-браузере, поэтому нам понадобится поддержка пары вспомогательных инструментов:

  1. модуль WebDriver от CodeCeption
  2. ChromeDriver .

Чтобы установить модуль WebDriver, просто выполните команду composer require codeception/module-webdriver --dev.

Чтобы установить ChromeDriver, сначала проверьте версию вашего Chrome, зайдя в раздел Help -> About Chrome. Узнав точный номер установленной версии, перейдите сюда и загрузите версию, соответствующую вашей установке.

Когда все будет готово, запустите ./chromedriver --url-base=/wd/hub --white-list-ip 127.0.0.1, чтобы инициировать сервер драйверов Chrome.

Знаю, знаю… кажется, что слишком много работы только для того, чтобы провести несколько тестов, верно? Возможно, это так, но помните, что это то, что вы сделаете всего один раз, а затем это сделает ваши приложения намного проще в тестировании и, следовательно, намного надежнее.

Пришло время посмотреть на реальный php-код, не так ли? Давайте перейдем прямо к нему!

Используйте эту команду, чтобы создать свой первый приемочный тест на основе CodeCeption: vendor/bin/codecept g:cest acceptance First, а затем откройте файл tests/acceptance/FirstCest.php, чтобы найти следующее:

<?php

class FirstCest
{
    public function _before(AcceptanceTester $I)
    {
    }

    // tests
    public function tryToTest(AcceptanceTester $I)
    {
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Не очень похоже, не так ли? Потерпите минутку, сейчас начнется волшебство.

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

Отредактируйте метод tryToTest класса FirstCest так, чтобы он выглядел следующим образом:

    public function tryToTest(AcceptanceTester $I)
    {
        $I->amOnPage('index.php');
        $I->amGoingTo('put a new number into the collection');
        $I->see('Numbers entered:');
        $I->see('Sum:');
        $newNumber = rand(1, 100);
        $I->fillField('newNumber', $newNumber);
        $I->click('Add it!');
        $I->wait(2);
        $I->see('Numbers entered: '.$newNumber);
        $I->see('Sum: '.$newNumber);
    }
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем запустите vendor/bin/codecept run acceptance.

Приступайте; я подожду здесь.

Готово? Хорошо.

Думаю, теперь вы понимаете, почему мне так нравится CodeCeption. Если нет, посмотрите назад на тест, который вы только что написали. Обратите внимание, как ясно и легко он был написан. Он, конечно, намного чище и элегантнее, чем его голый аналог phpUnit, верно?

Дело в том, что за кулисами CodeCeption использует phpUnit для выполнения тестов, но это поднимает опыт на совершенно новый уровень.

Методологии тестирования

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

Давайте рассмотрим два наиболее популярных из них.

TDD в PHP

Аббревиатура TDD расшифровывается как Test Driven Development. Идея заключается в том, чтобы написать тесты до написания кода. Звучит странно, не так ли? Как вы узнаете, что тестировать, пока код не написан? Именно в этом и заключается идея. Речь идет о написании минимального кода, необходимого для прохождения тестов.

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

Что касается инструментов, то здесь не так уж много нужно добавить к тому, что мы уже обсудили. Обычно phpUnit является предпочтительным инструментом для такого рода тестов; единственное, что меняется, — это порядок выполнения.

BDD в PHP

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

  1. Протестировать
  2. Написать работающий код
  3. Настроить
  4. Вернуться к 1

Однако способ написания тестов радикально отличается. На самом деле, тесты должны быть написаны на языке, понятном как разработчикам, так и бизнесменам (т.е. на примерах). Существует язык, разработанный специально для этой цели; он называется Gherkin.

Давайте рассмотрим на примере нашего приложения «Калькулятор»:

Feature: Numbers collection
  In order to calculate the sum of a series of numbers
  As a user
  I need to be able to input numbers

  Rules:
  - Numbers should be integers between 1 and 100

  Scenario: Input the first number
    Given the number series is empty
    When I enter 2
    Then The number series should contain only 2
    And The sum should be 2

  Scenario: Input the second number
    Given the number series contains 5
    When I enter 10
    Then The number series should contain 5 and 10
    And The sum should be 15    
Войти в полноэкранный режим Выйти из полноэкранного режима

Чтобы что-то сделать с этим определением, нам нужно подключить Behat. Как обычно, мы будем полагаться на Composer, чтобы помочь с этой задачей.

Выполните команду composer require --dev behat/behat. Затем нам нужно инициализировать набор тестов командой vendor/bin/behat --init. Эта команда создаст базовую структуру, необходимую для работы Behat. Наиболее важной частью этого является создание каталога features, где будут находиться описания наших функций.

Естественно, следующий шаг — взять написанный нами текст Gherkin и сохранить его в файле .feature. В нашем случае назовем его number_collection.feature.

Итак, мы готовы приступить к работе. Запустите vendor/bin/behat --append-snippets, и вы увидите, как Behat интерпретирует вашу функцию, распознавая два сценария и восемь шагов.

Поскольку вы впервые запускаете Behat на этом проекте, вам предстоит довольно много работы. В конце концов, определение текста выглядит великолепно, но когда дело доходит до того, чтобы компьютер сверил его с реальностью, боюсь, что ИИ еще не так далеко продвинулся. Нам придется помочь ему, заполняя пробелы.

В конце концов, у вас должен получиться файл features/bootstrap/FeatureContext.php, который выглядит следующим образом:

<?php

use BehatBehatContextContext;
use BehatGherkinNodePyStringNode;
use BehatGherkinNodeTableNode;

/**
 * Defines application features from the specific context.
 */
class FeatureContext implements Context
{
    /**
     * Initializes context.
     *
     * Every scenario gets its own context instance.
     * You can also pass arbitrary arguments to the
     * context constructor through behat.yml.
     */
    public function __construct()
    {
    }

    /**
     * @Given the number series is empty
     */
    public function theNumberSeriesIsEmpty()
    {
        throw new PendingException();
    }

    /**
     * @When I enter :arg1
     */
    public function iEnter($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Then The number series should contain only :arg1
     */
    public function theNumberSeriesShouldContainOnly($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Then The sum should be :arg1
     */
    public function theSumShouldBe($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Given the number series contains :arg1
     */
    public function theNumberSeriesContains($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Then The number series should contain :arg1 and :arg2
     */
    public function theNumberSeriesShouldContainAnd($arg1, $arg2)
    {
        throw new PendingException();
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Потратьте минуту, чтобы просмотреть этот файл.

Вы должны заметить, что существует четкое соответствие между текстовым определением, которое вы создали с помощью Gherkin, и именами методов, созданными Behat. Конечно, это не совпадение. Более того, посмотрите на аннотации над именами методов. Там происходит декларация точного соответствия между определениями Gherkin и кодом, который сделает их исполняемыми.

Выглядит красиво, не так ли?

Но есть небольшая проблема. Этот код, сам по себе, мало что делает. Здесь не хватает настройки контекста для выполнения теста. По сути, вы должны инициализировать объекты, необходимые для последующего тестирования, в методах, определенных аннотацией @Given, изменения, внесенные в них в методах, аннотированных @When, и, наконец, утверждения, необходимые для подтверждения ожиданий, выраженных аннотацией @Then.

Давайте рассмотрим полный пример для наглядности:

<?php

declare(strict_types=1);
use BehatBehatContextContext;
use BehatGherkinNodePyStringNode;
use BehatGherkinNodeTableNode;
use NumberCollection;
use PHPUnitFrameworkAssert;

/**
 * Defines application features from the specific context.
 */
class FeatureContext implements Context
{
    private NumberCollection $numberCollection;

    /**
     * Initializes context.
     *
     * Every scenario gets its own context instance.
     * You can also pass arbitrary arguments to the
     * context constructor through behat.yml.
     */
    public function __construct()
    {
        $this->numberCollection = new NumberCollection([], new Calculator());
    }

    /**
     * @Given the number series is empty
     */
    public function theNumberSeriesIsEmpty()
    {
    }

    /**
     * @When I enter :arg1
     */
    public function iEnter(int $arg1)
    {
        $this->numberCollection->append($arg1);
    }

    /**
     * @Then The number series should contain only :arg1
     */
    public function theNumberSeriesShouldContainOnly(int $arg1)
    {
        $numbers = $this->numberCollection->getNumbers();
        Assert::assertContains($arg1, $numbers);
        Assert::assertCount(1, $numbers);
    }

    /**
     * @Then The sum should be :arg1
     */
    public function theSumShouldBe(int $arg1)
    {
        Assert::assertEquals($arg1, $this->numberCollection->sum());
    }

    /**
     * @Given the number series contains :arg1
     */
    public function theNumberSeriesContains(int $arg1)
    {
        $this->numberCollection->append($arg1);
    }

    /**
     * @Then The number series should contain :arg1 and :arg2
     */
    public function theNumberSeriesShouldContainAnd(int $arg1, int $arg2)
    {
        Assert::assertContains($arg1, $this->numberCollection->getNumbers());
        Assert::assertContains($arg2, $this->numberCollection->getNumbers());
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

Behat — это замечательно, но она не единственная. На самом деле, CodeCeption также поддерживает Gherkin.

Некоторые другие интересные инструменты тестирования на основе PHP

В этом разделе я вкратце расскажу о некоторых инструментах, которые я еще не успел опробовать сам, но которые выглядят многообещающе:

  • Infection: инструмент для тестирования мутаций
  • Pest: фреймворк для тестирования, разработанный в соответствии со стандартами кодирования Laravel
  • Atoum: простой фреймворк для тестирования PHP
  • phpSpec: еще один BDD-фреймворк для PHP

Вы можете получить полный пример с GitHub, если хотите проверить его.

Подведение итогов

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

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

Время профессиональных PHP-разработчиков пришло; не оставайтесь позади.

Оцените статью
devanswers.ru
Добавить комментарий