воскресенье, 30 апреля 2017 г.

Использование символьных ссылок

При разработке плагина для WordPress удобно иметь одну директорию с плагином. Файлы, находящиеся в ней редактируются в текстовом редакторе, а сама директория является Git репозиторием. Однако, иногда нужно протестировать, как плагин работает с различными версиями WordPress, в режиме мультисайт и т.д. В этом случае у нас может быть установлено несколько версий WordPress. Без символьных ссылок, нам пришлось бы копировать директорию с плагином каждый раз, после внесения изменений в файлы плагина.

Символьные ссылки

Символьная ссылка - это специальный файл в файловой системе, который ссылается на другой файл или директорию. Символьные ссылки можно создавать как в Windows, так и в OSX и Linux. Однако, синтаксис команд для Windows и OSX/Linux различен.

OSX и Linux

// Если плагин находится в директории ~/plugin_name // Перейти в директорию с WordPress плагинами той установки WordPress, где нам нужно добавить плагин plugin_name. cd public_html/wp-content/plugins // Создать символьную ссылку ln -s ~/plugin_name plugin_name

Windows

// Если плагин находится в директории C:\plugin_name // Перейти в директорию с WordPress плагинами той установки WordPress, где нам нужно добавить плагин plugin_name. cd public_html/wp-content/plugins // Создать символьную ссылку mklink /j plugin_name C:\plugin_name

пятница, 31 марта 2017 г.

Как устроено модульное (Unit) тестирование кода в WordPress

Исходный код WordPress покрыт тестами. Для тестирования PHP кода используется PHPUnit, а для тестирования JavaScript — QUnit. В данной статье рассмотрим тестирование PHP кода.

Установка тестов

  1. Установите PHPUnit. Инструкция по установке доступна на сайте этого фреймворка.
  2. Выполните команды в консоли чтобы загрузить версию WordPress для разработчиков, включающую тесты: svn co https://develop.svn.wordpress.org/trunk/ wordpress-develop cd wordpress-develop
    Если у вас не установлена система управления версиями Subversion, вы можете скачать архив содержащий WordPress с тестами на этой странице. Это не удобно, т.к. нужно каждый раз скачивать архив чтобы иметь последнюю версию.
  3. Создайте пустую базу данных MySQL, которая будет использоваться для тестирования. Все данные будут удалены из всех таблиц во время исполнения тестов, поэтому нельзя использовать существующую базу данных.
  4. Скопируйте данные из файла wp-tests-config-sample.php в новый файл wp-tests-config.php и добавьте в него данные для доступа к базе данных, созданной на предыдущем шаге.
  5. В корневой директории, где расположены файлы wp-tests-config.php, phpunit.xml.dist, и папка tests/, выполните команду: phpunit
    или, добавьте путь к файлу, чтобы выполнить тесты находящиеся в нем, например: phpunit tests/phpunit/tests/dependencies/styles.php

О запуске различных групп тестов можно почитать в документации.

Для каждого выполненного теста в консоли отображается один из следующих символов:

  • . — тест успешно выполнен
  • F — тест не выполнен успешно. Какое либо утверждение, например assertEquals ложно.
  • E — тест не выполнен успешно из за ошибки в PHP коде: E_ERROR, E_WARNING, E_NOTICE
  • S — тест пропущен, например, с помощью метода markTestSkipped(). Обычно это означает что тест нужен только при определенных обстоятельствах, например, когда включен режим Мультисайт. Если он выключен — тест пропускается.
  • I — незаконченный тест. В нем присутствует метод markTestIncomplete() или это пустой тест без утверждений (asserts).

Устройство тестов

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

  • setUp — выполняется перед каждым методом в тестовом классе
  • tearDown — выполняется после каждого метода в тестовом классе
  • setUpBeforeClass — выполняется перед первым методом в тестовом классе
  • tearDownAfterClass после последнего метода в тестовом классе
  • assertPostConditions — выполняется перед окончанием теста, перед tearDown

Фабрики

Фабрики позволяют создавать посты, комментарии, таксономии, пользователей и т.д.

// создать пользователя с ролью 'editor', вернуть идентификатор $user_id = self::factory()->user->create( array( 'role' => 'editor' ) // создать пользователя с ролью 'editor', вернуть объект класса WP_User $user = self::factory()->user->create_and_get( array( 'role' => 'editor' ) // создать 5 страниц, вернуть массив идентификаторов $post_ids = self::factory()->post->create_many( 5, array( 'post_type' => 'page' ) );

суббота, 25 марта 2017 г.

Приемы работы в Vim

Файловый менеджер Netrw

vim -c Ex /tmp — обзор директории /tmp (запуск из консоли)

Сессии

:mksession ~/mysession.vim — сохранение
:source ~/mysession.vim, или vim -S ~/mysession.vim (запуск из консоли) — загрузка сохраненной сессии

Перемещение окон

<ctrl+w> j, <ctrl+w> k, <ctrl+w> h, <ctrl+w> l — переместить курсор в окно ниже, выше, левее и правее соответственно
<ctrl+w> J, <ctrl+w> K, <ctrl+w> H, <ctrl+w> L — переместить окно в окно ниже других, выше других, левее и правее других соответственно

Закрытие окна

ZZ, или :x – сохранить файл (если был изменен) и закрыть окно
ZQ, или :q! – закрыть окно без сохранения

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

z. — по центру
zt — вверху
zb — внизу

Увеличение окна, когда открыто несколько окон (split)

<ctrl+w> _, или <ctrl+w> T чтобы переместить окно в новый таб

Перенос длинных строк на следующие строки

:set wrap — включен
:set nowrap — выключен

При выключенном переносе:
zl — прокрутка вправо
zh — прокрутка влево

Возврат к месту редактирования

g; — вперед
g, — назад
Например, во время редактирования строки нужно вставить слово из другой части файла. После нахождения и копирования слова, нажимаем g;

Создание отступов (== и = )

== — отступ для текущей строки
= — отступ для выделения (Shift+v)
gg=G — отступ для всего файла

Редактирование в режиме Normal

После выдеения 3 строк с помощью <shift+v> $one = 1 $two = 2 $three = 3

:'<,'>normal A; — добавить ";", результат: $one = 1; $two = 2; $three = 3;

:'<,'>normal Ipublic <ctrl+q> <ctrl+[> A; — добавить "public" и ";", результат: public $one = 1; public $two = 2; public $three = 3;

Выполнение команды в консоли

:!ls — список файлов :!php % — выполнить редактируемый php файл

Команды в режиме редактирования (insert)

<ctrl+w> — удалить предыдущее слово
<ctrl+r>0 — вставить текст

Отличия trigger() и triggerHandler() в jQuery

Эти методы позволяют запускать обработчики определенных событий, привязанных к соответствующим элементам. Рассмотрим, чем они отличаются.

.triggerHandler( 'event' ) не вызывает .event() на элементе, .trigger( 'event' ) — вызывает

<input type="text"> <script> $(function() { $( "input" ).focus(function() { console.log('focus'); }); $( "input" ).trigger( "focus" ); // "focus" в консоли, текстовое поле получит фокус $( "input" ).triggerHandler( "focus" ); // "focus" в консоли, но текстовое поле не получит фокус }) </script>

.triggerHandler() обрабатывает только первый соответствующий элемент, trigger() — все элементы

<button id="button1">button1</button> <button id="button2">button2</button> <script> $("#button1").click(function(){ console.log('button 1'); }); $("#button2").click(function(){ console.log('button 2'); }); $("#button1, #button2").triggerHandler("click"); // "button 1" в консоли $("#button1, #button2").trigger("click"); // "button 1", "button 2" в консоли </script>

События, генерируемые .triggerHandler() не всплывают выше по иерархии DOM, генерируемые .trigger() — всплывают

<div id="outer"> <div id="inner"></div> </div> <script> $(function() { $("#outer").click(function(){ console.log('outer click'); }); $("#inner").click(function(){ console.log('inner click'); }); $("#inner").trigger('click'); // "inner click", "outer click" в консоли $("#inner").triggerHandler('click'); // "inner click" в консоли }); </script>

.triggerHandler() возвращает значение из последнего обработчика, или undefined, .trigger() возвращает jQuery объект

<button id="button">Button</button> <script> $(function() { $("#button").click(function(){ return 5; }); var result = $("#button").trigger('click'); result.css('color', 'green'); // изменить цвет кнопки var result = $("#button").triggerHandler('click'); console.log(result); // 5 }); </script>

суббота, 18 февраля 2017 г.

Использование PHP CodeSniffer при разработке для WordPress

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

PHP CodeSniffer состоит из двух скриптов:

  • phpcs — сканирует исходный код
  • phpcbf — исправляет ошибки, если это возможно

Установка

PHP CodeSniffer можно установить различными способами. Для установки через Composer выполните команду

composer create-project wp-coding-standards/wpcs --no-dev

Для запуска:
./wpcs/vendor/bin/phpcs ./wpcs/vendor/bin/phpcbf

Для удобства можно добавить wpcs/vendor/bin в переменную окружения PATH, и установить набор правил WordPress по умолчанию, чтобы не указывать его каждый раз при запуске
phpcs --config-set default_standard WordPress

Наборы правил

  • WordPress — все правила WordPress
  • WordPress-Core — правила для ядра WordPress
  • WordPress-Docs — правила документирования
  • WordPress-Extra — дополнительные правила, дополняющие правила WordPress-Core.
    Включают в себя WordPress-Core
  • WordPress-VIP — правила WordPress VIP.
    Включают в себя WordPress-Core

Пример

phpcs --standard=WordPress wp-load.php // найдено 13 ошибок, 4 предупреждения

phpcbf --standard=WordPress wp-load.php // исправление ошибок phpcs --standard=WordPress wp-load.php // найдено 9 ошибок, 4 предупреждения

воскресенье, 29 января 2017 г.

WP CLI — незаменимый инструмент для WordPress разработчика

WP CLI — это инструмент, который существенно увеличивает скорость и удобство разработки. Он представляет собой phar файл (исполняемый PHP архив), который запускается в командной строке и предоставляет множество команд для работы с WordPress. Хотя на сайте доступна подробная документация с примерами, я все же приведу несколько примеров использования команд, входящих в его состав.

wp search-replace — поиск и замена
wp search-replace 'existing_domain.com' 'new_domain.com' --skip-columns=guid // изменение URL блога во всех таблицах базы данных, пропуская столбец guid

wp eval — исполнение PHP кода
wp eval 'echo WP_CONTENT_DIR;' // просмотр значения константы WP_CONTENT_DIR

wp shell — интерактивная консоль в пределах среды WordPress. Здесь есть доступ к функциям, классам и глобальным переменным, которые, например, вы можете использовать при разработке плагина.
wp shell >>> get_current_blog_id() => 1 >>>

Для работы с wp shell в Windows, скачайте psysh (интерактивная PHP консоль) и подключайте его:
wp --require=psysh shell

wp plugin activate — активация плагина
wp --url=http://localhost/multisite/two plugin activate wp-amp // активация плагина wp-amp на втором сайте при использовании multisite

wp plugin toggle — переключение плагина (если плагин активен, деактивирует его, если не активен, активирует)
wp plugin toggle wp-amp amp-wp // переключение двух плагинов

wp plugin uninstall — удаление плагина
wp plugin uninstall advanced-ads-pro --skip-delete // запуск процедуры удаления плагина, при этом не удаляя файлы

wp scaffold — кодогенерация (позволяет сгенерировать плагин, тему на основе _s , создать дочернюю тему, шаблон для написания тестов к теме или плагину, custom post type или таксономию)
/* генерация нового плагина, включая: - конфигурационный файл PHPUnit - .travis.yml (конфигурационный файл Travis CI) - bin/install-wp-tests.sh ( создание конфигурации для тестирования, включая БД) - tests/test-sample.php (шаблон теста) - phpcs.ruleset.xml (правила PHP_CodeSniffer) */ wp scaffold plugin sample-plugin

wp db — операции с БД
wp db cli // интерактивная консоль MySQL

wp media regenerate — управление вложениями
wp media regenerate --yes // регенерация миниатюр

wp cache — управление кэшем (добавление, удаление, изменение и т.д.)
wp cache add test_key test_data test_group // добавление в кэш

воскресенье, 20 ноября 2016 г.

Acceptance Тестирование WordPress сайта с помощью Codeception

Codeception — это фреймворк для тестирования веб-приложений. Тесты, написанные с использованием этого фреймворка легко писать, модифицировать и исполнять. Используя набор готовых модулей, вы можете сконцентрироваться на написании самих тестов, вместо того, чтобы изобретать тестовый фреймворк.

Codeception позволяет писать 3 вида тестов.

Приемочные (Acceptance) тесты позволяют тестировать веб-сайт с точки зрения пользователя — переходить по страницам, кликать по ссылкам, заполнять формы и т.д. Не имеет значение, какой фреймворк, база данных, язык программирования или веб-сервер используются чтобы отобразить веб-страницу. Любая веб-страница, которую вы можете посетить с помощью веб-браузера может быть покрыта такими тестами.

Функциональные (Functional) тесты позволяют тестировать веб-приложение без запуска веб-сервера. Мы можем, например, эмулировать запрос к веб-серверу, передавая $_GET  и $_POST переменные, проверяя, что мы получаем правильный ответ при данном запросе и что отправленные данные корректно сохраняются в базе данных.

Модульные (Unit) тесты позволяют изолированно тестировать отдельные функции и классы.


WordPress и Codeception


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

WP-Browser  — набор модулей для Codeception облегчающий тестирование тем и плагинов для WordPress. Мы будем использовать только модуль WPBootstrapper позволяющий вызывать функции WordPress прямо в тестах.
  1. Создайте директорию и файл composer.json
    mkdir codeception_tests && cd codeception_tests touch composer.json
  2. Измените содержимое файла composer.json на:
    { "require": { "codeception/codeception": "^2.2", "lucatume/wp-browser": "~1.11" } }
  3. Выполните команду composer install
  4. Создайте псевдоним
    alias codecept='./vendor/bin/codecept'
  5. Подготовьте тестовую директорию и конфигурационные файлы
    codecept bootstrap
  6. Сгенерируйте тест
    codecept generate:cept acceptance Welcome
  7. Откройте созданный файл теста tests/acceptance/WelcomeCept.php и измените его на:
    // загрузка WordPress bootstrapWp(); // обновление описания блога update_option( 'blogdescription', 'Welcome to my blog' ); // Загрузка главной страницы $I->amOnPage('/'); // Проверка, что описание блога присутствует на странице $I->see('Welcome to my blog'); // Обновление описания блога update_option( 'blogdescription', 'Welcome again' ); // Обновление страницы $I->amOnPage('/'); // Проверка, что новое описание блога присутствует на странице $I->see('Welcome again');
  8. Добавьте следующий код в файл tests/acceptance.suite.yml
    class_name: AcceptanceTester modules: enabled: - PhpBrowser: url: http://localhost/blog // url блога - \Helper\Acceptance - WPBootstrapper: wpRootFolder: '..' // путь к директории с WordPress
  9. Запустите тест
    codecept run acceptance
  10. Тест выполнился успешно. Результат:
    Codeception PHP Testing Framework v2.2.6 Powered by PHPUnit 5.6.4 by Sebastian Bergmann and contributors. Acceptance Tests (1) ------------------------------------------------ + WelcomeCept: (14.78s) --------------------------------------------------------------------- Time: 20.15 seconds, Memory: 20.00MB OK (1 test, 2 assertions)