Thursday, August 28, 2014

PHPUnit in Zend Framework 2

Hi,

Process of setup PHPUnit testing in Zend Framework-2:

NOTE: Before starting to describe the process of PHPUnit i assuming that readers are aware of Zend Framework-2.

Step 1: PHPUnit Installation with the help of "Pear"
# pear config-set auto_discover 1
# pear install pear.phpunit.de/PHPUnit

Step 2: Create "test" directory inside your module.

Step 3: create phpunit.xml, TestConfig.php and Bootstrap.php file inside the "test" directory.

phpunit.xml File
<?xml version="1.0" encoding="UTF-8"?> 
<phpunit bootstrap="Bootstrap.php">
 <php>
  <!--server name="SERVER_PORT" value="80"/ -->
   </php>
    <testsuites>
        <testsuite name="Demo PHPUnit">
            <directory>./ApplicationTest</directory>
        </testsuite>
    </testsuites>
</phpunit>

TestConfig.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<?php
return array(
    'modules' => array(
        // Other modules needed
        'Application',
    ),
    'module_listener_options'   => array(
        'config_glob_paths' => array(
            '../../../config/autoload/{,*.}{global,local}.php',
        ),
        'module_paths'      => array(
            'module',
            'vendor',
        ),
    ),
);


Bootstrap.php

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<?php
namespace ApplicationTest; // our namespace
 
use Zend\Loader\AutoloaderFactory;
use Zend\Mvc\Service\ServiceManagerConfig;
use Zend\ServiceManager\ServiceManager;
use Zend\Stdlib\ArrayUtils;
use RuntimeException;
use Zend\Session\Container;
 
error_reporting(E_ALL | E_STRICT);
chdir(__DIR__);
 
class Bootstrap
{
    protected static $serviceManager;
    protected static $config;
    protected static $bootstrap;
 
    public static function init()
    {
        // Load the user-defined test configuration file, if it exists; otherwise, load
        if (is_readable(__DIR__ . '/TestConfig.php')) {
            $testConfig = include __DIR__ . '/TestConfig.php';
        } else {
            $testConfig = include __DIR__ . '/TestConfig.php.dist';
        }
 
        $zf2ModulePaths = array();
 
        if (isset($testConfig['module_listener_options']['module_paths'])) {
            $modulePaths = $testConfig['module_listener_options']['module_paths'];
            foreach ($modulePaths as $modulePath) {
                if (($path = static::findParentPath($modulePath)) ) {
                    $zf2ModulePaths[] = $path;
                }
            }
        }
         
        $zf2ModulePaths  = implode(PATH_SEPARATOR, $zf2ModulePaths) . PATH_SEPARATOR;
        $zf2ModulePaths .= getenv('ZF2_MODULES_TEST_PATHS') ?: (defined('ZF2_MODULES_TEST_PATHS') ? ZF2_MODULES_TEST_PATHS : '');
 
        static::initAutoloader();
 
        // use ModuleManager to load this module and it's dependencies
        $baseConfig = array(
            'module_listener_options' => array(
                'module_paths' => explode(PATH_SEPARATOR, $zf2ModulePaths),
            ),
        );
 
        $config = ArrayUtils::merge($baseConfig, $testConfig);
 
        $serviceManager = new ServiceManager(new ServiceManagerConfig());
        $serviceManager->setService('ApplicationConfig', $config);
        $serviceManager->get('ModuleManager')->loadModules();
 
        static::$serviceManager = $serviceManager;
        static::$config = $config;
    }
 
    public static function getServiceManager()
    {      
        return static::$serviceManager;
    }
 
    public static function getConfig()
    {
        
        return static::$config;
    }
 
    protected static function initAutoloader()
    {
        $vendorPath = static::findParentPath('vendor');
 
        if (is_readable($vendorPath . '/autoload.php')) {
            $loader = include $vendorPath . '/autoload.php';
        } else {
            $zf2Path = getenv('ZF2_PATH') ?: (defined('ZF2_PATH') ? ZF2_PATH : (is_dir($vendorPath . '/ZF2/library') ? $vendorPath . '/ZF2/library' : false));
 
            if (!$zf2Path) {
                throw new RuntimeException('Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.');
            }
 
            include $zf2Path . '/Zend/Loader/AutoloaderFactory.php';
 
        }
        
        AutoloaderFactory::factory(array(
            'Zend\Loader\StandardAutoloader' => array(
                'autoregister_zf' => true,
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/' . __NAMESPACE__,
                ),
            ),
        ));
    }
 
    protected static function findParentPath($path)
    {
        $dir = __DIR__;
        $previousDir = '.';
        while (!is_dir($dir . '/' . $path)) {
            $dir = dirname($dir);
            if ($previousDir === $dir) return false;
            $previousDir = $dir;
        }
        return $dir . '/' . $path;
    }
}
 
Bootstrap::init();



Step 4: Create directory for module testing inside the "test" directory. Name should be same as the module name.
EX: if your module name is "Report" then your testing module-name would be "ReportTest"

Step 5: Create Controller directory whose name would be "Controller" inside the Test module i.e. "ReportTest"

Step 6: Create controller class file inside your controller dir, named as your main module controller file-name.
ex: your module controller name as "IndexController" then test-module controller file name should be "IndexControllerTest".

IndexControllerTest.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php
 
namespace ApplicationTest\Controller;
use ApplicationTest\Bootstrap;
use Zend\Mvc\Router\Http\TreeRouteStack as HttpRouter;
use Application\Controller\IndexController;
use Zend\Http\Request;
use Zend\Http\Response;
use Zend\Mvc\MvcEvent;
use Zend\Mvc\Router\RouteMatch;
use Zend\Test\PHPUnit\Controller\AbstractControllerTestCase;
// use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class IndexControllerTest extends AbstractControllerTestCase
{
    protected $controller;
    protected $request;
    protected $response;
    protected $routeMatch;
    protected $event;
    protected $userMockObj;
    protected $serviceManager;
    
    public function setUp()
    {
        $this->serviceManager = Bootstrap::getServiceManager();
        $this->controller = new IndexController();
        $this->request    = new Request();
        $this->routeMatch = new RouteMatch(array('controller' => 'index'));
        $this->event      = new MvcEvent();
        $config = $this->serviceManager->get('Config');
        $routerConfig = isset($config['router']) ? $config['router'] : array();
        $router = HttpRouter::factory($routerConfig);
         
        $this->event->setRouter($router);
        $this->event->setRouteMatch($this->routeMatch);
        $this->controller->setEvent($this->event);
        $this->controller->setServiceLocator($this->serviceManager);
        $this->userMockObj = $this->getMockBuilder('Application\Model\TestModel')
                                    ->disableOriginalConstructor()
                                    ->getMock();
        $this->setApplicationConfig(
                include __DIR__.'/../../TestConfig.php'
        );
        parent::setUp();
    }
    
    public function testWorkAction() 
    {
        $this->serviceManager->setAllowOverride(true);
        $this->serviceManager->setService('Application\Model\TestModel', $this->userMockObj);
        
        $this->routeMatch->setParam('action', 'work');
        $response = $this->controller->getResponse();
        $result   = $this->controller->dispatch($this->request, $response);
        
        $this->assertEquals(200, $response->getStatusCode());
        
        // Check a ViewModel has been returned
        $this->assertInstanceOf('Zend\View\Model\ViewModel', $result);
        
        // Test against the test data
        $variables = $result->getVariables();
        $this->assertArrayHasKey('name', $variables);
        // Very lazy validation of data ;-)
        $this->assertEquals('OSSCube1', $variables["name"]);

        $this->dispatch('/index');
        $this->assertModuleName('Application');
        $this->assertControllerClass('IndexController');
        $this->assertMatchedRouteName('xyz');
        $this->assertControllerName('Application\Controller\Index');
    }

    public function testMemory() {
        $this->assertGreaterThanOrEqual(699328, memory_get_usage());
    }
}
?>


Now your directory structure would look like as:


Step 7: Run the phpunit inside of the "test" directory. then you will see some output if your test run successfully like as :

#phpunit
PHPUnit 4.1.3 by Sebastian Bergmann.
..
Time: 00:00
OK (2 tests)

Step 8: Some time you will get error, then there would be some code return that has some significant role like as:
. Printed when the test succeeds.
F Printed when an assertion fails while running the test method.
E Printed when an error occurs while running the test method.
S Printed when the test has been skipped.
I  Printed when the test is marked as being incomplete or not yet implemented.
Step 9: To get the html report for the code coverage analysis of your code, it's a 
feature of the phpunit to get the beautiful html formatted dashboard and reports.
To get this feature you have to install the PHP xDebug module.
# sudo pecl install xdebug 
Now, You can create the report by the below command:
# phpunit --coverage-html dir-name
Here, dir-name is the directory where you will put the report content. It will take bit of time to generate the html report. Once your report generated then just open the index.html file in your browser....










To see the code coverage for the tested code:



















In similar way you can get the dashboard on click of dashboard link that contain nice graph(s):
















I hope it will help you to run PHPUnit in Zend Framework-2. If anybody got issue during setup, Please put your comment, i highly appreciate that.. :)


Monday, June 30, 2014

Zend Server Deployment : With the help of ZPK File

Deployment of ZPK file of your application is pretty simple as compared to ZPK file creation.

Minimum requirement of the ZPK file deployment is installed Zend-Server version 6.2 on your system.

Once Zend-Server installed, just logged-in into zend-server, where you will see the home screen like as :


Here, You will see the Application tab where you can deploy the zpk file of your application.

click on the "Application -> Apps" tab, then you will see the below screen as:



Here, you will see the number of application deployed in "Name" column.
Now click on "Deploy Application" then select your ZPK file to deploy.


























Here, you will see option to upload the zpk file, upload your ZPK file and click next:



























Fill the "Display Name" which will appear in the "Name" column after deploy. Here, you can add your virtual host name where your application will resolve. Path field is optional, if you add path then Url would be like as:
"http://cmdpglock.in:80/path"

After fill the all detail, click "Next". after that you will see the Licence agreement screen as:


























Just accept the agreement of Licence, then click "Next".

Here, you will see all the Prerequisites for the application deploy, If all are okey, then click "Next" :

Fill "Host" as your Hosting server address, Database credentials etc. then click "Next" for the final deployment:
Click on Deploy, you will see the updated screen with your deploy name in "Name" column.

Now open the host URL of your site in your browser, your will see that your site is working.

Its Easy and simple :)

Here, now question is where is your virtual hosting occur at server level?

Virtual-host is setup at zend-server installation via creating a new .conf file at "/usr/local/zend/etc/site.d/" location and your application content stored at "/usr/local/zend/var/apps/http/" location.

Cool...

I hope above content would be helpful for the deploy process.






 

Thursday, June 26, 2014

Creating an Application Package(.ZPK) for Deployment on Zend Server

Hi,

This article is aimed to help you better understand how to better deal with deployments in your development workflow and provide some best practices for deployments. Sometimes a bad production deployment can ruin all the effort you invested in a development process. Having a solid deployment workflow can become one of the greatest advantages of your team.

So what actually is deployment means ?

Deploying an application is the process of copying, configuring and enabling a specific application to a specific base URL on Zend Server or on a cluster. Once the deployment process has finished, the application becomes publicly accessible on the base URL. The server carries out this two step process by first staging the application, and then activating it after successful staging.



The deployment mechanism in Zend Server uses a ZPK file, which contains the source code, assets and the deployment descriptor.

Application Package(.zpk) file for the deployment on Zend Server can be created via a Zend-Studio GUI OR Linux console.Both are ease to implement.

Via Zend-Studio IDE: This is for GUI lover :)

Step 1: 
From Zend IDE, select your application for which you want to create the zpk file.

Step 2: 
Right click on the application, then selecting “Add Application Deployment Support”

 
It will create deployment.xml file in your aplication and opens it on your IDE.

Step 3: 
Screen that you will get on your IDE is:



Most of the fields are self explanatory but a few might require a few words.
  • Document Root – This is the document root which is relative to the base directory of the deployment. 
  • License – This is the relative path to a text file in the project directory structure that contains the EULA for the project.  During the deployment work-flow in the UI the end user will be presented with this if the file is available and will be required to agree to it before proceeding.
  • Persistent Resources – These are items that you don’t want to have overwritten during an upgrade.  For example, cache directories.

Dependencies

There are several different types of dependencies you can specify for your application.
These dependencies will be checked prior to deploying the application.  If they are not satisfied then the application will not deploy.

Triggers

There are several triggers that can be hooked into during the deployment process, each of which has a Pre and Post stage
  • Activate
  • Deactivate
  • Stage
  • Unstage
To set up a trigger simply double click on the stage that you would like to edit and a new file will be created for you.  In that file will be documentation on information on how to retrieve variables and parameters for your deployment scripts.
Speaking of variables and parameters, what is the difference?  There are two differences.
  1. Variables you cannot change during the deployment process.  What the value is in the deployment file is the value that you will get in the deployment script.  Parameters need to be specified during the deployment work-flow and also have some validation that you can do on the entered values whereas with variables you do not.
  2. Both are accessible via getenv() during deployment but variables are retrieved with their names “as is” but parameters are upper cased and prepended with “ZS_”.  So if you have a parameter named “ugly_Duckling” it would be accessed via getenv(‘ZS_UGLY_DUCKLING’)

Package

There may be files in your application that you want to include or exclude.  You can specify those in the Package panel.
 
Exporting
The last step is to export your project.  Right click on the project and select Export and choose “Deployment Package”.  This will output the project into a ZPK file that you can then upload to your Zend Server instance or Zend Application Fabric installation where it will be deployed to your website. 







=================================================
 Via Linux Console : This is for Command line lovers :)
=================================================

Here, i am using Zend's Deployment Tool that allows you to create a skeleton package, and pack the contents into a .zpk package.

Tool location - The tool is located in:
  • Linux - '/usr/local/zend/bin/zdpack'
  • Windows - 'C:Program Files\Zend\ZendServer\bin\zdpack' -OR- as a 
  • standalone (if downloaded separately from the product).

Usage - Run the help command (Linux: '<install_dir>/bin/zdpack --help'; Windows: 'zdpack.exe --help') from the bin directory to see the usage.

The command line actions are:
Step 1
Select a directory and use the create command (Linux: '<install_dir>/bin/zdpack create <application-name>'; Windows: zdpack.exe create <application-name>'
where is your application's name) to create the skeleton of your .zpk package. This includes the XML descriptor file, the data folder and the hook scripts (templates).
Go to the directory to see the resources that have been created:
  • Data folder - The folder that will contain your application files.
  • Scripts folder - The hook script skeletons available for you to edit as needed. 
  • deployment.xml file - The template of the XML descriptor for you to edit as needed.

Step 2:
Perform the following actions:
  • Place your application files in the data folder. 
  • Edit the hook scripts according to your needs. 
  • Edit the XML file as needed. The XML template is made up of example elements.  
  • Validate the package by using the validate command (Linux: '<install_dir>/bin/zdpack validate [--schema=<xsd-file>] <package-xml-descriptor-file>'; Windows: 'zdpack.exe validate [--schema=<xsd-file>] <package-xml-descriptor-file>'). 

For example:
# /usr/local/zend/bin/zdpack validate --schema="/usr/local/zend/share/deployment.xsd" deployment.xml


NOTE: For ZF2 application zpk file creation, I edit the deployement.xml file for the document root settings i.e.
<docroot>data</docroot> 
TO 
<docroot>data/public</docroot>

Step 3:
Use the pack command (Linux: '<install_dir>/bin/zdpack pack <application-name>'; Windows: 'zdpack.exe pack <application-name>') to pack the contents into a .zpk package. By default, the Deployment Tool will create the package in the working directory.
For Example:
# /usr/local/zend/bin/zdpack pack my_application_dir


Once you have a .zpk application package ready and packed, you can deploy your application OR update an existing application.


--
Bye Buddy