Руководство для начинающих по модульному тестированию: что такое модульное тестирование?
() translation by (you can also view the original English article)
В зависимости от вашего образования вы могли слышать о модульном тестировании, разработке на основе тестирования, разработке на основе поведения или методологии тестирования другого типа. Часто эти методологии применяются в контексте более крупных программных систем или приложений и реже в контексте проектов на основе WordPress (хотя зачастую это улучшает!)
Честно говоря, сообщество разработчиков немного разделено на автоматическое тестирование программного обеспечения - у вас есть люди, которые считают, что вам нужно иметь тесты для 100% всего вашего кода, некоторые считают, что 80% достаточно, другие 50%, а некоторые довольны 20% или около того. В любом случае может быть, эта статья не о утверждая случай для уровня тестов, что вы должны иметь в вашем проекте не занимает позицию на тестирование общего программного обеспечения.
Вместо этого мы собираемся взглянуть на то, что требуется для начала работы с модульным тестированием ваших проектов в WordPress. Мы собираемся приближаться к этой серии с точки зрения абсолютного новичка, чтобы мы могли понять преимущества модульного тестирования и как настроить нашу среду для поддержки библиотек модульного тестирования, чтобы мы могли использовать это в будущих проектах. Наконец, все это будет сделано путем создания и тестирования простого плагина.
Что такое модульное тестирование?
Прежде чем приступить к настройке нашей среды и написанию какого-либо кода, давайте точно определим, что такое модульное тестирование, почему это стоит делать и как начать включать его в наши проекты.
На высоком уровне модульное тестирование относится к практике тестирования определенных функций и областей - или блоков - нашего кода. Это дает нам возможность убедиться, что наши функции работают как и предполагалось. То есть, для любой функции и заданного набора входных данных мы можем определить, возвращает ли функция правильные значения и будет ли она корректно обрабатывать сбои в ходе выполнения, если будет предоставлен неверный ввод.
В конечном счете, это помогает нам выявлять сбои в наших алгоритмах и/или логике, чтобы улучшить качество кода, составляющего определенную функцию. Когда вы начинаете писать все больше и больше тестов, вы в конечном итоге создаете набор тестов, которые вы можете запускать в любое время в процессе разработки, чтобы постоянно проверять качество своей работы.
Второе преимущество подхода к разработке с точки зрения модульного тестирования состоит в том, что вы, вероятно, будете писать код, который легко тестировать. Поскольку модульное тестирование требует, чтобы ваш код был легко тестируемым, это означает, что ваш код должен поддерживать этот конкретный тип оценки. Таким образом, вы, скорее всего, будете иметь большее количество меньших, более сфокусированных функций, которые обеспечивают одну операцию над набором данных, а не большие функции, выполняющие ряд различных операций.
Третье преимущество написания надежных модульных тестов и хорошо протестированного кода заключается в том, что вы можете предотвратить нарушение функциональности в будущих изменениях. Поскольку вы тестируете свой код при представлении своей функциональности, вы начнете разрабатывать набор тестовых случаев, которые можно запускать каждый раз, когда вы работаете над логикой. Когда происходит сбой, вы знаете где искать причину.
Конечно, это происходит за счет затрат времени на написание набора тестов на ранних стадиях разработки, но по мере роста проекта вы можете просто запускать разработанные тесты, чтобы гарантировать, что существующие функциональные возможности не будут нарушены, когда новые будут добавлены.
Планирование нашего плагина
Один из лучших способов начать работу с модульным тестированием - это сделать это в контексте практического применения. В этой серии из двух частей мы собираемся создать простой плагин и написать тесты, чтобы охватить все функциональные возможности.
Во-первых, давайте спланируем проект: мы напишем небольшой плагин, который добавит простое сообщение в верхней части одного сообщения, которое приветствует пользователя в зависимости от того, как он нашел конкретное сообщение в блоге. Идея очень похожа на Welcome Reader, но она не будет включать в себя почти такую же функциональность - мы просто создаем демоверсию, чтобы изучить все тонкости тестирования.
Во всяком случае, вот как плагин будет работать:
- Если пользователь перейдет на сайт из Google, мы дадим уникальное сообщение
- Если пользователь переходит на сайт из Twitter, мы дадим уникальное сообщение
- В противном случае мы не будем ничего отображать
Достаточно просто, не так ли? Это также послужит основой для добавления пользовательских сообщений для других служб и дальнейшего расширения наших возможностей модульного тестирования, если вы захотите это сделать.
Подготовка среды разработки
Для модульного тестирования нашего кода нам понадобится сторонняя библиотека, которую мы включим в наш проект, которая будет фактически выполнять тесты, которые мы пишем. В этой серии мы будем использовать PHPUnit. Вы можете получить копию здесь.
Далее нам нужно подготовить нашу среду разработки, обрезать наш плагин и включить необходимые библиотеки для тестирования нашего кода. В этой статье предполагается, что у вас уже установлена и запущена функциональная установка WordPress.
Итак, для начала давайте подготовим каталог плагинов:
- В /wp-content/plugins создайте каталог с именем Hello-Reader
- В каталоге Hello-Reader создайте файл с именем plugin.php и каталог с именем tests
- Мы отключим плагин, чтобы убедиться, что WordPress правильно видит наш проект
- Мы импортируем библиотеки модульного тестирования, чтобы начать писать наши тесты.
Вот скелет для плагина, который мы будем создавать:
1 |
/*
|
2 |
Plugin Name: Hello Reader
|
3 |
Plugin URI: http://github.com/tommcfarlin/Hello-Reader
|
4 |
Description: A simple plugin used to help demonstrate unit testing in the context of WordPress.
|
5 |
Version: 1.0
|
6 |
Author: Tom McFarlin
|
7 |
Author URI: http://tom.mcfarl.in
|
8 |
Author Email: tom@tommcfarlin.com
|
9 |
License:
|
10 |
|
11 |
Copyright 2012 Tom McFarlin (tom@tommcfarlin.com)
|
12 |
|
13 |
This program is free software; you can redistribute it and/or modify
|
14 |
it under the terms of the GNU General Public License, version 2, as
|
15 |
published by the Free Software Foundation.
|
16 |
|
17 |
This program is distributed in the hope that it will be useful,
|
18 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20 |
GNU General Public License for more details.
|
21 |
|
22 |
You should have received a copy of the GNU General Public License
|
23 |
along with this program; if not, write to the Free Software
|
24 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
25 |
|
26 |
*/
|
27 |
// Only create an instance of the plugin if it doesn't already exists in GLOBALS
|
28 |
if( ! array_key_exists( 'hello-reader', $GLOBALS ) ) { |
29 |
|
30 |
class Hello_Reader { |
31 |
|
32 |
function __construct() { |
33 |
|
34 |
} // end constructor |
35 |
|
36 |
} // end class |
37 |
|
38 |
// Store a reference to the plugin in GLOBALS so that our unit tests can access it
|
39 |
$GLOBALS['hello-reader'] = new Hello_Reader(); |
40 |
|
41 |
} // end if |
На этом этапе вы должны иметь возможность перейти к "Плагинам" на панели инструментов WordPress и увидеть запись "Hello Reader". Очевидно, что этот плагин еще ничего не делает - мы сосредоточимся на этом (а также на том, почему мы используем массив $GLOBALS
) в следующей статье.
Теперь, давайте настроим среду тестирования, чтобы мы могли писать наши тесты. Сначала нам нужно установить PHPUnit, а затем нам нужно будет установить WordPress Tests.
Примечание: следующий раздел потребует некоторой работы с терминалом и, вероятно, потребует, чтобы вы выполнили несколько команд для создания символических ссылок. Я пытался сделать это как можно упрощенней, но каждая операционная система и конфигурация будут разными. Пожалуйста, будьте внимательны,и я предлагаю поделиться своими инструкциями для ваших операционных систем в комментариях.
Установка PHPUnit
PHPUnit - это пакет фреймворков для юнит-тестов, специально для PHP. Тесты WordPress и среда, которую мы будем использовать для написания наших тестов WordPress, зависят от этого. К сожалению установки варьируются в зависимости от вашей платформы. В настоящее время я использую Mac OS X Lion с MAMP Pro и PHP 5.3.6. Если вы работаете на другой платформе, обязательно ознакомьтесь с документацией и/или не стесняйтесь делиться этим в комментариях.
Сначала откройте терминал и обновите pear (это средство, которое мы будем использовать для установки PHPUnit):
$ cd /Applications/MAMP/bin/php/php5.3.6/bin
$ sudo ./pear upgrade pear
Далее, проинструктируйте Pear использовать репозитории, которые мы укажем в терминале:
$ sudo /Applications/MAMP/bin/php/php5.3.6/bin/pear config-set auto_discover 1
После этого установите Pear, введя следующую команду:
$ sudo /Applications/MAMP/bin/php/php5.3.6/bin/pear install pear.phpunit.de/PHPUnit
Это установит PHPUnit в контексте вашей установки MAMP. Чтобы проверить это, выполните следующую команду в терминале сессии:
$ /Applications/MAMP/bin/php/php5.3.6/bin/phpunit --version
После чего должно появиться следующее сообщение:
PHPUnit 3.6.11 by Sebastian Bergmann.
Примечание: Если вы получили сообщение об ошибке терминала, в котором упоминается "unserialize ()", то существует несоответствие между конфигурацией pear и вашей версией pear. Чтобы устранить проблему, введите следующую команду (это просто переименовывает файл, если вы хотите восстановить его позже):
$ /Applications/MAMP/bin/php/php5.3.6/conf/pear.conf /Applications/MAMP/bin/php/php5.3.6/conf/pear.conf.old
Установка WordPress Tests
Теперь, когда у нас установлен и работает PHPUnit, пришло время настроить среду тестирования WordPress. Вы можете получить пакет из GitHub. Если вам удобно клонировать репозиторий, не стесняйтесь делать это; в противном случае просто скачайте архив проекта и распакуйте его в тестовый каталог, который мы создали ранее в этой статье.
Перед тем, как запускать тесты, нам нужно создать файл конфигурации для запуска WordPress tests. Это похоже на редактирование файла wp-config.php с помощью новой установки WordPress, но вместо этого мы делаем это для тестовой базы данных. Ниже я вставил свой файл конфигурации и добавил комментарии. Я обязательно добавлю это в репозиторий GitHub этой статьи.
1 |
/* Path to the WordPress codebase in relation to the location of these tests. Since they are included with our plugin, we refer to a few directories above. */
|
2 |
define( 'ABSPATH', '../../../../../' ); |
3 |
|
4 |
/* The name of the database for running the tests. Make sure this is a database just for testing as it's created and trashed during tests. */
|
5 |
define( 'DB_NAME', 'throwaway' ); |
6 |
|
7 |
/* The usual credentials for a local database. */
|
8 |
define( 'DB_USER', 'root' ); |
9 |
define( 'DB_PASSWORD', '' ); |
10 |
define( 'DB_HOST', 'localhost' ); |
11 |
define( 'DB_CHARSET', 'utf8' ); |
12 |
define( 'DB_COLLATE', '' ); |
13 |
|
14 |
define( 'WPLANG', '' ); |
15 |
define( 'WP_DEBUG', true ); |
16 |
define( 'WP_DEBUG_DISPLAY', true ); |
17 |
|
18 |
define( 'WP_TESTS_DOMAIN', 'localhost' ); |
19 |
define( 'WP_TESTS_EMAIL', 'tom@tommcfarlin.com' ); |
20 |
define( 'WP_TESTS_TITLE', 'Test Blog' ); |
21 |
|
22 |
/* Not worried about testing networks or subdomains, so setting to false. */
|
23 |
define( 'WP_TESTS_NETWORK_TITLE', 'Test Network' ); |
24 |
define( 'WP_TESTS_SUBDOMAIN_INSTALL', false ); |
25 |
$base = '/'; |
26 |
|
27 |
/* Cron tries to make an HTTP request to the blog, which always fails, because tests are run in CLI mode only */
|
28 |
define( 'DISABLE_WP_CRON', true ); |
29 |
|
30 |
/* Also not interested in testing multisite for this project, so setting to false. */
|
31 |
define( 'WP_ALLOW_MULTISITE', false ); |
32 |
if ( WP_ALLOW_MULTISITE ) { |
33 |
define( 'WP_TESTS_BLOGS', 'first,second,third,fourth' ); |
34 |
}
|
35 |
if ( WP_ALLOW_MULTISITE && !defined('WP_INSTALLING') ) { |
36 |
define( 'SUBDOMAIN_INSTALL', WP_TESTS_SUBDOMAIN_INSTALL ); |
37 |
define( 'MULTISITE', true ); |
38 |
define( 'DOMAIN_CURRENT_SITE', WP_TESTS_DOMAIN ); |
39 |
define( 'PATH_CURRENT_SITE', '/' ); |
40 |
define( 'SITE_ID_CURRENT_SITE', 1); |
41 |
define( 'BLOG_ID_CURRENT_SITE', 1); |
42 |
}
|
43 |
|
44 |
$table_prefix = 'wp_'; |
Чтобы убедиться, что вы правильно установили тесты, вы можете запустить в терминале следующую команду:
$ /Applications/MAMP/bin/php/php5.3.6/bin/phpunit all
Если вы получили ошибку, то это потому, что WordPress tests пытается использовать сокет для базы данных MySQL, а не тот, который используется MAMP. Чтобы это исправить, нам нужно создать символическую ссылку из гнезда MAMP на место на диске, которое используют модульные тесты. Введите следующие команды в терминале сессии:
1 |
$ sudo mkdir /var/mysql |
2 |
$ sudo ln -s /Applications/MAMP/tmp/mysql/mysql.sock /var/mysql/mysql.sock |
3 |
$ sudo ln -s /Applications/MAMP/tmp/mysql/mysql.sock /var/mysql/mysql.sock |
Теперь попробуйте снова запустить тесты, и вы должны увидеть что-то вроде следующего скриншота.



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