PHPUnit + runkit: now friendly together

To fake out resources when unittesting, you can now [1] use the runkit PHP extension, which adds some more dynamism to PHP, you get to:

  • add methods,
  • redefine classes runtime,
  • or run code in safe sandboxes

PHP heroine Sara Golemon created runkit, enabling this madness. (See her PECL user page for more of her Open Source contributions.)

My use-case for runkit+Unit Testing is Class Posing. [2]

When you deal with several layers of code, and you have no sensing in underlying layers, you feel the need to redefine that expensive database call, network access, or whatever’s cramping your unittesting style.

Fake resources using runkit ninja powers

Example test-case:

function testCallDbBadlyShouldComplain() {
    // This function body pacifies new DbQuery($cmd)
    $body = "return array();";
    runkit_method_redefine( 'DbQuery', '__construct', '$cmd', $body);
    $ret = db_exec_command('foo', 'baz');
    $this->assertEquals( array('alert'=>'Unknown DB command foo'), $ret);
}

(Sorry for “hamburger example”, not real code.) For details, see runkit_method_redefine‘s manual page.

Uh, OK, that’s it, I think. I’ll try to be more PHPUnit-bloggy, as we go along. I like that tool.

Weak-ass disclaimer: In other situations, Dependency Injection, or some other dependency-breaking technique, chould be used. This case is for getting any coverage on legacy code. Think of it as just another technique, for your exotic toolchest.

[1] Why now? My ticket at PHPUnit‘s Trac got fixed, and is set to be released rather soon, in version 3.2.7. Sebastian Bergmann, main PHPUnit hacker, works hard, releases very often. So, either run trunk, or fix the little problem yourself, OR wait until next release.

[2]: About Class Posing: It was Sebastian Bergmann‘s idea to use it with PHPUnit. (He has a specialized chunk of C code sitting around on his desk, customized to extend PHP with Class Posing, but he has not [yet] gotten it into PECL, the extension repository.)

Ruby’s gem and require explained with IRC wisdom

My Ruby rusts on the shelf. OK, here goes the evn, explainer:

[08:28] evn: did you know ruby 1.9 has an autoloading thing
[08:28] evn: its kind of odd
[08:28] evn: its like a lazy require
[08:28] evn: you have to set it up
[08:28] evn: but it doesnt happen until the constant gets referenced
[08:28] evn: seems like a source of subtle bugs to me
[08:28] evn: since loading some random ass module
              can be full of side effects
[08:29] olleolleolle: autoloading, huh.
[08:29] olleolleolle: I never get the new-style "gem" inclusion to work.
[08:29] olleolleolle: require_gem still works though.
[08:29] evn: thats cause 'gem' doesn't require
[08:29] evn: it just locks the version
[08:30] evn: you have to do
[08:30] evn: gem 'bob', '>= 3'
[08:30] evn: require 'bob
[08:30] evn: i think its weird too
[08:30] evn: require_gem used to do both didnt it?
[08:30] olleolleolle: In my limited mind, that should be a
              param hash to require_gem.
[08:30] evn: overloading require is just bad in general
[08:31] evn: so much badness

Blogged with Flock

Tags: , , , ,