Archive

Posts Tagged ‘PHP’

Using watchr with PHPUnit

December 16, 2011 Leave a comment

I’ve known about watchr and autotest for a while but have never taken the time to set them up.  I should have done this a long time ago, I noticed the efficiency gains immediately.

Initial Setup

Create a local Gemfile and install the necessary gems.

jheth@box1:~$ cd ~/project/src/test/
jheth@box1:~/project/src/test$ cat - > Gemfile << EOF
source :rubygems
gem 'watchr'
gem 'rev'  # Provides event support for Linux
EOF
jheth@box1:~/project/src/test$ bundle install --path=vendor --binstubs

This will install the watchr gem into a local vendor folder and create ~/project/src/test/bin which will contain the watchr executable script.

Configure Script

Next, configure the watchr.rb script.  You can configure any number of watches for files and/or folders.  The watch() function takes a regex with any number of captures to grab filename or parts of the path. The ‘do’ block is executed whenever a file changes. You can change the phpunit parameters to whatever you want.

~/project/src/test/watchr.rb
# Watch test files
watch("src/test/model/(.*\.php)") do |md|
   system("cd src/test/model && phpunit --debug --colors '#{md[1]}'")
end
# Watch src objects
watch("src/main/model/(.*)\.php") do |md|
   system("cd src/test/model && phpunit --debug --colors '#{md[1]}Test.php'")
end

Notice that these paths are RELATIVE, which means you must run this script from ~/project.  I had trouble with both absolute and relative (../) style paths so I just decided to run it from a higher level folder.

cd ~/project && ./src/test/bin/watchr ./src/test/watchr.rb

To see what files are being watched you can use the -l argument. This only prints the names, it doesn’t actually begin watching.

./src/test/bin/watchr -l ./src/test/watchr.rb

Fire this up in a separate terminal and let it just sit there all day while you edit your files. You will see the phpunit output everytime you save a file. I turned on –colors and –debug so I don’t have to guess when something goes wrong.

Wrap Up

This has already saved me a ton of time since I would previously switch between terminal sessions, typing or arrowing to the phpunit command I wanted to run. Now I never have to leave the editor and when saving either the test or the underlying source file, the tests get run. Decreasing the amount of time between edits and test execution is a huge time saver. I get instant feedback every time I save.

The startup command is a bit annoying to type so I added an alias to my .bash_profile.  No matter where I am, I can just pick a terminal and type ‘watchem’ and I’m up and running.

alias watchem='cd ~/project/ && ./src/test/bin/watchr ./src/test/watchr.rb'
Categories: Uncategorized Tags: , ,

Testing your PHP Code

September 19, 2011 Leave a comment

Depending on which circles you run in, hearing PHP will either make you cringe or bring you joy and comfort.   Another recently blogged on this topic and I really liked what he had to say.

Since he argued that point, I’m here to point out some of the testing libraries that are available for those of you using PHP.  You can see from the list below that PHP is gaining ground in an area many feel to be lacking.

In no particular order:

SimpleTest
Provides unit testing, basic web functional testing, and a mock API.

PHPUnit
I’ve been using PHPUnit for over 3 years now and it’s constantly improving.  It has strong community support and is backed by Sebastian Bergmann.   It provides unit testing, a mocking API, functional web testing via selenium,  database testing (DBUnit), code coverage generation utilizing xdebug, and a number of output formats easily consumable by various tools (My favorite: Jenkins).

Atoum
A pretty new framework (May 2010) that promotes ease of use. It makes heavy use of a Fluent interface for writing tests.

It delivers itself in the form of a PHAR (PHP Archive) file and is run like this:

php mageekguy.atoum.phar –testIt

Mockery
Easy to install via PEAR and integrates with PHPUnit as an alternative to the Mock API PHPUnit provides.

Phake
Not to be confused with phake, which is a rake/make equivalent for PHP, which is also what phing provides to the PHP community….

Capital P, Phake, is yet another mocking API built to overcome some of the short falls in other mock APIs.  mlively is a heavy contributor to PHPUnit’s DBUnit module and has written this module.

PHPSpec
You guessed it, Ruby has RSpec and PHP has PHPSpec.  A BDD testing style framework.  I’ll let you read more about it.

Behat
Ruby has Cucumber, PHP now has Behat.  Behat was inspired by and tries to stay true to Ruby’s Cucumber approach.  I really like the “feature file” approach at this level of testing.  How easy is it to read and collaborate on test scenarios when they’re in plain English?

Example taken from their website.

Feature: ls
  In order to see the directory structure
  As a UNIX user
  I need to be able to list the current directory's contents

  Scenario: List 2 files in a directory
    Given I am in a directory "test"
    And I have a file named "foo"
    And I have a file named "bar"
    When I run "ls"
    Then I should get:
      """
      bar
      foo
      """

These feature files are backed by “step definitions” that carry out the actions described here.  By creating a DSL (Domain Specific Language) you could have almost anyone write and execute tests.

Mink
The makers of Behat also bring us Mink,  a web functional testing tool.   Supports both headless browser (HTTP request/response) and in-browser testing for validating functionality.  It provides driver abstractions that integrate with a number of other open source software to accomplish its goal.

Categories: Uncategorized Tags: ,

Use $_REQUEST Sparingly

October 6, 2010 Leave a comment

Just tracked down an interesting bug that I thought should be mentioned.  Here’s the references so we all understand this a bit better.

$_REQUEST contains a combination of $_GET, $_POST, and $_COOKIE by default.
http://php.net/manual/en/reserved.variables.request.php

The variables_order configuration (php.ini) is what determines the content of that $_REQUEST array.
http://www.php.net/manual/en/ini.core.php#ini.variables-order

Example:
variables_order = GPC

This means that GET, POST, and COOKIE are all mashed up in the $_REQUEST array.   Each one overriding the previous key/value pairs if they exist.

Scenario:
One feature our application has is the ability to track the last selected tab on a page by storing the tab_id in a cookie.  This is only set when you visit certain tabs.   Some time later a new feature was created that also used a tab_id field.  A random bug started occurring where the tab_id for the new report was not at all correct, causing incorrect data to be saved.

Resolution:
Turns out the cookie data was to blame.  This bug only showed up if you had visited one of the tabs that saved the tab_id to your cookie.    The javascript for the new report was explicitly posting the data but the controller was receiving the wrong value, because it was using $_REQUEST.   Since cookie values override post values the controller was seeing the tab_id from the cookie ($_COOKIE) instead of the $_POST value we really wanted.

You should be using the most restrictive superglobal possible, in this case POST should have been used instead of REQUEST.

Categories: Uncategorized Tags:

Duplicate Code is Evil

September 21, 2010 Leave a comment

I’m hoping no one here disagrees with the FACT that duplicate code is evil.  Nothing good can come from it.  You’ve heard “Money is the root of all evil” but in software I say “Duplication is the root of all evil.”  I have never agreed with the copy and paste programming style that I have come to witness many times. You should literally feel sick whenever you copy/paste a block of code.  Now I don’t mind if you’re copying a block of similar logic that you’re going to change 90% of but I do care if you’re going to copy/paste an entire block and leave it in its entirety or just change some variable names.

If you ever have the need to copy/paste the first thing you should think is “I should be able to cut and paste instead.”  IMO, the easiest method of refactoring is extract method. (Yes, there are real names for refactoring approaches.)  Re-use the logic instead of duplicating it.  Make a new method in the same class or move the method into a common object that others can share.

I’ve heard a couple times that “copy/paste is faster than refactoring” and in that split second that you’re pasting that block it probably is (I argue that cut/paste takes no more time).  The problem is that someone (maybe you) now has to maintain this code and have to update those now duplicate blocks and either keep perpetuating the lie or eventually clean it up the way it should have always been.  This will take them/you way more than a couple seconds and now you’re wasting time because you took the “easy way” out.

Why Duplication is Bad

  • More code means more places for bugs to hide.
    • If your original code has a bug in it, now all your copies do too.
  • More code to maintain
    • Why should I have to update more than one place with the same change?
  • More code to test
    • We still need to test the duplicate logic right?
  • More to sift through, which slows down future work.
    • You’re going to make me sit and read the same code block again and again?
    • Why are there duplicate blocks here?
    • Are they REALLY duplicated? Now I have to compare letter by letter to see if these 20 lines are really the same.
  • Direct violation of the DRY principle.  Don’t Repeat Yourself.

One way we combat duplicate code at Sentry is by analyzing our code during every build.  We use PHPCPD (CPD = Copy Paste Detection) to statically analyze our PHP code to make sure we’re not introducing duplication.  PHPCPD generates a report that Hudson is happy to display and tell us where our faults are.

I can view any job/build and click into the “Duplicate Code” section.  It allows me to navigate through the warnings and see the exact source code that has been identified as duplicate.  You can’t make it any easier than that.

Categories: Uncategorized Tags:

Use a Hash Map instead

August 10, 2010 Leave a comment

I learned a valuable lesson just before coming to Sentry that I’ve shared with my co-workers and thought I’d share here at well.

If you find yourself searching through an array try to turn it into a hash/map instead.

Instead of an O(N) operation (looking at every element in an array), you can often turn it into a direct access hash map O(1).  Remember Big-O notation? Make sure you keep that in your hip pocket.  You never know who may ask about it (Amazon and Google will).

You rarely write your own search function since most languages provide one for you.  The PHP function in_array($needle, $haystack)) is your O(N) search and will only get worse as the size of the array gets bigger.  It’s tempting to throw that in whenever needed.

Here’s a quick PHP snippet that I recently worked through with another developer.

// $worksheet_names is still an array, but we
// use the index/key of the array instead of the value.
$worksheet_names = array();

foreach ($results as $row) {
     ...
     // instead of in_array, we look directly at the index.
     // previously in_array($name, $worksheet_names)
     while (isset($worksheet_names[$name])) {
         $name = substr($name,0,24) . "($duplicate_sheet_counter)";
         $duplicate_sheet_counter += 1;
     }
     $row['worksheet_name'] = $name;
     // previously $worksheet_names[] = $name;
     $worksheet_names[$name] = true;
}
Other Uses
Another helpful trick is to keep track of duplicate values in an array.  What’s the easiest way to get the number of occurrences for all these values?
<?php

$a = array (1, 2, 3, 3, 1, 4, 5, 3, 4);

$map = array();
foreach  ($a as $entry) {
     if (!isset($map[$entry])) {
          $map[$entry] = 1;
     } else {
          $map[$entry]++;
     }
}

print_r($map);
Array
(
    [1] => 2
    [2] => 1
    [3] => 3
    [4] => 2
    [5] => 1
)
Categories: Uncategorized Tags: