PHP: Объектно-ориентированный дизайн

PHPUnit

Практика на Хекслете проверяется автоматическими тестами, к которым вы уже немного привыкли, если смогли добраться до текущего урока. Для тестирования PHP-кода мы используем фреймворк PHPUnit, который, хоть и не единственный, но до сих пор — самый популярный. Имея некоторое представление об ООП, мы можем поговорить о его устройстве.

<?php

namespace App\Tests;

use PHPUnit\Framework\TestCase;

use function App\Math\average;

// Единственная незнакомая синтаксическая конструкция в этом тесте — `extends TestCase`.
// С её помощью реализуется наследование. О наследовании пойдёт разговор в следующих курсах,
// а сейчас достаточно знать, что все методы, которые мы вызываем внутри нашего теста,
// определены в классе `TestCase`, и именно наследование позволяет их использовать.

class MathTest extends TestCase
{
    public function testAverage()
    {
        $this->assertEquals(0, average(0));
        $this->assertEquals(5, average(0, 10));
    }
}

Не имеет значения предмет тестирования; любой тест PHPUnit всегда описывается в классе с именем Что-тоTest внутри директории tests. Если тестируется какой-то конкретный класс с именем Foo, то по соглашению его тесты располагаются в классе FooTest. Точно такое же правило с пространством имён без классов. Как правило, структура директорий внутри tests совпадает со структурой исходных файлов — так проще ориентироваться, и некоторые редакторы позволяют автоматически переключаться между тестом и исходным файлом при такой структуре и именовании.

src/                                tests/
`-- Money/Currency.php              `-- Money/CurrencyTest.php
`-- IntlFormatter.php               `-- IntlFormatterTest.php
`-- Money.php                       `-- MoneyTest.php

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

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

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

  1. Expected. Ожидаемый результат — то, что должна вернуть функция.
  2. Actual. Результат, который на самом деле вернула функция.

Порядок важен. На его основе PHPUnit формирует вывод, в котором указывает, что ожидалось, а что пришло на самом деле.

Другое популярное утверждение assertTrueassertFalse). Оно принимает только один аргумент и отлично подходит для тестирования предикатов.

Анализ дизайна

Дизайн тестов на основе классов теряет свою популярность, а во многих языках уже давно не используется. Современный подход растёт из BDD процесса. Синтаксически такие тесты часто полагаются на функции высшего порядка describe и it.

<?php

describe('Example', function () {
    $object = new stdClass();
    $object->name = 'pho';

    context('name', function () use ($object) {
        it('is set to pho', function()  use ($object) {
            expect($object->name)->toBe('pho');
        });
    });
});

Замечу, что в PHP такой стиль выглядит немного тяжёлым из-за обилия синтаксических конструкций.


Дополнительные материалы

  1. Официальная документация
  2. Behat (BDD Framework)
  3. Codeception (Браузерные тесты)
  4. Начинаем писать тесты (Правильно)

<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Для полного доступа к курсу нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».