Статьи

Руководство для начинающих по модульному тестированию: создание тестируемых тем

В первых двух статьях этой серии мы подробно рассмотрели, что такое модульное тестирование и как его применять в контексте разработки плагинов . Конечно, в WordPress есть нечто большее, чем написание плагинов, не так ли? Значительная часть работы разработчиков WordPress — для некоторых это самая значительная часть — это разработка тем.

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


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

  • Как объект, который инкапсулирует набор функций (что мы и сделали в этой статье ).
  • Как простой набор функций

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

Но когда дело доходит до разработки темы, на самом деле есть только один способ разработки темы — использование набора функций, определенных в functions.php . Это создает следующие две проблемы при написании модульных тестов для тем:

  • Поскольку тема не является объектно-ориентированной, у нас нет способа сохранить объект в массиве, как мы делали в предыдущей статье.
  • Мы должны определить способ написания и оценки функций нашей темы, которые могут работать независимо от загрузки темы в браузер.

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


Перед написанием кода давайте инициализируем каталог нашего проекта. Нам нужно настроить каркас темы, поэтому в каталоге тем WordPress создайте новый каталог для темы. Моя называется Basic-Theme . Добавьте следующие файлы (мы заполним их позже):

  • footer.php
  • functions.php
  • header.php
  • index.php
  • style.css

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

01
02
03
04
05
06
07
08
09
10
/*
Theme Name: Basic Theme
Theme URI: TODO
Version: 1.0
Description: A basic theme used to demonstrate how to write unit tests for themes.
Author: Tom McFarlin
Author URI: http://tommcfarlin.com
License: GNU General Public License v2.0
License URI: http://www.gnu.org/licenses/gpl-2.0.html
*/

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

И добавьте новый каталог с именем tests . Здесь нам нужно будет разместить тесты WordPress.


Ранее в этой серии я предоставил ссылку на тесты WordPress, расположенные на GitHub . Хотя эти тесты удобны в использовании, последние тесты WordPress, поддерживаемые Automattic, находятся в этом хранилище Subversion .

Если вы продвинутый разработчик, то я рекомендую проверить эти тесты; однако, если вы только начинаете с модульного тестирования — нет проблем! Я предоставляю весь исходный код, включая тесты WordPress, в репозитории GitHub, который вы сможете загружать, ссылать и использовать для своих собственных проектов.

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

Основная тема

Поскольку PHPUnit должен выполняться из командной строки, вам нужно открыть сеанс терминала (или командную строку), перейти к каталогу tests , и вы сможете запустить их, используя следующую команду (в качестве примера):

1
phpunit tests/test_user_capabilities.php

Ваш терминал должен затем вывести что-то вроде этого:

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

На данный момент, давайте продолжим активировать тему в Dashboard. Тема должна активироваться (если нет, убедитесь, что в файлах шаблонов нет случайных символов). Если вы попытаетесь просмотреть тему, она естественным образом отобразит белый экран.

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

В header.php добавьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
<!DOCTYPE html>
<html>
    <head>
        <meta charset=»UTF-8″>
        <link rel=»profile» href=»http://gmpg.org/xfn/11″ />
        <link rel=»pingback» href=»<?php bloginfo( ‘pingback_url’ ); ?>» />
        <title><?php wp_title( » );
        <?php wp_head();
    </head>
    <body <?php body_class();
     
        <div id=»header»>
            This is the header.
        </div><!— /#header —>

В index.php добавьте следующий код:

1
2
3
4
5
6
7
<?php get_header();
 
    <div id=»content»>
        This is the content.
    </div><!— /#content —>
 
<?php get_footer();

И в footer.php добавьте следующий код:

1
2
3
4
5
6
        <div id=»footer»>
            This is the footer.
        </div><!— /#footer —>
 
    </body>
</html>

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

Основная тема

В своем каталоге тестов создайте файл с именем test_basic_theme.php и удалите файл, чтобы он выглядел так:

1
2
3
4
5
6
// Include the functions for the theme
include_once(‘../functions.php’);
 
class Test_Basic_Theme extends WP_UnitTestCase {
     
} // end class

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

Сначала давайте определим метод setUp . Метод setUp — это функция, предоставляемая платформой WordPress Test, и мы можем использовать ее для запуска определенных функций перед запуском тестов. Например, когда запускаются тесты WordPress, они запускаются на тему по умолчанию, то есть Twenty Eleven. В нашем случае мы хотим запустить тесты против нашей собственной темы.

Чтобы сделать это, нам нужно сказать WordPress, что нужно переключать темы перед запуском остальных тестов. Поскольку это должно произойти до запуска тестов, его необходимо определить в методе setUp . Есть смысл?

Итак, давайте напишем наш метод setUp :

1
2
3
4
5
6
function setUp() {
     
    parent::setUp();
    switch_theme( ‘Basic Theme’, ‘Basic Theme’ );
     
} // end setup

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

1
phpunit tests/test_basic_theme.php

Если вы все сделали правильно, вы должны увидеть сбой при запуске теста:

Основная тема

Сообщение об ошибке ясно: « No tests found in class "Test_Basic_Theme" ». Итак, давайте смягчим это и напишем первый тест для темы. Это может быть что-то необычайно простое, но помните из предыдущего поста, что мы не хотим проверять только оптимальный путь, но также и путь отказа.

Таким образом, мы должны проверить, что Основная Тема активна, а Двадцать Одиннадцать не активна. Для этого мы будем использовать метод assertTrue и метод assertFalse, и мы будем делать это в контексте двух функций. Посмотрите на код ниже и обновите свой тестовый файл соответственно:

01
02
03
04
05
06
07
08
09
10
11
function testActiveTheme() {
 
    $this->assertTrue( ‘Basic Theme’ == get_current_theme() );
     
} // end testThemeInitialization
 
function testInactiveTheme() {
 
    $this->assertFalse( ‘Twenty Eleven’ == get_current_theme() );
 
} // end testInactiveTheme

Еще раз выполните тесты, и вы должны увидеть, что они работают зелеными. Хорошо, правда?

Основная тема

Это относительно простая функциональность, поэтому давайте рассмотрим несколько расширенных функций, которые может иметь наша тема.

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

  1. Написать тест
  2. Запустите тест (и он провалится)
  3. Напишите код, необходимый для прохождения теста
  4. Запустите тест (и он должен пройти, если шаг 3 был выполнен правильно)

Итак, давайте сделаем именно это для jQuery.

Во-первых, нам нужно написать тест, чтобы определить, загружен ли jQuery. Мы будем использовать функцию WordPress wp_script_is . Поскольку тема проходит обычный жизненный цикл страницы в браузере, нам нужно вручную указать WordPress загрузить jQuery с помощью функции do_action .

1
2
3
4
5
6
7
8
function testjQueryIsLoaded() {
 
    $this->assertFalse( wp_script_is( ‘jquery’ ) );
 
    do_action( ‘wp_enqueue_scripts’ );
    $this->assertTrue( wp_script_is( ‘jquery’ ) );
 
} // end testjQueryIsLoaded

Прежде чем мы пойдем дальше, отметим кое-что важное: мне не нравится помещать несколько утверждений в одну функцию, потому что я думаю, что каждая функция должна служить для проверки одной цели; Однако есть исключения. Здесь мы должны убедиться, что jQuery не загружен перед вызовом do_action .

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

1
2
3
4
5
6
function basic_add_jquery() {
 
    wp_enqueue_script( ‘jquery’ );
     
} // end basic_remove_jquery
add_action( ‘wp_enqueue_scripts’, ‘basic_add_jquery’ );

Наконец, запустите тест, и он должен быть зеленым. Достаточно просто, не правда ли?

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

1
2
3
4
5
6
function testBasicMetaDescription() {
     
    $meta_description = ‘<meta name=»description» content=»‘ . get_bloginfo( ‘description’ ) . ‘» />’;
    $this->expectOutputString( $meta_description, basic_meta_description() );
     
} // end testBasicMetaDescription

Запустите его — он потерпит неудачу. Обратите внимание, что я не использую стандартные функции assertTrue , assertFalse — подробнее об этом будет assertTrue assertFalse . Теперь давайте введем следующую функцию в functions.php :

1
2
3
4
5
6
function basic_meta_description() {
     
    echo ‘<meta name=»description» content=»‘ . get_bloginfo( ‘description’ ) . ‘» />’;
     
} // end basic_meta_description
add_action( ‘wp_head’, ‘basic_meta_description’ );

Обратите внимание, что эта функция wp_head действию wp_head . Чтобы записать мета-описание в элемент head, мы должны повторить строку, а не возвращать строку.

Теперь обратите внимание, что в приведенном выше тесте мы используем expectOutputString . Это полезно, когда нам нужно оценить функцию, которая отображает строку (а не возвращает строку). Поскольку действие wp_head вернет значительный объем данных (то есть весь элемент head), нам действительно нужно только оценить возвращаемое мета-описание. И поэтому вместо того, чтобы вызывать do_action( 'wp_head' ) , я просто do_action( 'wp_head' ) саму функцию и do_action( 'wp_head' ) .

Еще раз запустите PHPUnit, и все ваши тесты пройдут.


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

Помните, что это руководство для начинающих, и три статьи охватывают много вопросов.

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

Наконец, вы можете найти весь проект вместе с документированными функциями в этом репозитории GitHub .


Вот краткое изложение ресурсов, используемых в этой статье: