Friday, October 19, 2012

Testing shell methods with PHPUnit

Testing is fun. Testing global functions isn't, especially when those global functions use pass-by-reference parameters.

I write a lot of command line applications with PHP and I often must deal with exec, shell_exec, and passthru. This causes major headaches when I need to simulate a behavior for the purposes of testing.

In Bart, we have a class named Shell, which wraps many of the global shell and system functions of the PHP language. It's also a great place to collect any methods that don't come out of the Box with PHP. Combining the Shell class with Diesel  lets me mock or stub out pretty much all of my interactions with the shell. There's one catch though: PHPUnit doesn't work with mocking methods that have pass-by-reference parameters. Both exec and passthru return information back to the caller via this approach.

Enter the MockShell class. MockShell is a small stub class exposing an exec and passthru method. It also exposes two other methods to configure the commands expected by either of these methods for the duration of a unit test. Finally, it provides a verify() method to be called upon completion of a test run to verify that its expectations were met.

MockShell takes a mocked Shell class instance as a parameter. Any method calls sent to the MockShell that it doesn't understand are passed along the mocked MockShell. This utility of this is to allow you to provide only one stubbed object when you configure Diesel for the test. See below,

function testSymlinksCreated()
 $phpuShell = $this->getMock('Bart\Shell');
  ->with('~/code/nagios/logs', 0777, false);

 // Create the MockShell and supply it the mocked Shell instance
 // that any calls to methods _other_ than exec and passthru
 // ...may be passed on to that mock.
 $shell = new \Bart\Stub\MockShell($this, $phpuShell);
  ->expectExec("cd ~/code/nagios && ln -s /etc/nagios config", array(), 0, null)
  ->expectExec("cd /www && ln -s ~/code/nagios nagios", array(), 0, null);

 $this->registerDiesel('Bart\Shell', $shell);

 // Configure a generator for the nagios app
 $g = new Generator('nagios');
 // Expect that this creates the "logs" directory
 // ...and creates the two symlinks above

 // Verify that the two execs were called
 // PHPUnit will verify the call to mkdir()

Check out all the Bart code at,

Saturday, September 29, 2012

Dan Pink on Creativity and Motivation

A friend recently shared Dan Pink's talk on Creativity and Motivation with me. Pink discusses the progression of the 20th century 1st world workforce from a majority of simple task oriented workers to a majority of cognitive, right brained knowledge workers in our modern day. He then proposes that this new workforce is motivated not by the same monetary goals as yesterday, but rather by more fulfilling incentives, which he lists as autonomy, mastery, and purpose.

I wholeheartedly agree that the leading thought workers of today are ultimately attracted to these higher causes of self-fulfillment. Yet, I differ from his purportedly absolute stance that motivating by these three factors and removing monetary reward from the picture is a recipe for success.

Pink provides two extended examples,

  1. Atlassian Fedex day. Fedex day at Atlassian is essentially a 24 hour period during which engineers are encouraged to develop whatever code they want, specifically nothing on which they're currently working. Eventually, this has graduated into a 20% autonomy policy.
  2. Microsoft Encarta versus Wikipedia. Encarta was a multi-year project out of Microsoft, costing them large amounts of money and diligent coordination. Wikipedia promised no money to any contributor nor did it set any schedule for content.
In the case of Atlassian, his claim is that the engineers produce higher quality work faster during autonomous time because they are working for themselves. I agree that this has a lot of merit, but I disagree that this measurement alone can prove his point. In a typical development environment, engineers report to product managers. Product managers set the specifications and timelines. Typically, the communication between the engineer and the product manager is poor and this poor communication leads to bugs, missed deadlines, and subpar products. Much has been written on this subject (see Agile, XP, Scrum, Kanban). While this isn't the only difference between autonomous and required development, it does provide reasonable justification to question the percentage that autonomy plays in the success of Fedex days.

Next, Encarta versus Wikipedia. Again, I agree that there is much more incentive to contribute to wikipedia as an individual versus a requirement to work on Encarta as an employee. However, I attribute to that discrepancy very little influence in the eventual failure of Encarta. Three other factors played a very large role in the outcome of the Encarta / Wikipedia showdown,
  1. It happened right around when the internet was becoming ubiquitous.
  2. Wikipedia is a SaaS model: available anywhere; always up to date; social. Contrast that against Encarta which was available only on your machine, valid only at the time of install, and did not provide a straightforward way to share information with everyone.
  3. Wikipedia is free (See Chris Anderson, Freemium).
Ultimately I'm not opposed to his proposal; I'm just not convinced by his two examples.

My feeling is that material gain must still be taken into account. For example, consider a job that pays $200,000 versus a job paying only $40,000 that promised full autonomy in choosing projects and deadlines: very few engineers will choose the latter. At 200,000 against 160,000, you'd potentially have a strong case.

My conclusion is that autonomy, mastery, and purpose drive higher quality innovation, but that the level at which those drivers operate is variable. Furthermore, this debate needs more unassailable data points.

Tuesday, September 4, 2012

Bash Functions in Scope

Bash 4 is a lovely collection of globally shared state and scope. Variables and functions are declared, defined, and often redefined in many places and in a hopefully predictable order.

Here is my goto list of commands to help narrow down the field when I'm trying to debug things,

  • which is a quick way to find out where a command resides -- if it does at all
    • Using the -a option, you can see all of the places where the command could be defined
    • By default, functions and aliases are not searched by which. However, the manual documentation for which suggests you set which to the following, 
    • (alias; declare -f) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $@
  • type is a big step above which and will tell you more in depth information about the command
  • env with no arguments, this lists the global variables in scope
  • declare on its own will list every variable and function defined. It can give you a little more information about functions than the methods above.
    • Use the -f option to see the definition of the function
    • Use the -F option to show only the name and attributes.
    • To see where a function is defined (file and line number), you have to enable the extdebug shell option. This is probably my favorite!
      • shopt -s extdebug && declare -F $yourFunctionName

Sunday, July 29, 2012

PHP Dependency Injection, Part 2





  * Create an instance of class
  * @param string $className Name of the class
  * @param array $arguments Any arguments needed by the class
 public static function create()

  * Get singleton instance of this class
  * @param type $className
  * @return $className Singleton instance of class
 public static function singleton($className)




Monday, July 23, 2012

PHP Quality Metrics with Jenkins


See, and there's even a book!




Comments welcome!

Saturday, July 7, 2012

Keep It Simple, Stupid








Thursday, February 9, 2012

Introducting Diesel - PHP Dependency Injection









class Stop_The_Line {
  // The constructor param at the end
    // Use the default static dependencies?

    // Use Diesel to produce an instance of a Jenkins Job
      'w' => $w,

  public static function dieselify($me)



class Stop_The_Line_Test extends Bart_Base_Test_Case {
  public function testStopTheLine() {
    $job_name = 'the build';

    $di = new Diesel();


    // ...and it's Git instance

    // 1. Jenkins build failed,
    // 2. Commit message did not contain {buildfix}


    // Use PHPUnit to create a stub job
    // And set it up to say the last build failed

    // Now register this stub job for ONLY this Diesel instance
    $phpu = $this;
            'Jenkins job name did not match');

            'Expected host to match conf');

        return $mock_job;

  private function configureGit(Diesel $di) {

    // Let's see what happens when it doesn't

      function($params) use($mock_git) {
       return $mock_git;



Thursday, February 2, 2012

Encode AVI for iPad (for Free)

I wanted to convert an old movie of mine to m4v so that I could watch it on my iPad. I was unable to import it into my iTunes since the format didn't match, so I had to convert it to a format that makes iTunes happy -- namely mpeg4.

Since I didn't want to pay for Handbrake (and they don't have a default iPad format), I decided to just do it myself using ffmpeg.

I am on a mac, so I needed to install ffmpeg. The easiest way to do that was to use homebrew. My first attempt to install failed because home brew had some issues.  As it ended up, I had to uninstall home brew and uninstall mac ports (don't forget sudo rm /usr/local/bin/{brew,port})! I went through some drama with my Ruby installation (1.8.7), since home brew wasn't loading, which involved using rvm to install 1.9.3, then 1.9.2, and then back to my system install, which suddenly started working again with the brew install script.

Next: brew install ffmpeg. This got me *all* the required dependencies for ffmpeg in one go! Awesome.

Next, the encoding line:

ffmpeg -i myMovieFile.avi -acodec libfaac -ac 2 -ab 160k -s 1024x768 -vcodec libx264 -vpre iPod640 -b 1200k -f mp4 -threads 0 myMovieFile.ipad.aac

which I adapted from,

Wednesday, February 1, 2012

Testing Scalatra with Immutable Specs2

import org.specs2.Specification
import org.specs2.mock.Mockito
import org.scalatra.test.ScalatraTests
import org.eclipse.jetty.testing.ServletTester
import org.specs2.specification.After

class MySpec extends Specification { def is = 
  "My spec must" ^
  "verify that scalatra can be tested" ! Specs().assert()

   * Create a new jetty context each time
   * This lets us mock expectations *per* specification
  case class Specs() extends After with ScalatraTests with Mockito {
    // The servlet tester gives an http context to your tests
    lazy val tester = new ServletTester

    val myMock = mock[MyObject]

    // Register your servlet with the context and inject the mock
    addServlet(new MyServlet(myMock), "/*")

    // don't leave the jetty context hanging around
    def after { tester.stop() }

    // Pay special attention to the "this" keyword, which will provide the
    // ...method in a scope such that "after" may be called for teardown
    def assert() = this {
      // Just some expectation on the mock object
      myMock.get(0) returns true

      get("/") {
        there was one(myMock).get(0)

Sunday, January 29, 2012

Puppet: Multiple Classes & Inheritance




Friday, January 13, 2012

Specs2 Mockito - Invoke Injected Callback




      // The signature of the zookeeper watch function

      // create system under test, which will call watchNode internally
      new SUT(zkMock)


      // Now, call the callback method

      SUT.someValue must_== "some updated value"

Thursday, January 12, 2012

Specs2: IndexOutOfBoundsException: 30

I was consistently seeing a java.lang.IndexOutOfBoundsException: 30 exception today while working on some code. I had written a spec with a single use case, which was marked as pending because I couldn't test my trait until I flushed out another piece of code upon which it depended.

I'd seen the error in the past, but couldn't remember how (of it) it went away. Since I was working on a pretty much skeleton spec, I figured now would be a good time to get to the bottom of it.

Well, it was pretty simple! In connecting my use case text description to the actual test, I was using a "^" instead of an "!", which also explains the other oddity I was seeing (that I had thought related to pending tests) "No source file found at src/test/scala/...", since the "^" was expecting a String as the result of my test method being run, not a Specs result. Go DSLs!

def is =
"My trait should" ^
"do what I want" ^ SpecsStub().assert() // WRONG, ^ should be !

case class SpecsStub() {
  def assert() = {