Модульные тесты PHP

задняя часть PHP контрольная работа модульный тест

Эта статья была впервые опубликована на https://jaychen.cc/article/34.

Автор Джейчен

Друзья, вы слышали об Энн. . . Нет, вы написали модульные тесты?

Модульное тестирование — неотъемлемая часть процесса разработки.У проекта есть хороший код модульного тестирования, и смелости для рефакторинга гораздо больше. На этот раз я напишу небольшую статью, чтобы представить использование PHPUnit, инструмента модульного тестирования для PHP.

Использование PHPUnit не сложно.Эта статья в основном используется в качестве введения для ознакомления с основными понятиями и использованием.С основой этой статьи будет легче читать документацию на официальном сайте.

Установить

Способ установки PHPUnit очень прост, вы можете установить его одной строкой кода, используя composer.

composer require --dev phpunit/phpunit

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

➜  phpunit tree .

├── controller
├── model
├── service
├── test
└── vendor
├── composer.json

Среди них наш код модульного теста находится в каталоге test. Используйте composer, чтобы решить проблему с автозагрузкой.

{
  "autoload": {
    "psr-4": {
      "Controller\\": "controller/",
      "Model\\": "model/",
      "Service\\": "service/",
      "Test\\": "test/",
    }
  },
}

Если вы не понимаете использование автозагрузки композитора, вы можете обратиться кэта статья. окончательное исполнениеcomposer dumpautoload -oЗаставьте автозагрузку работать.

На этом наша установка окончена. Если вы используете phpstorm для разработки, то вам необходимо настроить следующее:

Это указывает, где загрузить PHPUnit.Поскольку мы используем композитор для установки, выберите файл autoload.php, сгенерированный композитором для файла здесь.

использовать

Хорошо, допустим, мы сейчас разрабатываем и добавляемCalculateServiceфайл и написал функцию abs.

namespace Service;

class CalculateService
{
    public function abs($num)
    {
        return abs($num);
    }
}

Теперь мыabsФункция unit test, PHPUnit test указанного класса, должна соответствовать следующим положениям:

  • Установка тестовых классов Имя тестирования должно быть заканчивается, должен наследовать\PHPUnit\Framework\TestCaseбазовый класс.
  • Каждая тестовая функция должна начинаться с test.

Приведенные выше правила должны соблюдаться.Если код не соответствует правилам, PHPUnit не будет рассматривать его как код модульного теста. В дополнение к двум вышеупомянутым, есть несколько хороших привычек кодирования для справки:

  • Код модульного теста помещается в каталог test.
  • Каждый класс модульного теста начинается с имени тестируемого класса. Например, тестируемый классCalculateService, Тогда классы модульных тестов должны бытьCalculateServiceTest.
  • Каждая функция модульного тестирования должна заканчиваться именем тестируемой функции. Например, тестируемая функцияabs, то функция модульного тестирования должна бытьtestAbs.

В соответствии с приведенной выше спецификацией напишите код модульного теста

class UserServiceTest extends \PHPUnit\Framework\TestCase
{
    public function testAbs()
    {
        $userService = new \Service\CalculateService();
        $this->assertEquals(4, $userService->abs(4));
    }
}

В приведенном выше тестовом коде функция, которую мы хотим протестировать, называетсяabs, а затем утверждать$userService->abs(4)Результат 4. прямо в phpstormtestAbsЩелкните правой кнопкой мыши функциюrun UserServiceTestвоплощать в жизнь:

Обнаружено, что в консоль будет выведено следующее

Time: 17 ms, Memory: 4.00MB

OK (1 test, 1 assertion)

показыватьabsпрошедший$userService->abs(4) == 4Прецедент.Обратите внимание, что это не означает, чтоabsФункция была протестирована, и хороший тест должен содержать несколько тестовых случаев, чтобы охватить как можно больше возможностей.

Теперь, когда базовые модульные тесты PHPUnit успешно выполнены, вДокументация для PHPUnit, чтобы узнать больше об использовании тестов. Из-за того, что PHPUnit используется слишком часто, мы не можем объяснить их здесь по отдельности.Вот некоторые другие варианты использования.

  • PHPUnit предоставляет@testаннотацию, если тестовая функция добавляет@testаннотация, имя тестовой функции не обязательно должно начинаться с test.

  • \PHPUnit\Framework\TestCaseсуществует одинsetUpфункция, если написанный вами тестовый класс переопределяет эту функцию, то каждый раз перед началом выполнения тестовой функции она будет выполняться первойsetUpИнициализировать перед тестированием. Аналогично, существует такжеtearDownФункция, если она переопределена, вызывается после завершения выполнения тестовой функции.tearDownфункция.

  • .... Для получения дополнительной информации обратитесь к документации PHPUnit.

файл phpunit.xml

В приведенном выше примере мы используем phpstorm для выполнения тестовых функций одну за другой, но если нам нужно выполнить все модульные тесты одновременно, мы можем написать файл phpunit.xml для этого.

Приведите пример написания phpunit.xml, объясняющий роль phpunit.xml.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
    <testsuites>
        <testsuite>
            <directory>test</directory>
        </testsuite>
    </testsuites>
</phpunit>

здесь<directory>test</directory>Укажите, что тестовый код находится в тестовом каталоге, щелкните правой кнопкой мыши файл phpunit.xml в разделе phpstorm и выберитеRun phpunit.xml, phpunit перейдет в каталог test, чтобы найти все модульные тесты и выполнить их один за другим.

В дополнение к использованию phpunit.xml для одновременного выполнения всех модульных тестов, вы также можете настроить выходное журналирование результатов модульных тестов в phpunit.xml.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
	.....
    <logging>
        <log type="testdox-html" target="tmp/log.html"/>
    </logging>
</phpunit>

На этом этапе при выполнении файла phpunit.xml в каталоге проекта будет создан файл.tmp/log.htmlфайл, этот файл записывает результаты всех модульных тестов.

Конечно, для получения дополнительной информации, связанной с конфигурацией phpunit.xml, вам все равно нужно проверить документацию. :смеющийся:

Пробный тест

PHPUnit также предоставляет пробные тесты. Вот введение в то, что такое пробный тест.

Предполагая, что функция foo вызывает функцию bar, есть две проблемы с модульным тестированием функции foo:

  • Функция foo зависит от результата функции bar, поэтому bar должен быть введен, когда foo тестируется модульно, поэтому субмодульный тест не имеет смысла.Если тест не пройден, нет гарантии, что ошибка находится в foo или bar.
  • Функция BAR не может выполняться в тестовой среде, тогда Foo не может получить результат выполнения BAR, поэтому FOO не разрешено модульное тестирование.

Мок-тест, по-видимому, решает указанную выше проблему.Используя Мок, мы можем виртуализировать вызов bar и предположить, что вызов bar возвращает результат. Если вы все еще не понимаете, вы будете знать предыдущий код.

class MockTest extends \PHPUnit\Framework\TestCase {
	public function testGet()
	{  
		$stub = $this->createMock(\App\UserService::class);     //1
		$stub->method('get')->willReturn(3); 					//2
		$this->assertEquals(3,$stub->get(1));  					//3
	} 
}

Приведенная выше тестовая функция использует Mock, который анализируется построчно:

  • Первая строка создает фиктивныйUserServiceобъект.
  • Вторая строка предполагаетUserServiceсерединаgetВозвращаемое значение функции равно 3.
  • Третья линия звонит$stub->get(1)на самом деле не будет выполнятьсяgetфункцию, а согласно второй строкеwillReturnФункция возвращает 3 напрямую.

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

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