Robert Basic's blog

Archives for September, 2012

Let's learn Astronomy!

by Robert Basic on September 29, 2012.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

I've graduated from Subotica Tech back in 2009., and earned a BsC in electrical engineering, or some such. Even though I had the opportunity to continue my academic studies, I decided that I had enough of schools for a while, and that I should start working. Turns out, that was a pretty smart move from my side, as I ended up working for two years with an awesome team, and later on started my own company, which is now over a year old! Yey!

But, recently I started thinking about going back to school again. Not for a new diploma, or to be able to get a better job, but for the knowledge itself. My brain craves Science. Mathematics. Formulae. My mind needs a new challenge. Sure, I could learn a new programming language, I hear Haskell would give me quite a challenge, but at this point, that just wouldn't be... It.

Introduction to Astronomy

A few weeks back Vranac sent me a link to Coursera's Course Catalog. I browsed through it, made a note about a couple of interesting ones, and left it at that. Until yesterday, when Andries brought up the subject of gaining new knowledge. For some odd reason, that made me do a step forward.

Thus, I singed up for the Introduction to Astronomy course. Why Astronomy? Because it should have a fair share of math and physics which will, hopefully, prove more than enough for my science hunger. Plus, learning things about planets and stars and galaxies cannot be anything else but fun! Maybe I even learn to recognize a constellation or two in the night skies.

I don't really know what to expect from the course itself, but it should be a good starting point as any. The description says it's a difficult course, lasts for 9 weeks, and has three hours of video lectures per week with additional homework and quizes. Guess it'll be interesting, we'll see.

Happy learnin'!

P.S.: I forgot to mention that these courses on Coursera are on-line, and free!

Tags: astronomy, course, coursera, learning.
Categories: Blablabla, Free time.

Unit testing Zend Framework 2 modules

by Robert Basic on September 15, 2012.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

Porting this blog to Zend Framework 2, I decided to write some unit tests as well, while I’m at it. Not that the current code base doesn’t have unit tests, just it doesn’t have much of it… Anyway, I’d like to show how to get unit tests for modules up and running, as well how to throw in Mockery in the mix, as it can help us greatly with mocking out objects. Some of the parts shown here probably could be written in a more cleaner/nicer way, especially the autoloading bit, but so far it works for me.

The phpunit.xml file is rather simple:

<phpunit bootstrap='./bootstrap.php' colors='true'>
    <testsuite name='ZF2 Module Test Suite'>
        <directory>.</directory>
    </testsuite>
    <filter>
        <whitelist>
            <directory suffix='.php'>../src/</directory>
        </whitelist>
    </filter>
    <listeners>
        <listener class="\Mockery\Adapter\Phpunit\TestListener"
            file="Mockery/Adapter/Phpunit/TestListener.php"></listener>
    </listeners>
</phpunit>

The Mockery TestListener, as I found out the hard way, is needed for Mockery to work properly. You might add in some more stuff, like generating code coverage reports, and the like.

In the bootstrap.php we set up the autoloading for the modules, the ZF2 library, and Mockery:

<?php
putenv('ZF2_PATH=' . __DIR__ . '/../../../vendor/ZF2/library');
include_once __DIR__ . '/../../../init_autoloader.php';
set_include_path(implode(PATH_SEPARATOR, array(
    '.',
    __DIR__ . '/../src',
    __DIR__ . '/../../SomeRequiredModule/src',
    __DIR__ . '/../../../vendor',
    get_include_path(),
)));
spl_autoload_register(function($class) {
    $file = str_replace(array('\\', '_'), DIRECTORY_SEPARATOR, $class) . '.php';
    if (false === ($realpath = stream_resolve_include_path($file))) {
        return false;
    }
    include_once $realpath;
});
$loader = new \Mockery\Loader;
$loader->register();

It assumes that the currently tested module lives inside a ZF2 application. If not, you’ll probably need to adjust the paths accordingly. It also assumes that the Mockery files are in the vendor/ directory.

Testing the service layer

Don’t want to get into a fight about terminology, but the service layer for me, is the layer that lives between the controller layers and the database layers. It allows for keeping other layers clean of business logic, and easier testing. These services implement the Zend\ServiceManager\ServiceLocatorAwareInterface, which greatly simplifies unit testing, as it is easier to replace concrete objects with mocks.

Let’s assume that we have a “post” service, which we can use to get the recent posts. The post service itself does not interact with the databse, but calls an AbstractTableGateway which does all the database work. A test case for this post service, to avoid database calls, should mock the AbstractTableGateway, and use the ServiceManager to replace the concrete implementation with the mock object. An example test case for this post service could look something like this:

<?php
namespace BlogModule\Service;
use PHPUnit_Framework_TestCase as TestCase;
use Zend\ServiceManager\ServiceManager;
use Zend\Db\ResultSet\ResultSet;
use \Mockery as m;
class PostTest extends TestCase
{
    protected $postService;
    /**
    * @var Zend\ServiceManager\ServiceLocatorInterface
    */
    protected $serviceManager;
    public function setup()
    {
        $this->postService = new Post;
        $this->serviceManager = new ServiceManager;
        $this->postService->setServiceLocator($this->serviceManager);
    }
    public function testGetRecentPosts()
    {
        $mock = m::mock('Blog\Model\Table\Post');
        $this->serviceManager->setService('blogModelTablePost', $mock);
        $result = array(
            array(
                'id' => 1,
                'title' => 'Foo',
            ),
        );
        $resultSet = new ResultSet;
        $resultSet->initialize($result);
        $mock->shouldReceive('getRecentPosts')
            ->once()
            ->andReturn($resultSet);
        $posts = $this->postService->getRecentPosts();
        $this->assertSame($posts, $resultSet);
    }
}

On line 18 we set the service manager to be used with the post service, on line 22 we create a mock object, and on line 23 we set that mock object in the service manager. We set some expectations on the mock object - what method should be called, how many times and what should it return. Finally we call the actual method that is being tested on the post service and assert that the returned result is correct.

Testing the database layer

For testing the database layer, that is the AbstractTableGateway implementations, I use a little… trick. I don’t actually test what is returned from the database, but that the correct Sql\Select objects are being called, with the correct parameters in a correct order. This, in turn, means that I trust the underlying Zend\Db code that in the end, it will assemble the correct SQL queries, but I also don’t have to bother with setting up a test database, and also the tests run faster, as they don’t actually call the database. An example test case, continuing our example of getting recent posts:

<?php
namespace Blog\Model\Table;
use PHPUnit_Framework_TestCase as TestCase;
use Zend\ServiceManager\ServiceManager;
use Zend\Db\Sql\Select;
use \Mockery as m;
class PostTest extends TestCase
{
    protected $postTable;
    protected $select;
    protected $tableName = 'blog_posts';
    public function setup()
    {
        $adapter = $this->getAdapterMock();
        $this->postTable = new Post($adapter);
        $this->select = m::mock(new Select($this->tableName));
        $this->postTable->setSelect($this->select);
    }
    public function testGetRecentPosts()
    {
        $this->select->shouldReceive('from')
            ->once()
            ->with($this->tableName)
            ->andReturn($this->select);
        $this->select->shouldReceive('where')
            ->once()
            ->with(array('published = ?' => 1))
            ->andReturn($this->select);
        $this->select->shouldReceive('order')
            ->once()
            ->with('id DESC')
            ->andReturn($this->select);
        $this->select->shouldReceive('limit')
            ->once()
            ->with(10)
            ->andReturn($this->select);
        $this->postTable->getRecentPosts();
    }
}

Here we create a mock adapter (the getAdapterMock method can be seen in this gist), and use that mock adapter in our AbstractTableGateway implementation. We also create a mock Sql\Select object and we set expectations on that mock Select object. As I said, this way of testing might not be the best way out there, but it did help me catch a bug where I failed to add the where clause on the actual Select object. Yey for Mockery! Oh, and please do note that the adapter mock might not work in all cases, but again, so far it worked nicely for me.

One other thing would probably be interesting to show how to test, and that’s the action controllers, but I haven’t got around to write any controllers yet, so I’ll probably leave that for part 2. Or you could do it for homework.

Happy hackin’!

Tags: mockery, modules, testing, unit test, zend framework 2, zf.
Categories: Development, Programming, Software.

Working with custom view helpers in Zend Framework 2

by Robert Basic on September 11, 2012.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

Zend Framework hit a big milestone as version 2 was released last week. Sadly, I didn’t have time to contribute to it, or even to poke around it much. I decided to slowly, as time permits, port this blog to ZF2; it should be a good enough learning playground.

I took the skeleton application, made it even skinnier by throwing out some (for me) unneeded parts and just put it all besides my old ZF1 code. Note: I think it could be possible to have a ZF1 and a ZF2 app run side by side, something like Stefan did for Symfony1 and Symfony2. Need to investigate on this. The first problem I ran into was using custom view helpers, especially view helpers that are more general and don’t fit into one specific module. Where to put the code? How to access them in views? The second problem was how to access the service manager from a view helper? And the third problem was how to tell the helper to use a specific value when inside a specific module?

Custom view helpers

As I found out, custom view helpers can live in different places (at least two) - in the vendor/ directory, or in the module/ directory as a part of a module. Both ways are probably good solutions, but for me it’s way easier to use the custom view helpers when they are “packaged” as a module:

On the image you can see I put the helpers in a module called Hex. The module.config.php file is something like:

<?php
return array(
    'view_helpers' => array(
        'invokables' => array(
            'customHelper' => 'Hex\View\Helper\CustomHelper',
            // more helpers here ...
        )
    )
);

The Module.php file is completely basic, it just has the Module class, implementing the getConfig() and the getAutoloaderConfig() methods. Include the module in the application’s main configuration file (config/application.config.php) and now the customHelper can be simply called from the view files as:

<php echo $this->customHelper(); ?>

Service manager in a view helper

To access the service manager in a view helper, it needs to implement the ServiceLocatorAwareInterface and two methods, setServiceLocator() and getServiceLocator(). In code, this would be something like:

<?php
namespace Hex\View\Helper;
use Zend\View\Helper\AbstractHelper;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class CustomHelper extends AbstractHelper implements ServiceLocatorAwareInterface
{
    /**
     * Set the service locator.
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @return CustomHelper
     */
    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
        return $this;
    }
    /**
     * Get the service locator.
     *
     * @return \Zend\ServiceManager\ServiceLocatorInterface
     */
    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }
    public function __invoke()
    {
        $serviceLocator = $this->getServiceLocator();
        // use it at will ...
    }
}

Now, if you call getServiceLocator(), you’ll actually get the Zend\View\HelperPluginManager which gives access to other view helpers. If you want to access the “application wide” service locator, you need to call getServiceLocator() again on the HelperPluginManager. Confused yet?

<?php
// first one gives access to other view helpers
$helperPluginManager = $this->getServiceLocator();
// the second one gives access to... other things.
$serviceManager = $helperPluginManager->getServiceLocator();

Module specific values in view helpers

The problem (a bit simplified): how to tell the view helper to show “Welcome to my site!” on all routes/modules, except for the blog module, where it should show “Welcome to my blog!”. This one was the trickiest, as it can be solved in way too many ways. I first tried 2-3 different approaches, but they either didn’t work at all, or were just plain ugly hacky solutions. The final solution came to me when I answered a different question: what would be the easiest way to unit test this code? First, the custom view helper:

<?php
namespace Hex\View\Helper;
use Zend\View\Helper\AbstractHelper;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class Greeter extends AbstractHelper implements ServiceLocatorAwareInterface
{
    protected $message = null;
    /**
     * Set the service locator.
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @return CustomHelper
     */
    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
        return $this;
    }
    /**
     * Get the service locator.
     *
     * @return \Zend\ServiceManager\ServiceLocatorInterface
     */
    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }
    public function setMessage($message)
    {
        $this->message = $message;
        return $this;
    }
    public function getMessage()
    {
        if ($this->message === null) {
            // for example, get the default value from app config
            $sm = $this->getServiceLocator()->getServiceLocator();
            $config = $sm->get('application')->getConfig();
            $this->setMessage($config['message']);
        }
        return $this->message;
    }
    public function __invoke()
    {
        $message = $this->getMessage();
        return $message;
    }

And the blog module specific part, where we hook to the “preDispatch” event:

<?php
namespace Blog;
class Module
{
    public function onBootstrap($e)
    {
        $eventManager = $e->getApplication()->getEventManager();
        $eventManager->attach('dispatch', array($this, 'preDispatch'), 100);
    }
    public function preDispatch($e)
    {
        $matchedRoute = $e->getRouteMatch()->getMatchedRouteName();
        // check for the matched route
        // and change the greeter message if needed
        if ($matchedRoute == 'blog') {
            $moduleConfig = $this->getConfig();
            $sm = $e->getApplication()->getServiceManager();
            $helper = $sm->get('viewhelpermanager')->get('greeter');
            $helper->setMessage($moduleConfig['message']);
        }
    }

And that would be it. I think.

Happy hackin’!

Tags: custom, php, view helpers, zend framework 2, zf.
Categories: Development, Programming, Software.

One hundred kilometers

by Robert Basic on September 06, 2012.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

One hundred and two kilometers, and three hundred-ish meters, to be precise. I just got home from my latest “run”, and that is the total number of kilometers I made (and tracked) on my longboard since I got it back in July. Maybe it doesn’t sound like much, but if someone would have told me 2-3 months ago, that I would do this much physical activity and actually like it and enjoy it, I would probably tell it’s just crazy talk. Me, getting up my arse from the chair and doing something outside? No way, dude.

Yes way, dude!

Getting into this longboarding thing is the bestest thing that happened to me in a while. Appart from it being healthy, making me feel awesome after a nice long ride, it also helps me clear my mind after a long day in the office. It’s just me, the board and the road. And it’s super fun! No, really, it is! You should try it. If you don’t trust me, ask Swizec, he’ll tell you the same.

The board itself is great, although the bearings are making some strange noise so I’ll probably change them soon. I’ll need to buy knee and elbow pads too, because this past weekend I had a nice little fall resulting in scratches and general pain on most of my body, so just to be prepared for the next time I decide to go downhilling. Lucky I had my helmet and sliding gloves on. Always wear a helmet. Always.

Now, onwards to the next milestone - one thousand kilometers. Until then,

Happy hackin’ and happy ridin’!

Tags: fun, longboard, longboarding.
Categories: Blablabla, Free time.