SlideShare 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

More Related Content

What's hot

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

What's hot (9)

SQL: Indexes, Select operator
SQL: Indexes, Select operatorSQL: Indexes, Select operator
SQL: Indexes, Select operator
 
Тестування при розробці програмного забезпечення. Unit Tests.
Тестування при розробці програмного забезпечення. Unit Tests.Тестування при розробці програмного забезпечення. Unit Tests.
Тестування при розробці програмного забезпечення. Unit Tests.
 
SQL Grouping, Joins
SQL Grouping, JoinsSQL Grouping, Joins
SQL Grouping, Joins
 
Ado.net module 2
Ado.net module 2Ado.net module 2
Ado.net module 2
 
Theme20_ajax
Theme20_ajaxTheme20_ajax
Theme20_ajax
 
01 c# basics
01 c# basics01 c# basics
01 c# basics
 
передача параметрів в функції
передача параметрів в функціїпередача параметрів в функції
передача параметрів в функції
 
Asynchronous programming in .NET (UA)
Asynchronous programming in .NET (UA)Asynchronous programming in .NET (UA)
Asynchronous programming in .NET (UA)
 
Sql 04n edited
Sql 04n editedSql 04n edited
Sql 04n edited
 

Viewers also liked

Magento digitalstore theme
Magento digitalstore themeMagento digitalstore theme
Magento digitalstore theme
NETBASE CMSMART
 
Blogging For Business
Blogging For BusinessBlogging For Business
Blogging For Business
Odofin Caleb
 
Proyecto 10 poblado
Proyecto 10 pobladoProyecto 10 poblado
Proyecto 10 pobladoNancy Romo
 
Retro-compatibilidade em Android
Retro-compatibilidade em AndroidRetro-compatibilidade em Android
Retro-compatibilidade em Android
Pedro Veloso
 
Jing Qiu's journal entry
Jing Qiu's journal entryJing 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#BMO15 | A scuola con i Maremmans | Nino Costa
#BMO15 | A scuola con i Maremmans | Nino Costa
Officina Turistica
 
Principios e ferramentas
Principios e ferramentasPrincipios e ferramentas
Principios e ferramentas
Luis Abreu
 
Музей освіти Меджибожа
Музей освіти МеджибожаМузей освіти Меджибожа
Музей освіти Меджибожа
Олександр Дрижал
 
Acoso escolar baleares
Acoso escolar balearesAcoso escolar baleares
Acoso escolar balearesIvanaGonzales
 

Viewers also liked (11)

Magento digitalstore theme
Magento digitalstore themeMagento digitalstore theme
Magento digitalstore theme
 
Blogging For Business
Blogging For BusinessBlogging For Business
Blogging For Business
 
Proyecto 10 poblado
Proyecto 10 pobladoProyecto 10 poblado
Proyecto 10 poblado
 
Retro-compatibilidade em Android
Retro-compatibilidade em AndroidRetro-compatibilidade em Android
Retro-compatibilidade em Android
 
Jing Qiu's journal entry
Jing Qiu's journal entryJing Qiu's journal entry
Jing Qiu's journal entry
 
#BMO15 | A scuola con i Maremmans | Nino Costa
#BMO15 | A scuola con i Maremmans | Nino Costa#BMO15 | A scuola con i Maremmans | Nino Costa
#BMO15 | A scuola con i Maremmans | Nino Costa
 
Proyecto Yaku Manta Yachay
Proyecto Yaku Manta YachayProyecto Yaku Manta Yachay
Proyecto Yaku Manta Yachay
 
Jefferson jara
Jefferson jaraJefferson jara
Jefferson jara
 
Principios e ferramentas
Principios e ferramentasPrincipios e ferramentas
Principios e ferramentas
 
Музей освіти Меджибожа
Музей освіти МеджибожаМузей освіти Меджибожа
Музей освіти Меджибожа
 
Acoso escolar baleares
Acoso escolar balearesAcoso escolar baleares
Acoso escolar baleares
 

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

Tdd, ти де?
Tdd, ти де?Tdd, ти де?
Tdd, ти де?
Roman Mazur
 
Php unit. Y. Muzychushun
Php unit. Y. MuzychushunPhp unit. Y. Muzychushun
Php unit. Y. MuzychushunHRdepartment
 
07 - vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
07 -  vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...07 -  vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
07 - vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
Igor Bronovskyy
 
05 Operations And Utilities
05 Operations And Utilities05 Operations And Utilities
05 Operations And Utilitiesolegapster
 
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
OdessaJS Conf
 
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
QAFest
 
Clean code (UA)
Clean code (UA)Clean code (UA)
Clean code (UA)
Oleksandr Pavlyshak
 
"How I don't need a state management library in React app", Tetiana Melnyk
"How I don't need a state management library in React app", Tetiana Melnyk "How I don't need a state management library in React app", Tetiana Melnyk
"How I don't need a state management library in React app", Tetiana Melnyk
Fwdays
 
Coding for Future in Lutsk. JavaScript. Part 11
Coding for Future in Lutsk. JavaScript. Part 11Coding for Future in Lutsk. JavaScript. Part 11
Coding for Future in Lutsk. JavaScript. Part 11
Олег Вілігурський
 
09 Static Polymorphism
09 Static Polymorphism09 Static Polymorphism
09 Static Polymorphismolegapster
 

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

Tdd, ти де?
Tdd, ти де?Tdd, ти де?
Tdd, ти де?
 
Php unit. Y. Muzychushun
Php unit. Y. MuzychushunPhp unit. Y. Muzychushun
Php unit. Y. Muzychushun
 
07 - vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
07 -  vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...07 -  vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
07 - vysnovky z tdd, pohliad pochatkivtsia - vitalii zinchenko it event 2013...
 
Design patterns part 1
Design patterns part 1Design patterns part 1
Design patterns part 1
 
PHP
PHPPHP
PHP
 
05 Operations And Utilities
05 Operations And Utilities05 Operations And Utilities
05 Operations And Utilities
 
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
"Is there life in react without redux" by Babich Sergiy. OdessaJS'2021
 
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
QA Fest 2015. Ярослав Пернеровский. Мутанты наступают - смогут ли ваши тесты...
 
Clean code (UA)
Clean code (UA)Clean code (UA)
Clean code (UA)
 
"How I don't need a state management library in React app", Tetiana Melnyk
"How I don't need a state management library in React app", Tetiana Melnyk "How I don't need a state management library in React app", Tetiana Melnyk
"How I don't need a state management library in React app", Tetiana Melnyk
 
Coding for Future in Lutsk. JavaScript. Part 11
Coding for Future in Lutsk. JavaScript. Part 11Coding for Future in Lutsk. JavaScript. Part 11
Coding for Future in Lutsk. JavaScript. Part 11
 
Theme24-jQuery
Theme24-jQueryTheme24-jQuery
Theme24-jQuery
 
09 Static Polymorphism
09 Static Polymorphism09 Static Polymorphism
09 Static Polymorphism
 
Automated testing
Automated testingAutomated testing
Automated testing
 

Тестування з допомогою 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