Вопрос:

Как протестировать функцию в PHPUnit, которая умножает аргумент на случайное число и возвращает результат умножения?

Ответ:

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

(звезда) Ньюанс: не достаточно переопределить ф-ю getRand, ф-ю ее вызывающую также обновить нужно: иначе она вызовет оригинальную getRand()

Например:

Нужно протестировать multiplyByRandom в классe: Randomizer.php

<?php

/**
 * Класс со случайным числом
 */
class Randomizer
{
    /**
     * @return int
     */
    public function getRand(): int
    {
        return mt_rand(1, 10);
    }

    /** Тестируемая функция
     * @param int $num
     * @return int
     */
    public function multiplyByRandom(int $num): int
    {
        return $num * $this->getRand();
    }
}

Скрипт тестирования: MultTest.php

<?php

use PHPUnitFrameworkTestCase;

require_once("Randomizer.php");

class MultTest extends TestCase
{
    // Тест рандомной функции
    public function testMultiply()
    {
        // Создаем мок
        $randMock = $this->createStub(Randomizer::class);

        // Задаем последовательность значений
        $randMock->expects($this->exactly(4))
                 ->method('getRand')
                 ->willReturnOnConsecutiveCalls(2, 7, 6, 5);

        // Не достаточно переопределить ф-ю getRand,
        // ф-ю ее вызывающую также обновить нужно: иначе она вызовет оригинальную getRand()
        $randMock->expects($this->exactly(4))
            ->method('multiplyByRandom')
            ->willReturnCallback(function (&$x) use ($randMock) {
                return $x * $randMock->getRand();
            });

        // Инжектим мок в функцию и Проверяем результат
        $result = $randMock->multiplyByRandom(3);
        $this->assertEquals(6, $result);        // 2 * 3 = 6

        $result = $randMock->multiplyByRandom(10);
        $this->assertEquals(70, $result);       // 10 * 7 = 70

        $result = $randMock->multiplyByRandom(20);
        $this->assertEquals(120, $result);      // 20 * 6 = 120

        $result = $randMock->multiplyByRandom(0);
        $this->assertEquals(0, $result);        // 0 * 5 = 0
    }
}

(warning) Таким образом мы имитируем поведение Randomizer и можем протестировать функцию для разных фиксированных случайных значений.


PS: рекомендую к изучению курс “Otus php professional“ (который я прошел), там рассматривается глубоко в т.ч. тема тестирования веб-приложений

Tags

Нет Ответов

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

Рубрики


Подпишись на новости
👋

Есть вопросы?