TTD in ZF2

Пространства имен

Замыкания

ZF2 поставляемые в стандартной
поставке тесты

Поддержка нового phpunit 3.5
# ls
Bootstrap.php docs phpunit.xml resources runtests.sh
TestConfiguration.php.dist Zend
# cat TestConfiguration.php.dist...
Стукрутра папок
- library - модульные
- application - интеграционные
+ functional - функциональные
+ perfomance — функцион...
Тестировать не нужно
- Zend Framework
- Doctrine / Propel
- Jquery / Prototype / Dojo
- Symphony DI / Crafty / DI
- all ex...
Тестировать нужно
- Абстрактные классы и интефейсы
- Базовые компонеты
- Магическую инициализацию
- Любые не очевидные вещи
DRY – не повторяться
1 тест – 1 проверка
Хороший тест – 5 строк
Если что-то протестировано, не
тетсируем это снова
Крохобо...
Class => ClassName + Test.php
Namespace => Test
PhpDoc => bugNumber
_files — для тестовых файлов
_fixtures — для фикстур
p...
<phpunit colors="true" bootstrap="./bootstrap.php">
<testsuite name="Test/Library">
<directory>./library/</directory>
</te...
/test/tests/application/controllers# cat IndexControllerTest.php
namespace Test;
class IndexController extends ZendTestPHP...
Тестирование Controller
class IndexController extends ZendTestPHPUnitControllerTestCase
public function testIndexAction()
...
Тестирование Controller::init
<?php
abstract class AbstractController extends ZendControllerAction
{
public function init(...
Тестирование Controller:init
class AbstractController extends ZendTestPHPUnitControllerTestCase
public function testInitCo...
Тестирование Form
<?php
namespace ApplicationForm;
class Registration extends ZendFormForm
public function init()
$this->a...
Тестирование Form
class Registration extends PHPUnit_Framework_TestCase
public function testValidate()
$form = new Applica...
Архитектура
→ getConnection
→ getDataSet
→ createDbTableDataSet
→ createDbTable
→ createDbRowset
Тестирование DbTable
$categories = ne...
Тестирование DbTable
class CategoriesTest extends ZendTestPHPUnitDatabaseTestCase
public function getConnection()
$applica...
Тестирование DbTable
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<categories id="1" name="cat1" />
<categories id="3"...
Тестирование Mapper
1. Использует сервис/сервисы
2. Используется моделями
3. Содержит код
setTable/getTable/__construct/in...
Тестирование Mapper
<?php
namespace ApplicationModel;
class XXXMapper
{
protected $_table = null;
protected $_defaultServi...
Тестирование Mapper

Выделить общий класс
AbstractMapper

Выделить интерфейс для сервисов

Наследовать все мапперы от
а...
Тестирование Mapper
<?php
namespace ApplicationModel;
class AbstractMapper
{
protected $_service = null;
protected $_defau...
Тестирование Mapper

Создаем реализации

Складываем в подпапку _files в
текущей директории
__Construct / Abstract class ...
Тестирование Mapper
class AbstractMapperTest extends PHPUnit_Framework_TestCase
public function testInit()
$mock = new Abs...
Тестирование Selenium
Selenium RC
Selenium IDE
Selenium GRID
Тестирование Selenium
Тестирование Selenium
Native = left
<div id=”left”> <input name='left'>
Xpath = //div[@id='left']
<div id=”left”>
Css =
cs...
Тестирование Selenium
class Example extends PHPUnit_Extensions_SeleniumTestCase
{
protected $captureScreenshotOnFailure = ...
Тестирование Selenium
public function testAjaxLoading()
{
$this->open("/index/index/");
$this->assertEquals("index", $this...
Тестирование Selenium
class IndexController extends PHPUnit_Extensions_SeleniumTestCase
{
public function testHighlight()
...
Тестирование Selenium
Вопросы ?
Upcoming SlideShare
Loading in...5
×

Юнит тестирование в Zend Framework 2.0

2,024

Published on

Ростислав Михайлив
Chief Developer / Software Architect, Gadu-Gadu

Published in: Technology, Education
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,024
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
14
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Юнит тестирование в Zend Framework 2.0

  1. 1. TTD in ZF2
  2. 2.  Пространства имен  Замыкания  ZF2 поставляемые в стандартной поставке тесты  Поддержка нового phpunit 3.5
  3. 3. # ls Bootstrap.php docs phpunit.xml resources runtests.sh TestConfiguration.php.dist Zend # cat TestConfiguration.php.dist /** * Zend_Db_Adapter_Sqlsrv * Note: Make sure that you create the "test" database and set a * username and password * */ define('TESTS_ZEND_DB_ADAPTER_SQLSRV_ENABLED', false); define('TESTS_ZEND_DB_ADAPTER_SQLSRV_HOSTNAME', ''); define('TESTS_ZEND_DB_ADAPTER_SQLSRV_USERNAME', null); define('TESTS_ZEND_DB_ADAPTER_SQLSRV_PASSWORD', null); define('TESTS_ZEND_DB_ADAPTER_SQLSRV_DATABASE', 'test');
  4. 4. Стукрутра папок - library - модульные - application - интеграционные + functional - функциональные + perfomance — функциональные
  5. 5. Тестировать не нужно - Zend Framework - Doctrine / Propel - Jquery / Prototype / Dojo - Symphony DI / Crafty / DI - all extenal libraries ...
  6. 6. Тестировать нужно - Абстрактные классы и интефейсы - Базовые компонеты - Магическую инициализацию - Любые не очевидные вещи
  7. 7. DRY – не повторяться 1 тест – 1 проверка Хороший тест – 5 строк Если что-то протестировано, не тетсируем это снова Крохобор (The Nitpicker) Уклонист (The Dodger) Гигант (Giant) Любитель Порядка (The Sequencer) Счётчик (The Enumerator) Избранный (The One) Тормоз (The Slow Poke) ... Основные принципы
  8. 8. Class => ClassName + Test.php Namespace => Test PhpDoc => bugNumber _files — для тестовых файлов _fixtures — для фикстур phpunit.xml @cover Class::method Организация тестов
  9. 9. <phpunit colors="true" bootstrap="./bootstrap.php"> <testsuite name="Test/Library"> <directory>./library/</directory> </testsuite> <testsuite name="Test/Application"> <directory>./application/</directory> </testsuite> <testsuite name="Test/Functional"> <directory>./functional/</directory> </testsuite> <logging> <log type="coverage-html" target="/tmp" charset="UTF-8" yui="true" highlight="false" lowUpperBound="35" highLowerBound="70"/> </logging> </phpunit>
  10. 10. /test/tests/application/controllers# cat IndexControllerTest.php namespace Test; class IndexController extends ZendTestPHPUnitControllerTestCase { public $bootstrap = '../../bootstrap.php'; /** * @group Bug123 * @cover IndexController::indexAction */ public function testIndexAction() { $this->dispatch('/'); $this->assertController("index"); $this->assertAction("index"); } } Тестирование Controller
  11. 11. Тестирование Controller class IndexController extends ZendTestPHPUnitControllerTestCase public function testIndexAction() $this->dispatch('/'); $this->assertController("index"); $this->assertAction("index"); $this->assertQueryContentContains('#content', 'Hello Im here'); $this->assertQueryContentContains('div.content', 'Hello Im here'); $this->assertQueryContentContains('body .content', 'Hello Im here'); $this->assertQueryCount('#categories li', 3); <?php class IndexController extends AbstractController public function indexAction() $this->view->hello = 'Im here';
  12. 12. Тестирование Controller::init <?php abstract class AbstractController extends ZendControllerAction { public function init() { $this->_helper->contextSwitch() ->addActionContext('index', array('xml', 'json')) ->setAutoJsonSerialization(true) ->initContext(); $this->view->categories = new ApplicationModelCategoryMapper(); } }
  13. 13. Тестирование Controller:init class AbstractController extends ZendTestPHPUnitControllerTestCase public function testInitContext() $controller = new AbstractControllerStub($this->getRequest(), $this->getResponse()); $this->assertEquals( $controller->getHelper('ContextSwitch')->getActionContexts('index'), array('xml', 'json')); public function testInitCategories() $controller = new AbstractControllerStub($this->getRequest(), $this->getResponse()); $this->assertType('ApplicationModelCategoryMapper', $controller->view->categories);
  14. 14. Тестирование Form <?php namespace ApplicationForm; class Registration extends ZendFormForm public function init() $this->addElement('text', 'username'); $this->addElement('text', 'password'); $this->addElement('text', 'password_retype'); public function isValid($params) $result = parent::isValid($params); if ($this->getValue('password')!=$this->getValue('password_retype')) { return false; } return $result;
  15. 15. Тестирование Form class Registration extends PHPUnit_Framework_TestCase public function testValidate() $form = new ApplicationFormRegistration; $this->assertTrue($form->isValid(array( 'username' => 'test', 'password' => '123', 'password_retype' => '123', ))); public function testValidateFail() $form = new ApplicationFormRegistration; $this->assertFalse($form->isValid(array( 'username' => 'test', 'password' => '123', 'password_retype' => '1234', )));
  16. 16. Архитектура
  17. 17. → getConnection → getDataSet → createDbTableDataSet → createDbTable → createDbRowset Тестирование DbTable $categories = new ApplicationModelDbTableCategories($this->getAdapter()); $categories->insert(array('id'=>4, 'name'=>'test')); $this->assertDataSetsEqual( $this->createFlatXmlDataSet("_fixtures/categoriesInsert.xml"), $this->createDbTableDataSet(array($categories)) );
  18. 18. Тестирование DbTable class CategoriesTest extends ZendTestPHPUnitDatabaseTestCase public function getConnection() $application = new Application (_ENV, _PATH . '/configs/application.ini'); $application->bootstrap(); $resource = $application->getBootstrap()->getPluginResource('db'); return $this->createZendDbConnection($resource->getDbAdapter(), 'any'); public function getDataSet() return $this->createFlatXMLDataSet(__DIR__ . '/_fixtures/categories.xml'); public function testFecthAll() $categories = new ApplicationModelDbTableCategories($this->getAdapter()); $rowset = $categories->fetchAllOrdered(); $this->assertEquals(count($rowset), 3);
  19. 19. Тестирование DbTable <?xml version="1.0" encoding="UTF-8"?> <dataset> <categories id="1" name="cat1" /> <categories id="3" name="cat3" /> <categories id="2" name="cat2" /> </dataset> <?xml version="1.0" encoding="UTF-8"?> <dataset> <categories id="1" name="cat1" /> <categories id="3" name="cat3" /> <categories id="2" name="cat2" /> <categories id="4" name="test" /> </dataset>
  20. 20. Тестирование Mapper 1. Использует сервис/сервисы 2. Используется моделями 3. Содержит код setTable/getTable/__construct/init которые идентичны и миргурируют из одного маппера в другой + есть еще внешние источники данных SOAP/XML-RPC/REST/RSS
  21. 21. Тестирование Mapper <?php namespace ApplicationModel; class XXXMapper { protected $_table = null; protected $_defaultServiceName = ''; public function __construct(DbTable $table=null) public function getTable() public function setTable(DbTable $table) … }
  22. 22. Тестирование Mapper  Выделить общий класс AbstractMapper  Выделить интерфейс для сервисов  Наследовать все мапперы от абстрактного  Имплементировать интерфейс Service в DbTable
  23. 23. Тестирование Mapper <?php namespace ApplicationModel; class AbstractMapper { protected $_service = null; protected $_defaultServiceName = ''; public function __construct(Service $service=null) { if (is_null($service)) { $name = $this->_defaultServiceName; $this->setService(new $name); } else { $this->setService($this->_service = $service); } } public function getService() public function setService(Service $service) }
  24. 24. Тестирование Mapper  Создаем реализации  Складываем в подпапку _files в текущей директории __Construct / Abstract class / Interface <?php namespace Test; class AbstractMapperMockAutoload extends ApplicationModelAbstractMapper { protected $_defaultServiceName = 'TestServiceMock'; }
  25. 25. Тестирование Mapper class AbstractMapperTest extends PHPUnit_Framework_TestCase public function testInit() $mock = new AbstractMapperMockAutoload(); $this->assertType('TestServiceMock', $mock->getService()); public function testInitFail() try { $mock = new AbstractMapperMock(); } catch (Exception $e) { return ; } $this->fail('An expected exception has not been raised.'); public function testSet() $mock = new AbstractMapperMockAutoload(); $mock->setService(new ServiceMock()); $this->assertType('TestServiceMock', $mock->getService());
  26. 26. Тестирование Selenium Selenium RC Selenium IDE Selenium GRID
  27. 27. Тестирование Selenium
  28. 28. Тестирование Selenium Native = left <div id=”left”> <input name='left'> Xpath = //div[@id='left'] <div id=”left”> Css = css=ul#recordlist li:nth-child(4) css=input[name='continue'][type='button'] css=a[id^='id_prefix_'] css=a:contains('Log Out')
  29. 29. Тестирование Selenium class Example extends PHPUnit_Extensions_SeleniumTestCase { protected $captureScreenshotOnFailure = TRUE; protected $screenshotPath = '~/conf/public/screenshots'; protected $screenshotUrl = 'http://conf.local/screenshots'; protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("http://conf.local/"); } public function testMyTestCase() { $this->open("index/index"); $this->assertEquals("index", $this->getText("content")); } }
  30. 30. Тестирование Selenium public function testAjaxLoading() { $this->open("/index/index/"); $this->assertEquals("index", $this->getText("content")); $this->click("showIndexInAjax"); for ($second = 0; ; $second++) { if ($second >= 60) $this->fail("timeout"); try { if ("Im here" == $this->getText("content")) break; } catch (Exception $e) {} sleep(1); } $this->assertEquals("Im here", $this->getText("content")); }
  31. 31. Тестирование Selenium class IndexController extends PHPUnit_Extensions_SeleniumTestCase { public function testHighlight() { $this->open("/index/index/"); $this->mouseOver("//div[@id='left']/li"); $this->assertEquals("rgb(255, 0, 0)", $this->getEval( "this.findEffectiveStyleProperty(this.page() .findElement("//div[@id='left']/li"), 'backgroundColor')")); }
  32. 32. Тестирование Selenium Вопросы ?
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×