ݺߣ

ݺߣShare a Scribd company logo
Тестування з допомогою PHPUnit

       Андрій Насінник




           Тернопіль
         Березень 2013
- Трохи історії
- Інсталяція PHPUnit
- Структура тесту
- Asserts
- Написання Тестів
- Data Providers
- Mock Objects
- Трохи про TDD
- Два слова про BDD
Трохи історії

SUnit - xUnit framework на Smalltalk (Kent Beck)

JUnit - порт xUnit на Java (Kent Beck & Erich Gamma)

PHPUnit - порт xUnit на PHP (Sebastian Bergmann)

SimpleTest - конкурет PHPUnit
Інсталяція PHPUnit

- Pear

pear config-set auto_discover 1
pear install pear.phpunit.de/PHPUnit


- Phar

wget http://pear.phpunit.de/get/phpunit.phar
chmod +x phpunit.phar
Інсталяція PHPUnit

- Composer (composer.json)

{
    "name": "phpunit",
    "description": "PHPUnit",
    "require": {
        "phpunit/phpunit": "3.8.*"
    },
    "config": {
        "bin-dir": "/usr/local/bin/"
    }
}



curl -s https://getcomposer.org/installer | php
./composer.phar install
Структура тесту

- Базовий інтерфейс

TestCase/TestSuite implements PHPUnit_Framework_Test
public function run(PHPUnit_Framework_TestResult $result);


- Запуск

$test->run($result):
    $result->run($test):
        $test->setUpBeforeClass() //once per class
        $test->setUp()
        $test->runTest()
        $test->tearDown()
        $test->tearDownAfterClass() //once per class
Структура тесту

- Інтерфейс suite`a

PHPUnit_Framework_TestSuite implements IteratorAggregate


- Запуск тестів з suite’а

foreach ($suite as $test) {
    $test->run();
}
Asserts

- TestCase містить 90 методів assert

$this->assertEquals('expected', 'actual', 'custom message');
$this->assertThat('expected',
    PHPUnit_Framework_Constraint $constraint, 'custom
message');


- 3 "marked" function

markTestIncomplete();
markTestSkipped();
fail();
Asserts

- 6 "constraint" методів

equalTo(); isNull(); isTrue(); isType(); isEmpty();


- 4 "logic" методи

logicalOr(); logicalXor(); logicalAnd(); logicalNot();


$constraint = $this->logicalAnd(
    $this->isType('string'),
    $this->equalTo('test')
);
$this->assertThat($value, $constraint, $message);
Написання Тестів

class FirstTest extends PHPUnit_Framework_TestCase
{
    public function testFirst()
    {
         $this->assertTrue(true);
    }
}

class FirstTest extends PHPUnit_Framework_TestCase
{
    /**
      * @test
      */
    public function first()
    {
         $this->assertTrue(true);
    }
}
Data Providers

public function firstDataProvider()
{
    return array(
        'empty' => array(''),
        'incorrect' => array('@#^&!^#*!#')
    );
}


/**
  * @test
  * @dataProvider firstDataProvider
  */
public function first($data)
{
     $this->assertFalse($object->validate($data));
}
Mock Objects

Мокаєм обєкт:
/** @return PHPUnit_Framework_MockObject_MockObject */
public function getMock($objectName, $methods, $parameters,
$mockName, $callConstructor, $callClone, $callAutoload,
$cloneArguments)


Invocation Matcher:

$mock->expects($this->any());


Matcher Types:

any(), never(), once(), atLeastOnce(),
exactly(count), at(index)
Mock Objects

Перевірка параметрів:

$mock->expects($this->any())
    ->method('test')
    ->with($arg1, $arg2);//аргумент   - constraint, по дефолту equalTo



Емуляція результату:

$mock->expects($this->any())
    ->method('test')
    ->will(
        $this->returnValue($data)
    );//PHPUnit_Framework_MockObject_Stub
Mock Objects

Формування Stubs:

$ths->returnValue($data);
$ths->returnValueMap(
    array(
        array('p1', 'p2', 'r'),
        array('p2', null, 'r2'),//з дефолтними параметрами
    )
);
$ths->returnCallback(function ($data) {
    return explode('/', $data)
});
$ths->returnSelf();//return theme self
$ths->returnArgument(argIndex);
Mock Objects

Приклад тесту з використанням мокінгу:

public function testMocking()
{
    $mock = $this->getMock('DbAdapterPdoMysql', array
('fetchRow'));
    $mock->expects($this->exactly(2))
            ->method('fetchRow')
            ->with($this->logicalOr('Query', 'Query2'))
            ->will(
                $this->returnValue(
                    array('min' => 1, 'max' => 300)
                )
            );

    $object = new Enterprise_Index_Model_ICCP_Refresh($mock);
    $object->rebuildIndex();
}
Трохи про TDD
Трохи про TDD

Простий приклад TDD

Спершу тест:

class EmailTest extends PHPUnit_Framework_TestCase
{
    public function testGetDomainFromEmail()
    {
        $e = new Email();
        $this->assertEquals(
            'example.com',
            $e->getDomainFromEmail('test@examlple.com')
        );
    }
}


Запускаєм тест. Результат Error.
Трохи про TDD

Найпростішим способом заставляєм працювати тест.
Підміняєм реалізацію (Fake It).

class Email
{
    public function getDomainFromEmail($email)
    {
        return 'example.com';
    }
}


Зелена плоса. Тест спрацьовує.
Трохи про TDD

Рефакторимо. Видаляємо дублювання.

class Email
{
    public function getDomainFromEmail($email)
    {
        return explode('@', $email)[1];
    }
}


Зелена плоса. Тест проходить. Метод працює так як нам
потрібно.
Трохи про TDD

Ще один приклад

Спершу тест:

class EmailTest extends PHPUnit_Framework_TestCase
{
    public function testIsEmailValid()
    {
        $v = new Validator();
        $this->assertTrue(
           $v->isEmailValid('test@examlple.com')
        );
    }
}


Запускаєм тест. Результат Error.
Трохи про TDD

Найпростішим способом заставляєм працювати тест.

class Validator
{
    public function isEmailValid($email)
    {
        return true;
    }
}


Зелена плоса. Тест проходить.
Трохи про TDD

Добавимо більше тестових випадків (Triangulate).

public function isEmailValidDataProvider()
{
    return array(
        'correct' => array('test@example.com', true),
        'incorrect' => array('incorrect', false),
    );
}
public function testIsEmailValid($email, $expectedResult)
{
    //...
    $this->assertEquals($expectedResult, $v->isEmailValid
($email));
}
Запускаєм і на цей раз бачим Fail.
Далі пишемо правильну реалізацію.
Трохи про TDD

Якщо код зрозуміло пишіть зразу правильний тест.
(Oblivious Implementation).
Два слова про BDD

- Базується на TDD.
- Описує роботу Бізнесу та Девелоперів.
- Бізнес пише специфікації в вигляді тестів або
специфікації генеруються в тести.
- Девелопери пишуть код так щоб всі тести
спрацьовували.

Рішення для PHP:
Codeception
Behat
PHPUnit_Story
Матеріали

Книжки:

Kent Beck - XP. Test Driven Development
Martin Fowler - Refactoring: Improving the Design of Existing Code


Лінки:

http://www.phpunit.de/manual/3.8/en/index.html
http://behat.org/
http://codeception.com/
http://getcomposer.org/
http://en.wikipedia.org/wiki/Test-driven_development
http://en.wikipedia.org/wiki/Behavior-driven_development
Дякую за увагу!

Андрій Насінник

Копанія:
Magento

Email:
andriy.nas@gmail.com

https://github.com/Nas1k

Skype:
nas_ua
Ad

Recommended

Phpunit модульне тестування
Phpunit модульне тестування
Vladimir Maslechkin
Phpunit
Phpunit
Vladimir Maslechkin
tsql
tsql
eleksdev
SQL: Indexes, Select operator
SQL: Indexes, Select operator
eleksdev
Тестування при розробці програмного забезпечення. Unit Tests.
Тестування при розробці програмного забезпечення. Unit Tests.
Elantix
SQL Grouping, Joins
SQL Grouping, Joins
eleksdev
Ado.net module 2
Ado.net module 2
Andrii Hladkyi
Theme20_ajax
Theme20_ajax
Олег Вілігурський
передача параметрів в функції
передача параметрів в функції
Людмила Булыгина
Asynchronous programming in .NET (UA)
Asynchronous programming in .NET (UA)
Oleksandr Pavlyshak
Sql 04n edited
Sql 04n edited
eleksdev
Magento digitalstore theme
Magento digitalstore theme
NETBASE CMSMART
Blogging For Business
Blogging For Business
Odofin Caleb
Proyecto 10 poblado
Nancy Romo
Retro-compatibilidade em Android
Pedro Veloso
Jing Qiu's journal entry
Jing Qiu's journal entry
CCZ800524
#BMO15 | A scuola con i Maremmans | Nino Costa
#BMO15 | A scuola con i Maremmans | Nino Costa
Officina Turistica
Proyecto Yaku Manta Yachay
Red de Investigación Educativa - ieRed
Jefferson jara
Jefferson Jara
Principios e ferramentas
Principios e ferramentas
Luis Abreu
Музей освіти Меджибожа
Музей освіти Меджибожа
Олександр Дрижал
Acoso escolar baleares
IvanaGonzales
[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
Exoft LLC
природна і економна дорожня карта для переходу команди розробки на тест центр...
природна і економна дорожня карта для переходу команди розробки на тест центр...
Andrii Podanenko

More Related Content

What's hot (9)

SQL: Indexes, Select operator
SQL: Indexes, Select operator
eleksdev
Тестування при розробці програмного забезпечення. Unit Tests.
Тестування при розробці програмного забезпечення. Unit Tests.
Elantix
SQL Grouping, Joins
SQL Grouping, Joins
eleksdev
Ado.net module 2
Ado.net module 2
Andrii Hladkyi
Theme20_ajax
Theme20_ajax
Олег Вілігурський
передача параметрів в функції
передача параметрів в функції
Людмила Булыгина
Asynchronous programming in .NET (UA)
Asynchronous programming in .NET (UA)
Oleksandr Pavlyshak
Sql 04n edited
Sql 04n edited
eleksdev
SQL: Indexes, Select operator
SQL: Indexes, Select operator
eleksdev
Тестування при розробці програмного забезпечення. Unit Tests.
Тестування при розробці програмного забезпечення. Unit Tests.
Elantix
SQL Grouping, Joins
SQL Grouping, Joins
eleksdev

Viewers also liked (11)

Magento digitalstore theme
Magento digitalstore theme
NETBASE CMSMART
Blogging For Business
Blogging For Business
Odofin Caleb
Proyecto 10 poblado
Nancy Romo
Retro-compatibilidade em Android
Pedro Veloso
Jing Qiu's journal entry
Jing Qiu's journal entry
CCZ800524
#BMO15 | A scuola con i Maremmans | Nino Costa
#BMO15 | A scuola con i Maremmans | Nino Costa
Officina Turistica
Proyecto Yaku Manta Yachay
Red de Investigación Educativa - ieRed
Jefferson jara
Jefferson Jara
Principios e ferramentas
Principios e ferramentas
Luis Abreu
Музей освіти Меджибожа
Музей освіти Меджибожа
Олександр Дрижал
Acoso escolar baleares
IvanaGonzales
Proyecto 10 poblado
Nancy Romo
Retro-compatibilidade em Android
Pedro Veloso
Jing Qiu's journal entry
Jing Qiu's journal entry
CCZ800524
#BMO15 | A scuola con i Maremmans | Nino Costa
#BMO15 | A scuola con i Maremmans | Nino Costa
Officina Turistica
Proyecto Yaku Manta Yachay
Red de Investigación Educativa - ieRed
Jefferson jara
Jefferson Jara
Principios e ferramentas
Principios e ferramentas
Luis Abreu
Acoso escolar baleares
IvanaGonzales
Ad

Similar to Тестування з допомогою PHPUnit (16)

[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
Exoft LLC
природна і економна дорожня карта для переходу команди розробки на тест центр...
природна і економна дорожня карта для переходу команди розробки на тест центр...
Andrii Podanenko
Code driven testing (UA)
Code driven testing (UA)
Oleksandr Pavlyshak
CoreCamp "Automated testing basics for developers"
CoreCamp "Automated testing basics for developers"
Bohdan Pashkovskyi
Code driven testing -- oleksandr pavlyshak
Code driven testing -- oleksandr pavlyshak
Igor Bronovskyy
Як прокачати трьох студентів за п’ять тижнів
Як прокачати трьох студентів за п’ять тижнів
Stfalcon Meetups
Як прокачати трьох студентів за п’ять тижнів
Як прокачати трьох студентів за п’ять тижнів
Artem Henvald
Testing in Ruby
Testing in Ruby
Pivorak MeetUp
Php unit. Y. Muzychushun
Php unit. Y. Muzychushun
HRdepartment
Marafon_part1 (1).pptx
Marafon_part1 (1).pptx
ssuser75c4bb
"Unit testing in AngularJS" Виктор Зозуляк
"Unit testing in AngularJS" Виктор Зозуляк
Fwdays
МИХАЙЛО БОДНАРЧУК «Як перестати боятись та полюбити автотести на JavaScript» ...
МИХАЙЛО БОДНАРЧУК «Як перестати боятись та полюбити автотести на JavaScript» ...
QADay
ОЛЕКСАНДР ХОТЕМСЬКИЙ «Заготівля тестових даних для автоматичних тестів» QADay
ОЛЕКСАНДР ХОТЕМСЬКИЙ «Заготівля тестових даних для автоматичних тестів» QADay
QADay
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
QAFest
[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
[Knowledge Sharing] - Unit Testing by Pavlo Serdyuk (UKR)
Exoft LLC
природна і економна дорожня карта для переходу команди розробки на тест центр...
природна і економна дорожня карта для переходу команди розробки на тест центр...
Andrii Podanenko
CoreCamp "Automated testing basics for developers"
CoreCamp "Automated testing basics for developers"
Bohdan Pashkovskyi
Code driven testing -- oleksandr pavlyshak
Code driven testing -- oleksandr pavlyshak
Igor Bronovskyy
Як прокачати трьох студентів за п’ять тижнів
Як прокачати трьох студентів за п’ять тижнів
Stfalcon Meetups
Як прокачати трьох студентів за п’ять тижнів
Як прокачати трьох студентів за п’ять тижнів
Artem Henvald
Php unit. Y. Muzychushun
Php unit. Y. Muzychushun
HRdepartment
"Unit testing in AngularJS" Виктор Зозуляк
"Unit testing in AngularJS" Виктор Зозуляк
Fwdays
МИХАЙЛО БОДНАРЧУК «Як перестати боятись та полюбити автотести на JavaScript» ...
МИХАЙЛО БОДНАРЧУК «Як перестати боятись та полюбити автотести на JavaScript» ...
QADay
ОЛЕКСАНДР ХОТЕМСЬКИЙ «Заготівля тестових даних для автоматичних тестів» QADay
ОЛЕКСАНДР ХОТЕМСЬКИЙ «Заготівля тестових даних для автоматичних тестів» QADay
QADay
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
QAFest
Ad

Тестування з допомогою PHPUnit

  • 1. Тестування з допомогою PHPUnit Андрій Насінник Тернопіль Березень 2013
  • 2. - Трохи історії - Інсталяція PHPUnit - Структура тесту - Asserts - Написання Тестів - Data Providers - Mock Objects - Трохи про TDD - Два слова про BDD
  • 3. Трохи історії SUnit - xUnit framework на Smalltalk (Kent Beck) JUnit - порт xUnit на Java (Kent Beck & Erich Gamma) PHPUnit - порт xUnit на PHP (Sebastian Bergmann) SimpleTest - конкурет PHPUnit
  • 4. Інсталяція PHPUnit - Pear pear config-set auto_discover 1 pear install pear.phpunit.de/PHPUnit - Phar wget http://pear.phpunit.de/get/phpunit.phar chmod +x phpunit.phar
  • 5. Інсталяція PHPUnit - Composer (composer.json) { "name": "phpunit", "description": "PHPUnit", "require": { "phpunit/phpunit": "3.8.*" }, "config": { "bin-dir": "/usr/local/bin/" } } curl -s https://getcomposer.org/installer | php ./composer.phar install
  • 6. Структура тесту - Базовий інтерфейс TestCase/TestSuite implements PHPUnit_Framework_Test public function run(PHPUnit_Framework_TestResult $result); - Запуск $test->run($result): $result->run($test): $test->setUpBeforeClass() //once per class $test->setUp() $test->runTest() $test->tearDown() $test->tearDownAfterClass() //once per class
  • 7. Структура тесту - Інтерфейс suite`a PHPUnit_Framework_TestSuite implements IteratorAggregate - Запуск тестів з suite’а foreach ($suite as $test) { $test->run(); }
  • 8. Asserts - TestCase містить 90 методів assert $this->assertEquals('expected', 'actual', 'custom message'); $this->assertThat('expected', PHPUnit_Framework_Constraint $constraint, 'custom message'); - 3 "marked" function markTestIncomplete(); markTestSkipped(); fail();
  • 9. Asserts - 6 "constraint" методів equalTo(); isNull(); isTrue(); isType(); isEmpty(); - 4 "logic" методи logicalOr(); logicalXor(); logicalAnd(); logicalNot(); $constraint = $this->logicalAnd( $this->isType('string'), $this->equalTo('test') ); $this->assertThat($value, $constraint, $message);
  • 10. Написання Тестів class FirstTest extends PHPUnit_Framework_TestCase { public function testFirst() { $this->assertTrue(true); } } class FirstTest extends PHPUnit_Framework_TestCase { /** * @test */ public function first() { $this->assertTrue(true); } }
  • 11. Data Providers public function firstDataProvider() { return array( 'empty' => array(''), 'incorrect' => array('@#^&!^#*!#') ); } /** * @test * @dataProvider firstDataProvider */ public function first($data) { $this->assertFalse($object->validate($data)); }
  • 12. Mock Objects Мокаєм обєкт: /** @return PHPUnit_Framework_MockObject_MockObject */ public function getMock($objectName, $methods, $parameters, $mockName, $callConstructor, $callClone, $callAutoload, $cloneArguments) Invocation Matcher: $mock->expects($this->any()); Matcher Types: any(), never(), once(), atLeastOnce(), exactly(count), at(index)
  • 13. Mock Objects Перевірка параметрів: $mock->expects($this->any()) ->method('test') ->with($arg1, $arg2);//аргумент - constraint, по дефолту equalTo Емуляція результату: $mock->expects($this->any()) ->method('test') ->will( $this->returnValue($data) );//PHPUnit_Framework_MockObject_Stub
  • 14. Mock Objects Формування Stubs: $ths->returnValue($data); $ths->returnValueMap( array( array('p1', 'p2', 'r'), array('p2', null, 'r2'),//з дефолтними параметрами ) ); $ths->returnCallback(function ($data) { return explode('/', $data) }); $ths->returnSelf();//return theme self $ths->returnArgument(argIndex);
  • 15. Mock Objects Приклад тесту з використанням мокінгу: public function testMocking() { $mock = $this->getMock('DbAdapterPdoMysql', array ('fetchRow')); $mock->expects($this->exactly(2)) ->method('fetchRow') ->with($this->logicalOr('Query', 'Query2')) ->will( $this->returnValue( array('min' => 1, 'max' => 300) ) ); $object = new Enterprise_Index_Model_ICCP_Refresh($mock); $object->rebuildIndex(); }
  • 17. Трохи про TDD Простий приклад TDD Спершу тест: class EmailTest extends PHPUnit_Framework_TestCase { public function testGetDomainFromEmail() { $e = new Email(); $this->assertEquals( 'example.com', $e->getDomainFromEmail('test@examlple.com') ); } } Запускаєм тест. Результат Error.
  • 18. Трохи про TDD Найпростішим способом заставляєм працювати тест. Підміняєм реалізацію (Fake It). class Email { public function getDomainFromEmail($email) { return 'example.com'; } } Зелена плоса. Тест спрацьовує.
  • 19. Трохи про TDD Рефакторимо. Видаляємо дублювання. class Email { public function getDomainFromEmail($email) { return explode('@', $email)[1]; } } Зелена плоса. Тест проходить. Метод працює так як нам потрібно.
  • 20. Трохи про TDD Ще один приклад Спершу тест: class EmailTest extends PHPUnit_Framework_TestCase { public function testIsEmailValid() { $v = new Validator(); $this->assertTrue( $v->isEmailValid('test@examlple.com') ); } } Запускаєм тест. Результат Error.
  • 21. Трохи про TDD Найпростішим способом заставляєм працювати тест. class Validator { public function isEmailValid($email) { return true; } } Зелена плоса. Тест проходить.
  • 22. Трохи про TDD Добавимо більше тестових випадків (Triangulate). public function isEmailValidDataProvider() { return array( 'correct' => array('test@example.com', true), 'incorrect' => array('incorrect', false), ); } public function testIsEmailValid($email, $expectedResult) { //... $this->assertEquals($expectedResult, $v->isEmailValid ($email)); } Запускаєм і на цей раз бачим Fail. Далі пишемо правильну реалізацію.
  • 23. Трохи про TDD Якщо код зрозуміло пишіть зразу правильний тест. (Oblivious Implementation).
  • 24. Два слова про BDD - Базується на TDD. - Описує роботу Бізнесу та Девелоперів. - Бізнес пише специфікації в вигляді тестів або специфікації генеруються в тести. - Девелопери пишуть код так щоб всі тести спрацьовували. Рішення для PHP: Codeception Behat PHPUnit_Story
  • 25. Матеріали Книжки: Kent Beck - XP. Test Driven Development Martin Fowler - Refactoring: Improving the Design of Existing Code Лінки: http://www.phpunit.de/manual/3.8/en/index.html http://behat.org/ http://codeception.com/ http://getcomposer.org/ http://en.wikipedia.org/wiki/Test-driven_development http://en.wikipedia.org/wiki/Behavior-driven_development
  • 26. Дякую за увагу! Андрій Насінник Копанія: Magento Email: andriy.nas@gmail.com https://github.com/Nas1k Skype: nas_ua