A couple of tricks you might not know about. Held at an internal developer show'n'tell in October 2010 at SilverStripe Ltd. in Wellington, New Zealand. Video available at http://vimeo.com/16446690
5. MORE EXPRESSIVE ASSERTIONS
$members = DataObject::get('Member');
$this->assertContains('test@test.com',$members->column('Email'));
$member = DataObject::get_one('Member', '"Email" = 'test@test.com'');
$this->assertType('Member', $member);
Using assertType()
Using DataObjectSet->column()
Wednesday, 17 November 2010
6. PHPUNIT EXECUTABLE INSTEAD OF SAKE
New feature since 2.4.3, backported to 2.3.9 as well
More features than proxying through “sake” CLI tool
Code coverage generation in “XML Clover” format
(which can be parsed by phpUnderControl and other tools)
Wednesday, 17 November 2010
7. PHPUNIT EXECUTABLE INSTEAD OF SAKE
With “sake”
phpunit .
phpunit sapphire
phpunit sapphire/tests/DataObjectTest.php
phpunit --coverage-html assets/
sake dev/tests/all
sake dev/tests/modules/sapphire
sake dev/tests/DataObjectTest
sake dev/tests/coverage
With “phpunit”
Wednesday, 17 November 2010
8. PHPUNIT: RUN ALLTESTS IN A FOLDER
phpunit --verbose sapphire/tests/security
PHPUnit 3.5.3 by Sebastian Bergmann.
sapphire/tests/security
BasicAuthTest
....
GroupTest
...
Time: 9 seconds, Memory: 83.50Mb
OK (72 tests, 286 assertions)
More granular control over which tests are run
Filepath autocompletion built-in on CLI
Wednesday, 17 November 2010
9. PHPUNIT: RUN ONLY ONETEST METHOD
Less hacky than commenting out other tests
Supports regular expressions
phpunit --filter testDelete sapphire/tests/DataObjectTest.php
PHPUnit 3.5.3 by Sebastian Bergmann.
.
Time: 1 second, Memory: 64.75Mb
Wednesday, 17 November 2010
10. FASTERTESTSTHROUGH SQLITE3
Up to 10x faster test execution¹ means
“Test Driven Development” (TDD) is fun again!Thanks Andreas :)
phpunit mysite/tests '' db=sqlite3
...
Time: 2:44 seconds, Memory: 113.75Mb
phpunit mysite/tests
...
Time: 22:56, Memory: 116.75Mb
PostgreSQL Sqlite3
¹ Internal project on SilverStripe 2.4.2, with 97 tests and 410 assertions.
Postgresql and SQLite3 modules both on trunk.
Wednesday, 17 November 2010
11. FASTERTESTSTHROUGH SQLITE3
Needs the sqlite3 module in your project
http://silverstripe.org/sqlite-database/
Simple modification in mysite/_config.php
require_once('conf/ConfigureFromEnv.php');
// ...
if(Director::isDev() && @$_REQUEST['db'] == 'sqlite3') {
$databaseConfig['type'] = 'SQLite3Database';
}
Not a complete replacement to running tests on the
actual database driver, but most of the time implementations are the same.
Wednesday, 17 November 2010
12. DEBUGGING A FIXTURE
YAML fixtures are more concise than SQL inserts
Problem: You have to run queries and joins in your head
Wednesday, 17 November 2010
13. DEBUGGING A FIXTURE
For more complex data models, looking at SQL can be easier
SilverStripe lets you load aYAML fixture into a temporary database
through http://localhost/dev/tests/startsession
Wednesday, 17 November 2010
14. SEPARATE INTEGRATION AND UNITTESTS
A UnitTest (SapphireTest class) covers an isolated aspect of a class,
e.g. one method call.
An IntegrationTest (FunctionalTest class) tests the sum of its parts,
in SilverStripe mostly HTTP requests and their HTML responses.
Wednesday, 17 November 2010
15. SEPARATE INTEGRATION AND UNITTESTS
Unit and IntegrationTests complement each other,
both are necessary and have different intentions.
Good practice: Separate tests into different folders.
Example: mysite/tests/unit and mysite/tests/integration
Idea: Run coverage reports separately for unit and integration tests
Wednesday, 17 November 2010
16. WRITE QUALITYTESTS
Lack of test coverage points to problems,
but high coverage doesn’t automatically mean quality code
class HomepageTest extends FunctionalTest {
function testResponse() {
$response = $this->get('home');
$this->assertNotNull($response->getBody());
$this->assertEquals($response->getStatusCode(200));
}
}
Probably gives you 80% code coverage for a Homepage class,
but failures don’t tell you anything useful.
Bad example:
Wednesday, 17 November 2010
17. WRITE QUALITYTESTS
High code coverage is the side effect of writing quality tests,
not a goal in itself.
Recommendation:
Strive for high unit test coverage,
and highlevel “smoke tests” through integration tests
Wednesday, 17 November 2010
18. WRITE FLEXIBLE INTEGRATIONTESTS
<div class="sidebar">
<ul>
<li class="news-item">
<a href="mylink">My first news</a>
</li>
<!-- ... -->
</ul>
</div>
class HomepageTest extends FunctionalTest {
function testSidebarShowsLatestNews() {
$response = $this->get('home');
$newsEls = $response->cssParser()->getBySelector('.sidebar .news-item');
$this->assertEquals(3, count($newsEls), 'Shows three items');
$news1LinkEls = $newsEls[0]->xpath('.//a'); // relative xpath
$this->assertEquals(
'My first news',
(string)$news1LinkEls[0],
'News item link contains correct title'
);
}
}
Wednesday, 17 November 2010
19. WRITE FLEXIBLE INTEGRATIONTESTS
Learn XPath (or use a CSS to XPath converter)
Learn SimpleXML (built-in with PHP5)
Make few assumptions about template markup
Make assertions less brittle by using semantic markup
Wednesday, 17 November 2010
20. LINKS
Unit testing in SilverStripe
http://doc.silverstripe.org/testing-guide
Usage of “phpunit” executable in SilverStripe
http://goo.gl/D23KJ
Book:“Test Driven Development: By Example” (Kent Beck)
Wednesday, 17 November 2010