Added PHPUnit unit testing framework

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@40129 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Sam Minnee 2007-08-15 06:38:41 +00:00
parent 9b1487c376
commit f55e0bf547
7 changed files with 229 additions and 20 deletions

View File

@ -119,11 +119,11 @@ class DatabaseAdmin extends Controller {
* Updates the database schema, creating tables & fields as necessary.
*
* @param boolean $quiet Don't show messages
* @param boolean $populate Populate the database, as well as setting up its schema
*/
function doBuild($quiet = false) {
function doBuild($quiet = false, $populate = true) {
$conn = DB::getConn();
Profiler::mark('doBuild');
if($quiet) {
DB::quiet();
} else {
@ -158,30 +158,28 @@ class DatabaseAdmin extends Controller {
if(!$quiet) {
echo "<li>$dataClass";
}
Profiler::mark("requireTable $dataClass");
singleton($dataClass)->requireTable();
Profiler::unmark("requireTable $dataClass");
}
}
$conn->endSchemaUpdate();
ManifestBuilder::update_db_tables();
if($populate) {
if(!$quiet) {
echo '<p><b>Creating database records</b></p>';
}
if(!$quiet) {
echo '<p><b>Creating database records</b></p>';
}
foreach($dataClasses as $dataClass) {
// Test_ indicates that it's the data class is part of testing system
foreach($dataClasses as $dataClass) {
// Test_ indicates that it's the data class is part of testing system
if(strpos($dataClass,'Test_') === false) {
if(!$quiet) {
echo "<li>$dataClass";
}
if(strpos($dataClass,'Test_') === false) {
if(!$quiet) {
echo "<li>$dataClass";
singleton($dataClass)->requireDefaultRecords();
}
Profiler::mark("requireDefaultRecords $dataClass");
singleton($dataClass)->requireDefaultRecords();
Profiler::unmark("requireDefaultRecords $dataClass");
}
}
@ -190,7 +188,6 @@ class DatabaseAdmin extends Controller {
if(isset($_REQUEST['from_installer'])) {
echo "OK";
}
Profiler::unmark('doBuild');
}

View File

@ -21,7 +21,7 @@ class ErrorPage extends Page {
*/
function requireDefaultRecords() {
parent::requireDefaultRecords();
if(!DataObject::get_one("ErrorPage", "ErrorCode = '404'")) {
$errorpage = new ErrorPage();
$errorpage->ErrorCode = 404;

View File

@ -398,14 +398,12 @@ class SiteTree extends DataObject {
if($this->class == 'SiteTree') {
if(!DataObject::get_one("SiteTree", "URLSegment = 'home'")) {
$homepage = new Page();
echo 'Running with the homepage: ' . $homepage->ID;
$homepage->Title = "Home";
$homepage->Content = "<p>Welcome to SilverStripe! This is the default homepage. You can edit this page by opening <a href=\"admin/\">the CMS</a>.</p>";
$homepage->URLSegment = "home";
$homepage->Status = "Published";
$homepage->write();
echo 'Created the homepage: ' . $homepage->ID;
$homepage->publish("Stage", "Live");
$homepage->flushCache();

127
tests/SapphireTest.php Normal file
View File

@ -0,0 +1,127 @@
<?php
/*
$dir = dirname(dirname((__FILE__)));
$_SERVER['SCRIPT_FILENAME'] = "$dir/main.php";
chdir($dir);
require_once 'core/Core.php';
require_once("core/ManifestBuilder.php");
require_once("core/ClassInfo.php");
require_once('core/Object.php');
require_once('core/control/Director.php');
require_once('filesystem/Filesystem.php');
require_once("core/Session.php");
$envFiles = array('../_ss_environment.php', '../../_ss_environment.php', '../../../_ss_environment.php');
foreach($envFiles as $envFile) {
if(@file_exists($envFile)) {
include($envFile);
break;
}
}
require_once(MANIFEST_FILE);
print_r($_CLASS_MANIFEST);
if(ManifestBuilder::staleManifest()) ManifestBuilder::compileManifest();
require_once(MANIFEST_FILE);
*/
require_once 'PHPUnit/Framework.php';
/**
* Test case class for the Sapphire framework.
* Sapphire unit testing is based on PHPUnit, but provides a number of hooks into our data model that make it easier to work with.
*/
class SapphireTest extends PHPUnit_Framework_TestCase {
function setUp() {
// Create a temporary database
$dbConn = DB::getConn();
while(!$dbname || $dbConn->databaseExists($dbname)) {
$dbname = 'tmpdb' . rand(1000000,9999999);
}
$dbConn->selectDatabase($dbname);
// This code is a bit misplaced; we want some way of the whole session being reinitialised...
Versioned::reading_stage(null);
$dbConn->createDatabase();
singleton('DataObject')->flushCache();
$dbadmin = new DatabaseAdmin();
$dbadmin->doBuild(true, false);
// Load the fixture into the database
$className = get_class($this);
$fixtureFile = eval("return {$className}::\$fixture_file;");
$this->loadFixture($fixtureFile);
}
/**
* Array of
*/
protected $fixtureDictionary;
/**
* Get the ID of an object from the fixture.
* @param $className The data class, as specified in your fixture file. Parent classes won't work
* @param $identifier The identifier string, as provided in your fixture file
*/
protected function idFromFixture($className, $identifier) {
return $this->fixtureDictionary["$className.$identifier"];
}
/**
* Get an object from the fixture.
* @param $className The data class, as specified in your fixture file. Parent classes won't work
* @param $identifier The identifier string, as provided in your fixture file
*/
protected function objFromFixture($className, $identifier) {
return DataObject::get_by_id($className, $this->idFromFixture($className, $identifier));
}
/**
* Load a YAML fixture file into the database.
* Once loaded, you can use idFromFixture() and objFromFixture() to get items from the fixture
* @param $fixtureFile The location of the .yml fixture file, relative to the site base dir
*/
function loadFixture($fixtureFile) {
$parser = new Spyc();
$fixtureContent = $parser->load(Director::baseFolder().'/'.$fixtureFile);
$this->fixtureDictionary = array();
foreach($fixtureContent as $dataClass => $items) {
foreach($items as $identifier => $fields) {
$obj = new $dataClass();
foreach($fields as $fieldName => $fieldVal) {
// Parse a dictionary reference - used to set foreign keys
if(substr($fieldVal,0,2) == '=>') {
$obj->$fieldName = $this->fixtureDicationary[ substr($fieldVal,2) ];
// Regular field value setting
} else {
$obj->$fieldName = $fieldVal;
}
}
$obj->write();
// Populate the dictionary with the ID
$this->fixtureDictionary[$dataClass.'.'.$identifier] = $obj->ID;
}
}
}
function tearDown() {
// Delete our temporary database
$dbConn = DB::getConn();
if(substr($dbConn->currentDatabase(),0,5) == 'tmpdb') {
// echo "Deleted temp database " . $dbConn->currentDatabase() . "\n";
$dbConn->dropDatabase();
}
}
}
?>

30
tests/SiteTreeTest.php Normal file
View File

@ -0,0 +1,30 @@
<?php
class SiteTreeTest extends SapphireTest {
static $fixture_file = 'sapphire/tests/SiteTreeTest.yml';
/**
* Test generation of the URLSegment values.
* - Turns things into lowercase-hyphen-format
* - Generates from Title by default, unless URLSegment is explicitly set
* - Resolves duplicates by appending a number
*/
function testURLGeneration() {
$expectedURLs = array(
'home' => 'home',
'staff' => 'my-staff',
'about' => 'about-us',
'staffduplicate' => 'my-staff-2',
'product1' => '1-1-test-product',
'product2' => 'another-product',
'product3' => 'another-product-2',
'product4' => 'another-product-3',
);
foreach($expectedURLs as $fixture => $urlSegment) {
$obj = $this->objFromFixture('Page', $fixture);
$this->assertEquals($urlSegment, $obj->URLSegment);
}
}
}

30
tests/SiteTreeTest.yml Normal file
View File

@ -0,0 +1,30 @@
Page:
home:
Title: Home
about:
Title: About Us
staff:
Title: Staff
URLSegment: my-staff
Parent: =>Page.about
staffduplicate:
Title: Staff
URLSegment: my-staff
Parent: =>Page.about
products:
Title: Products
product1:
Title: 1.1 Test Product
product2:
Title: Another Product
product3:
Title: Another Product
product4:
Title: Another Product
contact:
Title: Contact Us
ErrorPage:
404:
Title: Page not Found
ErrorCode: 404

27
tests/TestRunner.php Normal file
View File

@ -0,0 +1,27 @@
<?php
require_once 'PHPUnit/Framework.php';
require_once 'PHPUnit/TextUI/TestRunner.php';
/**
* Controller that executes PHPUnit tests
*/
class TestRunner extends Controller {
function index() {
ManifestBuilder::includeEverything();
$tests = ClassInfo::subclassesFor('SapphireTest');
array_shift($tests);
echo "<h1>Sapphire PHPUnit Test Runner</h1>";
echo "<p>Discovered the following subclasses of SapphireTest for testing: " . implode(", ", $tests) . "</p>";
echo "<pre>";
$suite = new PHPUnit_Framework_TestSuite();
foreach($tests as $test) {
$suite->addTest(new PHPUnit_Framework_TestSuite($test));
}
PHPUnit_TextUI_TestRunner::run($suite);
}
}