In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

Now that my repustateApi client component both has working API calls and 100% code coverage from its unit tests, I want to make a PEAR package ready for release. At this stage, I’m only going to release it for internal testing (and so that the other components in my app can use it); there are plenty of other things to be done before it is really fit to release to the wider world.

What Is A PEAR-Compatible Package?

The PEAR installer is the de facto standard tool for installing reusable components into a PHP environment. Chances are that it was installed onto your computer when PHP was installed; if not, it’s normally available as a package for your operating system of choice. One day it will be replaced by Pyrus (the next-generation PEAR installer); Pyrus supports the same packages that the PEAR installer does.

Both installers know how to download PEAR-compatible packages from websites (known as channels), how to install them, and importantly how to upgrade them when new releases become available. This makes PEAR-compatible packages a good choice when picking the format to ship your component.

The package itself is a tarball containing:

  • package.xml, a manifest file that tells the PEAR installer all about the package and its contents, and
  • your PHP code (plus any additional files) that you want the PEAR installer to install

A lot of the work that has gone into the skeleton files for the component is make it easy to create a PEAR-compatible package.

How To Make A PEAR-Compatible Package

To make a PEAR-compatible package, go into the top-level folder of your component (where the build.xml file is), and run this command:

stuart:~/Devel/sental/repustateApi$ phing pear-package

This will build a PEAR-compatible package from your source code, and put it in the dist/ folder for you.

How To Test The Package

If you want to test that the package itself is compatible with the PEAR installer, go into the top-level folder of your component, and run this command:

stuart:~/Devel/sental/repustateApi$ phing install-vendor

This will install your PEAR-compatible package into the ‘vendor/’ folder for you, alongside your component’s dependencies.

How To Install The Package Onto Your Computer

If you want to install your PEAR-compatible package into /usr/share/php on your computer, go into the top-level folder of your component, and run this command:

stuart:~/Devel/sental/repustateApi$ sudo phing install-system

The sudo command will prompt you for your password, and will then run phing as the ‘root’ user, so that it has permissions to write into /usr/share/php.

Of course, the very best way to install your PEAR-compatible package is by publishing it to your own PEAR channel, and that’s something I’ll explain in the next blog post.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

Working unit tests is only half the battle. If your unit test doesn’t cover 100% of the code, chances are you’re shipping bugs. 100% code coverage doesn’t guarantee bug-free code by any means, but it’s an important step in the right direction. There isn’t much point in shipping code that other developers cannot trust; they will just go elsewhere to get their components.

How Much Of My Code Is Covered By My Tests?

The skeleton component created by the phix php-library:init command makes it very easy for you to see how much of your code is covered by your unit tests. To do this, you need to make sure that you have Derick’s excellent xdebug extension installed. After that, just run your unit tests from the command line, and our skeleton will take care of generating the code coverage data.

stuart:~/Devel/sental/repustateApi$ phing test

This command will generate a HTML-based report in the ‘review/code-coverage’ folder:

This report shows you exactly which lines have been executed during the unit tests, and which lines of code have gone untested, making it very easy for you to see where the gaps in your testing are.

Aim For 100% Code Coverage

I’m the first to admit that this is something I’ve changed my tune over. When I was trained as a professional engineer in the 1990’s, we were taught to do 100% code coverage … and, frankly, the cost of writing all those tests seemed horrendous to me. On one project I worked on, the project manager told me that he budgeted 40% of our time for writing tests. As the dot com bubble came, and everyone rushed to compete on Internet Time (no, I didn’t believe in it then, and I definitely don’t believe in it now!), the emphasis was on shipping code with all possible haste. 100% code coverage seemed a luxury no-one could afford.

Today, with the benefit of 20/20 hindsight, I can clearly see that the costs of shipping partially-working / barely-working code are just too high. Even cobbled-together code ends up surviving for many years longer than anyone anticipated, and that just means generation after generation of programmer having to waste time maintaining the code, or spending their time instead creating and shipping their own barely-working code.

I’ve been experimenting with, and developing, this approach to components in PHP since summer 2010 (annual vacations are great for getting some hacking done!), and there’s no way I’m going to admit how many bugs I found in my own code – code I was actively using – when I went back to add 100% coverage 🙂 Suffice to say it was a lot, and more than enough to convince me of just how important 100% code coverage is to a component.

100% code coverage does not guarantee that your code is bug-free; it is not the magic target that will produce zero-defect code. But it is a good step in the right direction.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

To be a success, all components need high-quality unit tests, and this applies to the component I am building, a client for Repustate.com’s semantic analysis API. But how do you go about creating the unit tests for a remote web service without the process becoming onerous or even dangerous?

Can You Test The Quick And Nasty Way?

This is the first question that always comes to mind whenever I’m writing an API client. I don’t want to do it the classical way, of creating my own mockup of the web service, if that can be avoided. Mockups are slower to build, and they perpetuate any misunderstandings I have about the API and its behaviour. I want to test directly against the API, so that I can catch errors immediately, and have confidence that my code will work in production. Technically, these are integration tests not unit tests, and there are good arguments out there for also having the mocked up unit tests too, but I’m a pragmatic engineer, and I need to get this done before my app’s requirements change.

Now, this all comes down to whether or not the web service makes life easy for developers or not.

  • Does the web service provide a test API, where I can reset the state of my account to a known position before I start testing?

    This is the holy grail for writing tests against an API. Tests must be deterministic – same data in must always produce the same result out – to be trustworthy. Being able to use a test API, where I can control the starting conditions before I run my tests, gives me everything I need to safely test against the web service’s endpoint.

    Sadly, you’re more likely to see a unicorn than come across one of these, but never give up hope!

  • Is the API destructive in a disruptive way?
  • If I have to test against the live API, can I do so safely? Can I write tests that will not cause trouble for my production systems that are using the API?

    Often, the answer to this is ‘yes’, which is great news. Not as good as our unicorn-test-API above, but something I can work with.

  • Do I have to mock up the API locally?

    This is the testing of last resort, tbh … but sometimes you’re left with no choice on the matter.

    And, it’s worth me mentioning that API mockups are actually the best way to deal with regression tests against your own client, as they allow you to catch badly-formed requests to the remote API perfectly.

At the time of writing, I couldn’t find my unicorn-test-API for Repustate, but because their live API is entirely non-destructive, there is little risk in making my unit tests for this component work against the live API.

Never Commit Your API Key

Like many web services, Repustate’s requires you to apply for an API key, which is then used to authorise your web service requests. This allows Repustate to keep track of who is doing what, and allows them to revoke access if the web service is abused.

To run the tests against the live API, my test code is going to need to know the API key that I’ve obtained from Repustate. But if I commit that to the component’s public GitHub repo, I’m simply asking for every script kiddie to abuse that key. It’s simply not safe to commit this key. And it wouldn’t be safe if the repo was private; how do I know that one day the repo won’t be open-sourced, with the key available to find in the repo’s history?

Never, ever, ever, commit an API key to a component’s source control repo.

But my test code needs this API key. Where can it get the API key from? We could put the key in a config file that’s installed by an uber-secret component, and indeed this is a practical approach when you’re controlling the deployment of apps in the enterprise. (Just don’t make it so secret that your own devs can’t work on it. That kinda brings a lot of work to a standstill). But that won’t work for an opensourced component that hopefully others will find useful.

So we need to put the API key somewhere else, just for the tests to work.

Getting The Key From The Environment

The easiest place for the unit tests to look is in the process’s environment. First, I need to set the key, like this:

stuart:~/Devel/sental/repustateApi$ export REPUSTATE_KEY="<my API key>"

This puts the key into the environment of my terminal’s bash shell. When I run the tests from this shell, the API key will be available for my tests to use:

[code lang=”php”]
$apiKey = getenv(“REPUSTATE_KEY”);
[/code]

This is a handy tip, and it means I can now get on with the quick-and-dirty approach to unit testing my component, without worrying about giving anyone my API key to abuse.

It does cause one problem though: anyone who downloads my component and tries to run the unit tests will simply see them fail. I will mention it in the component’s README.md file, but I cannot rely on anyone actually reading that file in all honesty. For now, I’ve addressed that by testing for the REPUSTATE_KEY environment variable, and if it doesn’t exist, the unit tests die() with clear instructions rather than fail.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

A component-based approach works well with the new namespace support added to PHP 5.3, and indeed I’m making full use of this in the components I’m building for this tutorial. But not everyone is ready to move to namespaces, and when you start to consume older components inside yours, you might run into errors.

Namespaces Recapped

The whole idea behind namespaces is to make life easier for developers, by doing away with having to type incredibly long class names all the time. For example, take the ConsoleDisplayLib component I recently released. In the pre-PHP 5.3 days, I would have had to define the classes it provides like this:

[code lang=”php”]
class Phix_Project_ConsoleDisplayLib_StdOut { … }
[/code]

… and then when I wanted to use it, I would have to do this:

[code lang=”php”]
$stdout = new Phix_Project_ConsoleDisplayLib_StdOut();
[/code]

A workable system, to be sure, and one that OO PHP programmers have used for many years, but hardly RSI-friendly, I’m sure you agree. With namespaces, however, things change. The class is now defined like this:

[code lang=”php”]
class Phix_ProjectConsoleDisplayLibStdOut { … }
[/code]

Note the use of ” instead of underscores. That’s PHP’s new namespace separator, and it tells PHP that the class StdOut lives inside the Phix_ProjectConsoleDisplayLib namespace, which in turn lives inside the Phix_Project namespace. Namespaces are just another kind of scope, like local scope vs global scope. Hold that thought, because it’s these new scopes that affect our attempts to mix in non-namespaced code.

If I’m writing code that is part of ConsoleDisplayLib, to create a new StdOut object, I now only need to do this:

[code lang=”php”]
namespace Phix_ProjectConsoleDisplayLib;

$stdout = new StdOut();
[/code]

PHP automatically expands ‘StdOut’ to mean ‘Phix_ProjectConsoleDisplayLibStdOut’, because I’ve used the namespace keyword to tell PHP that this code is part of Phix_ProjectConsoleDisplayLib.

And that is where the fun begins.

Adding HTTP_Request2 To RepustateApi

I’ve made the choice to reuse the existing PEAR component HTTP_Request2. The PEAR project doesn’t currently use namespaces; all classes defined by HTTP_Request2 exist in the global scope. So if I try to use HTTP_Request2 like this inside my Repustate API client:

[code lang=”php”]
namespace GradwellRepustateApi;

$httpClient = new HTTP_Request2($url, HTTP_Request2::METHOD_POST);
[/code]

… PHP reports the fatal error: Class GradwellRepustateApiHTTP_Request2 not found.

First time you see this, you might be wondering what is going on, and how to fix it. After all, the class is called HTTP_Request2. Why is PHP trying to load a class called GradwellRepustateApiHTTP_Request2?

The answer is simple. By using the namespace keyword at the top of the file, I’ve told PHP to assume that all of the code in this file is part of the GradwellRepustateAPI scope. So, just like in my ConsoleDisplayLib example where PHP automatically expanded StdOut to be Phix_ProjectConsoleDisplayLibStdOut, PHP is going to expand HTTP_Request2 to be GradwellRepustateApiHTTP_Request2.

That isn’t what we want, but that’s PHP’s fault. We need to tell PHP that, in this case, we want it to load HTTP_Request2, and not GradwellRepustateApiHTTP_Request2.

Load From The Global Namespace

Getting PHP to load code from the global namespace, instead of from your component’s namespace, is very easy … you’ve just got to remember to do it everywhere. Simply make sure you’ve put a ” at the start of any classnames that are part of the global namespace:

[code lang=”php”]
namespace GradwellRepustateApi;

$httpClient = new HTTP_Request2($url, HTTP_Request2::METHOD_POST);
[/code]

Remember to do this, and you’ll have no trouble working with non-namespaced components inside your own components.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

Last week, I began work on a simple component to talk to the Repustate semantic analysis API. To save myself a bit of effort, I thought it would make sense to make my API client reuse PEAR’s existing HTTP_Request2 component. No sense in re-inventing the wheel, I thought. But that’s where my troubles began.

There are a few quirks in the way that the PEAR installer handles version numbers, and you need to know how to deal with them if you’re going to re-use PEAR project components in your own apps.

Adding A Dependency On HTTP_Request2

HTTP_Request2 is PEAR’s very useful wrapper around making HTTP requests from your app. At the time of writing, there are 22 PEAR packages that rely on it: a good indicator that this component is doing something right.

Making the repustateApi component rely on PEAR’s HTTP_Request2 should be as simple as adding the following to the %lt;required> section in package.xml:

<package>
  <name>HTTP_Request2</name>
  <channel>pear.php.net</channel>
  <min>2.0.0</min>
  <max>2.999.9999</max>
</package>

But, when I try to rebuild the vendor/ folder (this is the sandbox where all of the component’s dependencies are installed, so that we can run our unit tests), using the command phing build-vendor, I get an error:

[echo] Populating vendor/ with dependencies
[exec] Executing command: phix pear:register-channels 2>&1
[exec] Registering PEAR channel pear.gradwell.com
[exec] Adding Channel "pear.gradwell.com" succeeded
[exec] Discovery of channel "pear.gradwell.com" succeeded
[exec] Registering PEAR channel pear.php.net
[exec] Channel "pear.php.net" is already initialized
[exec] Executing command: pear -c /home/stuarth/Devel/sental/repustateApi/.tm
p/pear-config install --alldeps /home/stuarth/Devel/sental/repustateApi/.buil
d/package.xml 2>&1
[exec] Failed to download pear/HTTP_Request2 (version >= 2.0.0, version = 2.0.0, version <= 2.999.9999)
[exec] downloading Autoloader-2.0.1.tgz ...
[exec] Starting to download Autoloader-2.0.1.tgz (2,080 bytes)
[exec] ....done: 2,080 bytes
[exec] install ok: channel://pear.gradwell.com/Autoloader-2.0.1

So what’s going on? And what do we need to change to make this dependency work?

PEAR Version Numbers and Stability

There are two things preventing the PEAR installer from downloading the package:

  • The package’s version number is 2.0.0beta2, not plain old 2.0.0
  • The package has been marked as beta quality, rather than as a stable release.

From HTTP_Request2’s point of view, this is all perfectly reasonable. The package authors are currently transitioning from the older PHP4-based HTTP_Request, and they’re not yet ready to unleash HTTP_Request2 on the world.

As a result, the PEAR installer is (rightly) looking at the dependency information I’ve set, and telling me that HTTP_Request2 is not yet at version 2.0.0.

The PEAR installer doesn’t just use version numbers when handling dependencies. If you dig deep into package.xml, you’ll find not only a <version> tag, but also a <stability> tag. Here’s the tags from PEAR’s HTTP_Request2’s package.xml at the time of writing:

  <version>
    <release>2.0.0beta2</release>
    <api>2.0.0</api>
  </version>
  <stability>
    <release>beta</release>
    <api>beta</api>
  </stability>

How To Depend On A Beta PEAR Component

The ‘fix’ we need to make to package.xml is very simple; simply depend on the beta version:

<package>
  <name>HTTP_Request2</name>
  <channel>pear.php.net</channel>
  <min>2.0.0beta1</min>
  <max>2.999.9999</max>
</package>

With this change made, the PEAR installer does the right thing, and installs HTTP_Request2 just like I want it to 🙂

It remains to be seen what will happen when HTTP_Request-2.0.0 and beyond are released. Will the PEAR installer download it, or will I have to come back and edit the dependency in package.xml? I’ll post news on that when the time comes.

With the right dependency information in package.xml, I can now get back to cranking out the code for the repustateApi component.

Be the first to leave a comment »

Beyond Frameworks: The Page

Posted by Stuart Herbert on March 26th, 2011 in Toolbox.

I’ve put together a page on my blog to collate my Beyond Frameworks series of articles about building PHP components into one convenient place. If you’re enjoying the series, you might find it a handy reference page to bookmark.

And if you missed the beginning of the series, why not head on over and see what I’m up to? 🙂

PS: Thank you to everyone who has left comments or pinged me on Twitter so far. The feedback is excellent to have – more please 🙂

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

Earlier today, I created some very basic unit tests for my repustateApi component. Unit tests are an essential part of developing your component, but how do you run them?

Running Your Component’s Code From The Command-Line

Many old-skool developers choose to work largely from the command-line. You can happily run PHPUnit by hand from the command line yourself each time, but if you’re taking advantage of the extra data that PHPUnit can report back on, that soon gets to be a lot of typing! This is where the build.xml file in our skeleton comes in handy …

To run your unit tests from the command line, all you need to do is run the command phing test:

stuart:~/Devel/sental/repustateApi$ phing test
Buildfile: /home/stuart/Devel/sental/repustateApi/build.xml
 [property] Loading /home/stuart/Devel/sental/repustateApi/build.properties

 > lint:

  [phplint] /home/stuart/Devel/sental/repustateApi/src/php/Gradwell/Repustate
Api/Client.php: No syntax errors detected

 > run-unittests:

   [delete] Deleting directory /home/stuart/Devel/sental/repustateApi/review/
code-coverage
    [mkdir] Created dir: /home/stuart/Devel/sental/repustateApi/review/code-c
overage
    [exec] Executing command: phpunit --bootstrap=/home/stuart/Devel/sental/
repustateApi/src/tests/unit-tests/bootstrap.php --coverage-html /home/stuart/
Devel/sental/repustateApi/review/code-coverage --coverage-clover /home/stuart
/Devel/sental/repustateApi/review/logs/phpunit.xml /home/stuart/Devel/sental/
repustateApi/src/tests/unit-tests 2>&1
     [exec] PHPUnit 3.5.3 by Sebastian Bergmann.
     [exec]
     [exec] .EE
     [exec]
     [exec] Time: 0 seconds, Memory: 4.00Mb
     [exec]
     [exec] There were 2 errors:
     [exec]
     [exec] 1) GradwellRepustateApiClientTest::testCanRetrieveSentimentScor
eForTextByJson
     [exec] Exception: oh dear
     [exec]
     [exec] /home/stuart/Devel/sental/repustateApi/src/php/Gradwell/Repustate
Api/Client.php:209
     [exec] /home/stuart/Devel/sental/repustateApi/src/php/Gradwell/Repustate
Api/Client.php:151
     [exec] /home/stuart/Devel/sental/repustateApi/src/php/Gradwell/Repustate
Api/Client.php:90
     [exec] /home/stuart/Devel/sental/repustateApi/src/tests/unit-tests/php/G
radwell/RepustateApi/ClientTest.php:70
     [exec]
     [exec] 2) GradwellRepustateApiClientTest::testCanRetrieveSentimentScor
eForUrlByJson
     [exec] Exception: oh dear
     [exec]
     [exec] /home/stuart/Devel/sental/repustateApi/src/php/Gradwell/Repustate
Api/Client.php:209
     [exec] /home/stuart/Devel/sental/repustateApi/src/php/Gradwell/Repustate
Api/Client.php:151
     [exec] /home/stuart/Devel/sental/repustateApi/src/php/Gradwell/Repustate
Api/Client.php:116
     [exec] /home/stuart/Devel/sental/repustateApi/src/tests/unit-tests/php/G
radwell/RepustateApi/ClientTest.php:83
     [exec]
     [exec] FAILURES!
     [exec] Tests: 3, Assertions: 1, Errors: 2.
     [exec]
     [exec] Writing code coverage data to XML file, this may take a moment.
     [exec]
     [exec] Generating code coverage report, this may take a moment.
Execution of target "run-unittests" failed for the following reason: /home/st
uart/Devel/sental/repustateApi/build.xml:108:40: Task exited with code 2

BUILD FAILED
/home/stuart/Devel/sental/repustateApi/build.xml:108:40: Task exited with cod
e 2
Total time: 0.5951 seconds

That went bang in a spectacular way! At this stage, where we have tests but don’t yet have a working Repustate API client, that’s exactly what should happen. As I work through the code, and satisfy the tests, we should quickly get to the point where we have more tests, and that they all pass.

Here’s an example of another component – our CommandLineLib – which has many tests that all succeed, just so that you can see what a successful test run should look like:

Buildfile: /home/stuart/Devel/GWC/CommandLineLib/build.xml
 [property] Loading /home/stuart/Devel/GWC/CommandLineLib/build.properties

 > lint:

  [phplint] /home/stuart/Devel/GWC/CommandLineLib/src/php/Phix_Project/Comman
dLineLib/CommandLineParser.php: No syntax errors detected
  [phplint] /home/stuart/Devel/GWC/CommandLineLib/src/php/Phix_Project/Comman
dLineLib/ParsedSwitches.php: No syntax errors detected
  [phplint] /home/stuart/Devel/GWC/CommandLineLib/src/php/Phix_Project/Comman
dLineLib/DefinedArg.php: No syntax errors detected
  [phplint] /home/stuart/Devel/GWC/CommandLineLib/src/php/Phix_Project/Comman
dLineLib/DefinedSwitch.php: No syntax errors detected
  [phplint] /home/stuart/Devel/GWC/CommandLineLib/src/php/Phix_Project/Comman
dLineLib/DefinedSwitches.php: No syntax errors detected
  [phplint] /home/stuart/Devel/GWC/CommandLineLib/src/php/Phix_Project/Comman
dLineLib/ParsedSwitch.php: No syntax errors detected

 > run-unittests:

   [delete] Deleting directory /home/stuart/Devel/GWC/CommandLineLib/review/c
ode-coverage
    [mkdir] Created dir: /home/stuart/Devel/GWC/CommandLineLib/review/code-co
verage
     [exec] Executing command: phpunit --bootstrap=/home/stuart/Devel/GWC/Com
mandLineLib/src/tests/unit-tests/bootstrap.php --coverage-html /home/stuart/D
evel/GWC/CommandLineLib/review/code-coverage --coverage-clover /home/stuart/D
evel/GWC/CommandLineLib/review/logs/phpunit.xml /home/stuart/Devel/GWC/Comman
dLineLib/src/tests/unit-tests 2>&1
     [exec] PHPUnit 3.5.3 by Sebastian Bergmann.
     [exec]
     [exec] ............................................................ 60 /
 78
     [exec] ..................
     [exec]
     [exec] Time: 1 second, Memory: 5.75Mb
     [exec]
     [exec] OK (78 tests, 407 assertions)
     [exec]
     [exec] Writing code coverage data to XML file, this may take a moment.
     [exec]
     [exec] Generating code coverage report, this may take a moment.
     [echo]
     [echo] The code coverage report is in /home/stuart/Devel/GWC/CommandLine
Lib/review/code-coverage

 > test:

BUILD FINISHED

Total time: 3.7912 seconds

Command-Line Test Run Explained

The component’s build.xml file contains targets – sequences of instructions that you can invoke by using phing. When you run the command phing test, here’s what happens:

  • phing loads the build.xml file in the current working directory. So make sure you’re in your component’s top-level folder when you run phing!
  • build.xml sucks in the build.properties file where we set the component’s name and version number. These properties are in a separate file so that it’s safe to replace build.xml with new versions as we improve the component’s skeleton files in the future (via the phix php-library:upgrade command).
  • phing runs the ‘test’ target in build.xml, which tells it to actually run the ‘lint’ and ‘run-unittests’ targets.
  • The ‘lint’ target does a syntax check on all of your PHP files. As your component grows, and the time it takes to run your unit tests grows too, a quick syntax check can save a developer wasting a surprising amount of time.
  • If the syntax check is successful, the ‘run-unittests’ target runs next.
  • The ‘run-unittests’ target invokes PHPUnit, telling it to use the skeleton’s bootstrap file, and to write out the results in XML format to feed into other tools later on. It also tells PHPUnit to write out code coverage data as HTML. We’ll look at that in a later blog post.

Running Your Unit Tests From Netbeans

If the command-line isn’t for you, don’t worry … the component skeleton is also designed to make it very easy to run your unit tests from inside Netbeans. I’m assuming that it will be just as easy to do this from other IDEs that support PHPUnit, but I haven’t tested any myself.

First of all, you need to setup your project in Netbeans to tell it where your tests are. Open the project’s properties dialog box:

and then set the Test Folder to be your ‘unit-tests’ folder:

Next, open the PHPUnit settings in the project’s properties dialog box, and tick the ‘Use Bootstrap’ box:

and then, tell Netbeans to use the bootstrap file inside the ‘unit-tests’ folder:

so that the PHPUnit settings look like this:

Now we’re all set to run the tests from inside Netbeans. In the project browser, simply right-click on the Client.php file, and select ‘Test’ from the popup menu. Netbeans will run the tests for you, and tell you exactly where they broke:


I hope you find these tools useful, and time-saving!

I’m going to beaver away over the weekend getting several components completed, and will be back on Monday to go through more of the things you need to know if you’re going to successfully go Beyond Frameworks and shift to a component-based architecture. Have a great weekend!

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

I’ve started work on creating the components for my simple app. The first component is repustateApi, which will be a PHP client for Repustate.com’s semantic analysis API. With the component’s metadata all done, and the decision made to start with unit tests, let’s get the unit tests written and running.

The First Unit Tests

Repustate’s API is extremely simple to use, making it the ideal choice for my first semantic analysis client. It’s very low risk to knock up a client and see if their API does the job; if the API isn’t suitable under heavy testing, and I’m forced to try someone else’s semantic analysis API, I haven’t lost much time in the attempt.

As a result, my initial unit tests can be extremely simple:

[code lang=”php”]
namespace GradwellRepustateApi;

class ClientTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->_apiKey = ”;
}

public function testCanCreateClient()
{
// create the client with a valid key
$client = new Client($this->_apiKey);

// did it work?
$this->assertTrue($client instanceof Client);
}

public function testCanRetrieveSentimentScoreForTextByJson()
{
// setup
$client = new Client($this->_apiKey);
$text = “this is a happy piece of text”;

// do the test
$score = $client->callScoreForText($text, ‘json’);

// evaluate result here
$this->assertTrue ($score !== false);
}

public function testCanRetrieveSentimentScoreForUrlByJson()
{
// setup
$client = new Client($this->_apiKey);
$url = “http://www.stuartherbert.com”;

// do the test
$score = $client->callScoreForUrl($url, ‘json’);

//evaluate result here
$this->assertTrue ($score !== false);
}
}
[/code]

… and the skeleton class needed to execute those tests is just as simple:

[code lang=”php”]
namespace GradwellRepustateApi;

class Client
{
protected $apiKey = null;

public function __construct($apiKey)
{
$this->setApiKey($apiKey);
}

public function setApiKey($apiKey)
{
$this->validateApiKey($apiKey);
$this->apiKey = $apiKey;
}

public function validateApiKey($apiKey)
{
// @TODO
}

public function callScoreForText($text, $format = ‘json’)
{
// placeholder
return false;
}

public function callScoreForUrl($url, $format = ‘json’)
{
// placeholder
return false;
}
}
[/code]

Remember, at this stage, all I need to do is create unit tests that

  • can be executed, and
  • will fail

to allow me to model the API that this component will provide to the outside world. By the time I’m finished, both the unit tests and the GradwellRepustateApiClient class will look quite different 🙂

Where The Unit Tests And PHP Code Goes

In our skeleton, tests go into the src/tests/unit-tests folder, and the PHP code that the component will install into /usr/share/php does into the src/php folder.

Because we’re using a PSR0-compliant autoloader for all components, it’s extremely easy to translate the name of a class into its full filename on disk.

  • GradwellRepustateApiClient goes into the file src/php/Gradwell/RepustateApi/Client.php
  • GradwellRepustateApiClientTest goes into the file src/tests/unit-tests/Gradwell/RepustateApi/ClientTest.php

This approach means that, if needed, we can scale to hundreds of components inside a single app, and still only need the one autoloader.

The Component’s Folder Structure So Far

If I take the component structure, and dump it out using the ‘tree’ command, here’s a list of which files have gone where:

├── build.properties
├── build.xml
├── dist
│   └── repustateApi-0.1.0.tgz
├── LICENSE.txt
├── package.xml
├── README.md
├── src
│   ├── bin
│   ├── data
│   ├── php
│   │   └── Gradwell
│   │       └── RepustateApi
│   │           └── Client.php
│   ├── tests
│   │   ├── functional-tests
│   │   ├── integration-tests
│   │   └── unit-tests
│   │       ├── bin
│   │       ├── bootstrap.php
│   │       ├── php
│   │       │   └── Gradwell
│   │       │       └── RepustateApi
│   │       │           └── ClientTest.php
│   │       └── www
│   └── www
└── vendor
    └── php
        └── gwc.autoloader.php

In the next blog post later this evening, I’ll show you have to run the tests in your component, both from the command-line, and from inside Netbeans.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

In my last article, I finished editing the metadata for my component, and then used the component’s package.xml file to download its dependencies and automatically install them into the vendor/ folder – a local sandbox that we can recreate and destroy at any time.

We can now get stuck into what we all love doing the most: writing code, and that means starting with our unit tests. Why does it?

Why You Should Unit Test Your Component

There are many good reasons for ensuring your component has good unit tests:

  • Components are written to be used by many other developers. Good tests ensure that your components will behave well in the hands of others, which will save them time and enhance their trust in your future releases.
  • Good tests can serve as the best reference documentation for your code. They can show others how your code was intended to be used, in a way that they should be able to easily understand.
  • If you find yourself changing your tests in future releases, it’s a good way of making you pause and just have a think about whether you are actually breaking backwards compatibility without realising it.
  • As bugs are reported and fixed, you can add additional tests for each bug, to make sure that the bug doesn’t sneak back into any future releases (this is regression testing).
  • You can plug your unit tests into a Continuous Integration environment such as Jenkins, to make sure no-one in your team breaks your component with their next code check-in.

These are all reasons that you have probably come across before, and I’m sure you’ll come across them again before too long from many other bloggers. You can watch Sebastian Bergmann, creator of PHPUnit, talk about this at #phpuk2011 if you need further convincing. (Do watch the video, especially if you’re a World of Warcraft fan. His talk at #phpuk2011 was a big hit).

But there is another reason why components in particular need tests, which you might not have seen before, and it’s all to do with how a component is different to hacking on a webapp.

TDD: Unit Tests Come First

Components are well-suited to test-driven design (or test-driven development, if you prefer) because they are standalone little chunks of code. There’s no website for you to point your browser at to test the components by hand. The code inside your component only gets executed when someone writes some code of their own to call your code.

If you don’t write the unit tests, that means the first time your code runs will be when another developer downloads the code and tries it for himself. What do you think is likely to happen? Your code is likely to fail. Is he going to fix your code, or is he going to move on and look somewhere else for another solution?

Seeing as you need to write the tests anyway, why not embrace test-driven design, and write the tests first? Writing the tests first means that you’re already starting to define the API that other developers are going to use. It get you designing right from the very beginning with the end in mind – how your code will be reused.

In this afternoon’s blog post, I’ll show you where to put your tests, and how to run them both from the command-line and from within Netbeans.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

In the last article, I edited the build.properties file to set the component’s name and version number. I need to finish setting up the component’s metadata by editing package.xml.

Introducing package.xml

Every PEAR-compatible component needs to ship with a manifest file called package.xml. You can see the the unedited version on GitHub that we’re about to change.

package.xml contains the following useful information:

  • The component’s name, channel, version number, and description.
  • A list of the component’s authors.
  • The component’s license.
  • A list of the component’s contents.
  • A list of the component’s dependencies, including PHP version, PHP extensions, and other components.

(package.xml can hold other information too, but I’ve yet to see them being put to practical use, so we’ll leave them for today and come back to them if needed later on).

In our component skeleton, we need to add some of this data to package.xml, and the rest will be added automatically by the tools when we build a PEAR-compatible package, to save us the trouble of doing it by hand.

Setting Up The Component’s Name And Channel

All PEAR-compatible packages have a fully-qualified name of the form <channel>/<name>. In this skeleton, our tools will automatically inject project.name from the build.properties file into package.xml’s <name> tag when we build the PEAR-compatible package. We just need to edit the <channel> tag in package.xml to point to our server.

As I’m going to publish these packages via our public PEAR channel, I’ve set <channel> to be “pear.gradwell.com”. Don’t worry if you don’t have your own PEAR channel yet; they’re very easy to create, and I’ll look at exactly how to set one up and publish it later in this series.

Setting Up The Component’s Version Number, And Description

All PEAR-compatible packages have a version number. We’ve already set this in build.properties; our tools will automatically inject this into package.xml. (We could have put this directly into package.xml, but the version number is duplicated in a couple of places, and it seems much easier to let the tools deal with that so that we don’t forget to update all the version numbers when we make a new release).

For the description, edit the &lt:summary> and <description> tags. The descriptions get used in the human-friendly HTML page that each PEAR channel has, so they’re worth the trouble of filling in.

Setting Up The Component’s Author

There’s a few tags inside package.xml that tell anyone who is interested who the current author of the component is. This information gets used in the human-friendly HTML page that each PEAR channel has. I’ve set these tags as follows:

[code lang=”xml”]
Stuart Herbert
stuartherbert
stuart@stuartherbert.com
yes
[/code]

Setting Up The Component’s License

The <license> tag contains text to say under what license the component has been released. By default, the skeleton sets this to be “All rights reserved.” Whilst I’d love you to opensource all of your components, I wouldn’t like to presume 😉

For our component, I’ve set this tag to say “New BSD license.”.

Setting The List Of The Component’s Contents

The <contents> tag is where the PEAR installer expects to find a file-by-file list of all of the files that need to be installed, along with instructions on where to install them. Each file is flagged as being a specific ‘role’ – script, php code, data file, unit test, website page – and the PEAR installer then decides for you where it will put them. Don’t try fighting it; it has some built-in assumptions that aren’t worth trying to work around.

We don’t need to edit this tag at all. When we build our PEAR-compatible package later on, the tools will manage this section for us. It saves a lot of time and effort, and debugging!

Setting Up The Component’s Dependencies

Finally, we get to the bit that makes it all worthwhile: the list of what this component needs in order to work. By getting these right, we can reliably re-create the entire environment that our app needs with just a single command.

A practical demonstration is needed, I think, because this is probably something you’ve never had the opportunity to do before now.

stuart:~/Devel/sental/repustateApi: phing build-vendor

When I run that command, our tools will download all of the dependencies listed in package.xml, and install them into a folder called ‘vendor’. This gives us a reproducible sandbox, where we can find the correct versions of all the code needed to unit test our component. We don’t have to ensure the right version is installed on the computer; we get our own copy of everything needed. If you develop on shared servers, or even if you end up maintaining a lot of components, this is a real time saver.

If you run that command locally, and look inside the ‘vendor’ folder it creates, you should see that our tools have downloaded and installed the Autoloader package that’s listed in package.xml’s list of dependencies. As we add more PEAR-compatible packages to the package.xml’s dependency list, we can rebuild the vendor folder and install all of the dependencies side by side. I’ve picked the repustateApi component because it will allow me to demonstrate that as we go along.

Please ignore the errors that you will see scroll up the screen when you run ‘phing build-vendor’ at this stage. Unfortunately, the PEAR installer doesn’t seem to have a command to install just the dependencies (i.e. pear install –onlydeps) listed. It’s also trying to install our component’s PEAR-compatible package, which doesn’t exist yet.

The Final package.xml File

You can see the final package.xml file, containing all of the edits listed in this blog post, on Github.

As we work on the component and then release it, we will need to come back and edit package.xml a little more. But we’ve done what we need to, for now, and can get started on creating some code.

My apologies if it seems like a lot of work just to create an empty component and then sort out the component’s metadata. In all honesty, after you’ve done it a few times, you can create a new component in a matter of minutes, and this is work you only have to do the once.

In the next blog post, we’re going to start creating the initial tests for this component.

Be the first to leave a comment »
Page 5 of 9« First...34567...Last »

This Month

September 2017
M T W T F S S
« Jul    
 123
45678910
11121314151617
18192021222324
252627282930