Модульное тестирование WordPress с помощью Brain Monkey

Модульное тестирование WordPress с помощью Brain Monkey

Кто ещё не знаком с тестированием и модульным тестированием можете ознакомится: Автоматизация тестирования, Модульное тестирование при помощи PHPUnit.

Тестирование тем и плагинов под WordPress имеет в себя одну большую проблему — взаимодействие с ядром. Решить ее можно при помощи библиотек Brain-WP/BrainMonkey или 10up/WP_Mock .

Как писать тесты при помощи 10up/WP_Mock вы можете без проблем прочитать в статье: Модульное тестирование WordPress(PHPUnit, WP_Mock), но а теперь разберемся с Brain Monkey.

Библиотека Brain Monkey помогает делать заглушки для возможностей и классов из ядра WordPress.

Установка библиотеки Brain-WP/BrainMonkey для тестирования WordPress

Устанавливаем библиотеку через composer:

composer require --dev brain/monkey

Для работы библиотеки необходимо использовать фикстуры setUp и tearDown:

use Brain\Monkey;use PHPUnit\Framework\TestCase;class Test_Main extends TestCase { public function setUp(): void {parent::setUp();Monkey\setUp();} public function tearDown(): void {Monkey\tearDown();parent::tearDown();} }

Сейчас мы можем делать заглушки абсолютно для любых возможностей и классов WordPress.

Функции библиотеки

Brain\Monkey\Functions\when;

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

justReturn

use function Brain\Monkey\Functions\when;when( 'function_name')->justReturn( 'krya');$this->assertSame( 'krya', function_name());

С помощью when мы делаем мок для возможности function_name и при ее вызове будет возвращен результат из способа justReturn.

returnArg

when( 'func1')->returnArg();when( 'func2')->returnArg( 2);when( 'func3')->returnArg( 3);$this->assertSame( 'krya', func1( 'krya', 2, 3));$this->assertSame( 'krya', func2( 1, 'krya', 3));$this->assertSame( 'krya', funct3( 1, 2, 'krya'));

С помощью when мы делаем мок для возможности function_name и при ее вызове будет возвращен аргумент возможности под номером из способа returnArg.

Это удобно, когда нам необходимо использовать возможности для очистки переменных или очистки данных перед выводом( sanitize_*, esc_*).

justEcho

when( 'function_name')->justEcho( 'krya');ob_start();function_name();$this->assertSame( 'krya', ob_get_clean());

При вызове возможности function_name выводим на экран текст из способа justEcho.

alias

when( 'duplicate')->alias( function( $value) {return "Was ". $value. ", now is ". ( $value * 2 );} );$this->assertSame( 'Was 1, now is 2', duplicate( 1 ) );

Вызов возможности duplicate мы заменяем на нашу возможность.

when( 'bigger' )->alias( 'strtoupper' );$this->assertSame( 'WAS LOWER', bigger( 'was lower' ) );

При вызове возможности bigger будет вызвана функцию strtoupper .

Brain\Monkey\Functions\stubs;

Функцию для массовой замены возможностей:

stubs(['esc_attr','esc_html','esc_textarea','__','_x','esc_html__','esc_html_x','esc_attr_x',]);$this->assertSame( 'krya', esc_attr( 'krya' ) );$this->assertSame( 'krya', esc_html( 'krya' ) );

При вызове каждой из возможностей будет возвращаться первый аргумент, который был в нее передан. Тоже самое что и when( 'func1' )->returnArg() , но массово.

Так же можно легко вторым настройкою указать результат возможностей:

stubs( [ 'is_user_logged_in', 'current_user_can', ], true);

Или ещё круче, передав массив ключ-значени, в котором ключ — название возможности , а значении примитив или callback .

stubs(['is_user_logged_in' => true,'current_user_can' => false,'bigger'        => 'strtoupper',]);$this->assertTrue( is_user_logged_in() );$this->assertFalse( current_user_can() );$this->assertSame( 'WAS LOWER', bigger( 'was lower' ) );

Подводные камни

null нельзя передать, как результат возможности, так что используйте __return_null для этого:

stubs(['return_null_function' => '__return_null',]);$this->assertNull( return_null_function() );

Если вам необходимо замокать возможность, которая возвращает callback . Так что необходимо указать callback , который возвращает callback .

Модульное тестирование WordPress при помощи Brain Monkey
stubs(['return_callback' => function () {return [ 'Callback_Class', 'callback_method' ];},]);$this->assertSame([ 'Callback_Class', 'callback_method' ],return_callback());

Brain\Monkey\Functions\expect

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

Функцию была вызвана n-раз

expect( 'once' )->once(); // 1expect( 'twice' )->twice(); // 2expect( 'i_dont_know' )->zeroOrMoreTimes();expect( 'no_more_than_one' )->atLeast()->once(); // <=1expect( 'more_than_one' )->atMost()->once(); // >= 1expect( 'never' )->never(); // 0expect( 'three_times' )->times( 3 ); // 3expect( 'from_2_to_4_times' )->between( 2, 4 ); // 2-4

Функцию была вызвана с такими настройками:

expect( 'function_name' )->once()->withAnyArgs();function_name( 1, 2, 3 );expect( 'function_name' )->once()->withNoArgs();function_name();expect( 'function_name' )->once()->with( 'arg1', 'arg2' );function_name( 'arg1', 'arg2' );expect( 'function_name' )->once()->with( Mockery::type( 'int' ), Mockery::type( 'string' ) );function_name( 10, 'string' );expect( 'function_name' )->once()->with( Mockery::any() );function_name( new stdClass() );expect( 'function_name' )->once()->with( Mockery::anyOf( 'a', 2, true ) );function_name( 'a' );expect( 'function_name' )->once()->with( Mockery::not( 'a', 2, true ) );function_name( 1 );
  • withAnyArgs() — с любыми аргументами, с любым их числом или вовсе без них;
  • withNoArgs() — без аргументов;
  • with( ... ) — указываем точные аргументы.
  • with( Mockery::type( 'int' ), Mockery::type( 'string' ) ) — первый аргумент любое число, а второй — любая строка;
  • with( Mockery::any() ) — первый аргумент может быть абсолютно любого типа;
  • with( Mockery::anyOf( 'a', 2, true ) ) — первый аргумент любой из списка;
  • with( Mockery::not( 'a', 2, true ) ) — любой, кроме тех, что в списке.

Функцию возвращает

expect( 'function_name' )->once()->andReturn( 'Baz!' );$this->assertSame( 'Baz!', function_name() );expect( 'function_name' )->twice()->andReturn( 'First time I run', 'Second time I run' );$this->assertSame( 'First time I run', function_name( 'First time I run' ) );$this->assertSame( 'Second time I run', function_name( 'Second time I run' ) );expect( 'function_name' )->twice()->andReturnValues( [ 'First time I run', 'Second time I run' ] );$this->assertSame( 'First time I run', function_name( 'First time I run' ) );$this->assertSame( 'Second time I run', function_name( 'Second time I run' ) );expect( 'function_name' )->once()->andReturnNull();$this->assertNull( function_name() );expect( 'function_name' )->once()->andReturnUsing( function () {return 'I am an alias!';} );$this->assertSame( 'I am an alias!', function_name() );expect( 'function_name' )->once()->andThrow( 'RuntimeException' );$this->expectException( 'RuntimeException' );function_name();
  • andReturn( 'Baz!' ) — функцию вернет Baz! ;
  • andReturn( 'One', 'Two' ) — функцию вернет One в первый раз и Two во второй;
  • andReturnValues( 'One', 'Two' ) — функцию вернет One в первый раз и Two во второй;
  • andReturnNull() — функцию вернет null ;
  • andReturnUsing( callback ) — функцию вернет callback ;
  • andThrow( 'RuntimeException' ) — функцию выбросит исключение RuntimeException .

Тестирование хуков

Тестирование подключений хуков

Тестируемый класс:

class Metabox {public function hooks() {add_action( 'init', [ $this, 'init' ], 20, 4 );add_filter( 'the_title', [ $this, 'the_title' ], 20, 2 );}public function init() {}public function the_title() {}}

Проверить подключение хуков можно при помощи возможностей has_action и has_filter :

public function test_hooks() {$metabox = new Metabox();$metabox->hooks();$this->assertTrue( has_action( 'init', [ $metabox, 'init' ] ) );$this->assertTrue( has_filter( 'the_title', [ $metabox, 'the_title' ] ) );}

Тестирование наличия хуков

Пример класса:

class Metabox {public function awesome_method() {do_action( 'my_action', $this );return apply_filters( 'my_filter', 'Filter applied', $this );}}

Проверяем при помощи did_action и applied , которые возвращают кол-во вызовов данных хуков:

public function test_awesome_method() {$metabox = new Metabox();$this->assertNull( $metabox->awesome_method() );$this->assertSame( 1, did_action( 'my_action' ) );$this->assertSame( 1, applied( 'my_filter' ) );}

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

Так что тестировать лучше и более качественее при помощи Brain\Monkey\Actions\expectDone и Brain\Monkey\Filters\expectApplied :

public function test_awesome_method() {$metabox = new Metabox();expectDone( 'my_action' )->once()->with( $metabox );expectApplied( 'my_filter' )->once()->with( 'Filter applied', $metabox )->andReturn( 'Brain Monkey rocks!' );$metabox->awesome_method();}

Отображение

При помощи Brain Monkey мы можем тестировать большую часть функциональности WordPress. А как вы считаете что лучше WP_Mock или Brain Monkey ?

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

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