Testgetriebene Entwicklung im Kohana PHP Framework

Innerhalb einer MVC-Architektur können Models sehr gut testgetrieben entwickelt werden, indem für jede Modelfunktion parallel eine Testfunktion geschrieben wird.

Eine gute Übersicht zur Vorgehenweise liefert Frank Westphal in seinem Blog:

“Wir schreiben dabei Tests, noch bevor wir den zu testenden Programmcode schreiben.

Idealerweise wird jede funktionale Programmänderung zuvor durch das Schreiben eines weiteren Tests motiviert. Wir entwerfen diesen Test so, dass er zunächst fehlschlägt, weil das Programm die gewünschte Funktionalität noch nicht besitzt. Erst anschließend schreiben wir den Code, der den Test zum Laufen bringt.

Sie fragen sich vielleicht, was wir denn testen sollen, wenn wir noch überhaupt keinen Code geschrieben haben? Doch diese Frage lässt sich umdrehen. Woher wissen wir denn, was wir programmieren sollen, wenn wir noch nicht wissen, was denn überhaupt erforderlich ist?

Zuerst die Tests zu schreiben, ist eine Möglichkeit, um herauszufinden, was wir programmieren müssen und was nicht, und wie wir auch sicherstellen können, dass wir tatsächlich programmieren werden, was wir programmieren wollten.

Analysieren Sie dazu, wie die erforderliche Klasse funktionieren und sich verhalten sollte. Dokumentieren Sie dann Ihr Verständnis in einem ausführbaren Test. Stellen Sie sich dabei vor, der zu testende Code wäre einfach schon realisiert. Entwerfen Sie die Tests aus der Verwendungsperspektive, so, wie Sie sich die Schnittstelle der zu testenden Klasse wünschen, und verdrängen Sie die Gedanken an die Implementierung für einen kurzen Moment.”

Weitere Links zum Thema:

In PHP wird als Testumgebung üblicherweise PHPUnit eingesetzt. Das Paket ist unter phpunit.de verfügbar.

Für das von uns vorzugsweise eingesetzte PHP FrameworkKohana” gibt es ein Unittest-Modul, das PHPUnit als Basis nutzt. Neben dem Kohana-Unittest-Modul haben wir auch ein Fixture-Modul eingebunden. Dies gestattet das automatische Laden einer Datenbank mit Testdaten. Die Testdaten müssen im YAML-Format vorliegen:

user:
  0:
    id:		1
    company_id: 1
    salutation:	Herr
    lastname:	Wüstemann
    firstname:	Axel
    language:   de
    email:	awu@qbus.de
    password:	xTZh78:GhJz
company:
  0:
    id:		1
    company:	qbus | websolutions
    company_code: QBWS
    group:	intern
    is_owner:	1
project:
  0:
     id:	1
     leader_id: 4
     company_id: 1
     company_code: QBWS
     project_key: 09-001
     group:  development
     title: qbProjects
     description: Projektmanagementsoftware
     start_on: 1261132926
     due_on: 1261142926
     budget: 1000.0
     external_costs: 0.0
     status: 4
     created_by: 1
     created_on: 1261132926
project_user:
  0:
     project_id:  1
     user_id:     1
...

Dazu gibt es in der Datenbankkonfiguration einen zweiten Datenbankzugang test. Die Idee ist, dass es eine automatische Umschaltung zwischen Test- und Arbeits-Datenbank gibt. Damit die Umschaltung funktioniert, gibt es in application/config/database.php einen Konfigurationsparameter database_used.

'database_used' => 'test',

Dieser Parameter wird jedem unserer Jelly-Models mitgegeben:

class Model_Auth_Row_User extends Sitechips_Model_Jelly_Row_Abstract
{
    public static function initialize(Jelly_Meta $meta)
    {
        $meta->table('usr_user');
        $meta->db(Kohana::config('database.database_used'));
        ...
     }
}

Die Test-Scripte müssen unter application/tests/core oder unter modules|plugins/tests/core abgelegt werden, die Testdaten unter application/tests/fixtures/xxx.yaml oder unter modules|plugins/tests/fixtures/zzz.yaml.

Ein Test-Script hat den Aufbau:

/**
 * @group   sitechips
 * @author  awu@qbus.de
 */
class UnitTest_Auth extends Kohana_Unittest_Testcase
{
 
    protected function setUp()
    {
        $db = Database::instance(Kohana::config('unittest.db_connection'));
 
        // load fixtures for test
        $fixture = new Fixture($db, MODPATH . 'sitechips/tests/fixtures');
        $fixture->load('auth.yaml');
 
        // set a valid language
         i18n::lang('de');
    }
 
    protected function tearDown()
    {
        // empty the  whole database after the tests
        $db = Database::instance(Kohana::config('unittest.db_connection'));
        $tables = $db->query(Database::SELECT, 'SHOW TABLES', FALSE);
        foreach($tables as $table)
        {
            $table = $table[key($table)];
            $db->query(0, "TRUNCATE TABLE {$table}", FALSE);
        }
    }
 
    public function test_construct()
    {
        $user = new Model_User(1);
 
        $this->assertThat($user, $this->isInstanceOf('Model_User'));
        $this->assertThat($user->row, $this->isInstanceOf('Model_Row_User'));
        $this->assertEquals(1, $user->getId());
    }
 
    public function test_login()
    {
 
    ....

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *