Lime is a testing tool bundled with
symfony. It can be, however, used separately with any PHP application.
It is a great alternative for famous
PHPUnit. Its advantage is simplicity. Since writing tests with lime is dead easy it’s a perfect choice for unit testing newbies.
Simplicity
What makes lime so powerful is that almost no effort is needed to create a new test. You just open a new file, initialize
lime_test object and you’re ready to start writing your tests.
include dirname(__FILE__) .
‘/../bootstrap/unit.php’;
$test = new lime_test(3, new lime_output_color());
$test->diag(‘::stripText()’);
$text = gyText::stripText(‘Lorem Lipsum’);
$test->isa_ok($text, ‘string’, ‘::stripText() returns a string’);
$test->cmp_ok($text, ‘===’, ‘lorem-lipsum’, ‘::stripText() replaces spaces with dash’);
$text = gyText::stripText(‘Gdańsk’);
$test->cmp_ok($text, ‘===’, ‘gdansk’, ‘::stripText() handles diacritic characters’);
Note: file included in the first line initializes symfony related libraries (like autoloader). If you want to use lime without symfony you should replace this line with simple require statements. You’ll need to include lime and other classes used in test.
Reigning the Chaos
Lime approach is simple and quick to start with. Unfortunately, it becomes hard to maintain in big projects.
As the number of tests grows test files become complicated and unclear. Splitting them into several smaller files isn’t a big improvement. Besides, too often helper functions are needed to make tests more readable and avoid code repetition.
Object oriented approach solves the problem in a better way.
class gyTextTest extends gyLimeTest
{
public function testStripTextReturnsString()
{
$test = gyText::stripText(‘Lorem Lipsum’);
$this->isa_ok($test, ‘string’, ‘::stripText() returns a string’);
$test->cmp_ok($text, ‘===’, ‘lorem-lipsum’, ‘::stripText() replaces spaces with a dash’);
}
public function testStripTextHandlesDiactricCharacters()
{
$text = gyText::stripText(‘Gdańsk’);
$test->cmp_ok($text, ‘===’, ‘gdansk’, ‘::stripText() handles diacritic characters’);
}
}
$test = new gyTextTest(3);
$test->run();
What I did was group tests as methods of a test class. Adding new test is as simple as creating a new method. Test cases are clearly separated and I gain power of object orientation.
Note:
Lime 2, the next generation of Lime, will be far more sophisticated. Out of the box it’ll let you use neat annotations or test classes. For good introduction to Lime 2 read
Best Practice Testing with Lime 2 by
Bernhard Schussek.
The Magic
Every public method which name starts with ‘
test‘ is considered to be a test and is called by a
run() method. You can see the full implementation on the next listing.
class gyLimeTest extends lime_test
{
public function __construct($plan = null, $outputInstance = null)
{
$outputInstance =
is_null($outputInstance) ?
new lime_output_color
() :
$outputInstance;
parent::__construct($plan, $outputInstance);
}
public function run()
{
foreach ($this->getTestMethods() as $method)
{
$test = $method->getName();
$message = sfInflector::humanize(sfInflector::underscore($test));
$this->diag($message);
$this->setUp();
$this->$test();
$this->tearDown();
}
}
protected function getTestMethods()
{
$reflection = new ReflectionClass($this);
$methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method)
{
&& 0 == $method->getNumberOfParameters())
{
$testMethods[] = $method;
}
}
return $testMethods;
}
public function setUp()
{
}
public function tearDown()
{
}
}
Separation
Every test should be run in a clean and separate environment. That’s why before each test
setUp() is called. Most often I use it to load test data into the database. Respectively after each test
tearDown() should clean things up.
Handy initialization
Common initializations can be done in a constructor. Additional feature is added here. Since I’m annoyed by having to pass
lime_output_color instance all the time to get results in color I made it a default behavior.
Good tests are the documentation
Giving descriptive and meaningful test method names is important for the reader. It helps to figure out what’s the purpose of a test case and catch the requirements. To support practice of appropriate naming a diagnostic message is created from the method name and printed out before each test.
Hierarchy
The
gyLimeTest class is a base test class in most of my projects. As it’s part of my test plugin I cannot put project specific methods there. What I usualy do is I introduce additional project test class. This way I can put common project methods and assertions in one place.

Tagged as:
lime,
PHP,
Symfony,
TDD,
tests
Pingback: uberVU - social comments
Pingback: Tweets that mention Getting More From The Lime Testing Framework | Goyello blog -- Topsy.com