Our friends Ed Finkler and Chris Hartjes recently had a chat about testing in PHP. Read on to get the low down on different testing tools and their relative merits--check it out as Ed and Chris weep for the future, come to some interest...
Our friends Ed Finkler and Chris Hartjes recently had a chat about testing in PHP. Read on to get the low down on different testing tools and their relative merits--check it out as Ed and Chris weep for the future, come to some interesting conclusions and get their hands dirty so you don't have to.
Ed and Chris had a little chat about testing in PHP.
Chris: Okay, so today's topic is PHP testing
Ed: Word up
Chris: Now, Ed, I know that for the most part you are not a big fan of the mainstream PHP testing tools
Ed: Yes, that's true
Chris: So what is it that you don't like about them
Ed: I guess realistically my complaints are aimed at PHPUnit . It's very powerful and very complete from what I can tell, but I think it's difficult to pick up and I think that difficulty makes people less likely to use it. Because it's by far the best known testing tool, I think that tends to limit the use of unit testing, period, in PHP. That's not necessarily PHPUnit's fault per se. I just think it's the situation we're in. I think the documentation, the setup, and just obtaining PHPUnit is a challenge, particularly when compared to unit testing options I've seen in other languages. Python, for example, has a simple but effective unit testing library built into the core.
Chris: So, when you say "difficult to pick up", is it because tests look like this?
db = $db;
}
/**
* Turns label values like codingStandardsSuck into
* CODING_STANDARDS_SUCK
*/
public function screamingSnakeLabels()
{
$results = $db->query("SELECT name FROM labels");
$labels = array();
foreach ($results as $result) {
$labels[] = $this->_camelToScreamingSnake($result);
}
return $labels;
}
/**
* Method that takes a camelCase string into SCREAMING_SNAKE_CASE
*
* @param string $value
*/
protected function _camelToScreamingSnake($value)
{
$result = preg_replace_callback(
'/[A-Z]/',
function ($match) {
return "_" . strtolower($match[0]);
},
$value
);
return strtoupper($result);
}
}
class DevhellTest extends PHPUnit_Framework_TestCase
{
public function testShowEdHow()
{
$db = $this->getMockBuilder('Foo')
->disableOriginalConstructor()
->setMethods(array('query'))
->getMock();
$db->expects($this->once())
->method('query')
->will($this->returnValue(array('devHell', 'camelCase'));
$label = new Label($db);
$expectedResults = array('DEV_HELL', 'CAMEL_CASE');
$testResults = $label->screamingSnakeLabels();
$this->assertEquals(
$expectedResults,
$testResults,
"Labels were not correctly coverted to screaming snake case"
);
}
}
Chris: Maybe it's because I've worked with it a lot, all I see is some boilerplate and then a few statements that seem pretty intuitive to me.
Ed: I think boilerplate is part of the issue. I think that's intimidating. Tools can mitigate that to some extent, but I don't think it eliminates the problem entirely. I just don't think writing a simple test should be anything more than a couple lines of code. Then you can build upon that iteratively as you need. I think that approach of starting simply and building up your set of tests really helps you understand what's going on, and I think it makes testing a lot more accessible to people who haven't done it before. A lot of testing framework docs I see throw a ton of nomenclature out at the reader. I think if you don't already understand that nomenclature, you won't understand what's up.
Chris: So when you say 'nomenclature', you're talking about things like what exactly? Assertions and mocks?
Ed: Knowing how to mock that stuff up is pretty complex. In my experience the majority of people w