test.ical.ly | getting PHP by the balls

Feb/10

8

Bootstrap Besonderheiten für Unit Tests von symfony Plugins

Während der letzten Wochen habe ich mich ausführlich mit dem Testen von symfony Anwendungen beschäftigt. Ich habe mit lime herumgespielt und mit PHPUnit, wobei ich mich für letzteres als mein Testframework entschieden habe. Mir sind dabei ein paar Sachen aufgefallen, mit denen ich mich hier näher auseinandersetzen möchte.

Wenn man ein neues Plugin anlegt, werden bereits ein paar Verzeichnisse und Strukturen angelegt. Die symfony Entwickler werden sich sicher einiges dabei gedacht haben. Jedoch haben sie es augenscheinlich versäumt, ihre Gedanken ausführlich zu dokumentieren, weswegen ich mich an die Mailingliste gewandt habe und parallel dazu werde ich versuchen, direkt aus dem Generierten schlauer zu werden. :)

Wenn wir mittels $ symfony generate:plugin myPlugin ein neues Plugin anlegen erhalten wir folgende Struktur:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
   .
   |-config
   |-lib
   |-test
   |---bin
   |---bootstrap
   |---fixtures
   |-----project
   |-------apps
   |---------frontend
   |-----------config
   |-----------i18n
   |-----------lib
   |-----------modules
   |-----------templates
   |-------cache
   |-------config
   |-------data
   |---------fixtures
   |-------lib
   |---------form
   |-------log
   |-------plugins
   |-------test
   |---------bootstrap
   |---------functional
   |---------unit
   |-------web
   |---------css
   |---------images
   |---------js
   |---------uploads
   |-----------assets
   |---functional
   |---unit

Was hier auffallen sollte ist, dass unterhalb test/fixtures/project die Struktur eines kompletten symfony Projektes liegt. Nur: warum?

Eine ebenfalls generierte Datei kann uns vielleicht einen gewissen Aufschluss geben:

myPlugin/test/bootstrap/unit.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
 
if (!isset($_SERVER['SYMFONY']))
{
  throw new RuntimeException('Could not find symfony core libraries.');
}
 
require_once $_SERVER['SYMFONY'].'/autoload/sfCoreAutoload.class.php';
sfCoreAutoload::register();
 
$configuration = new sfProjectConfiguration(dirname(__FILE__).'/../fixtures/project');
require_once $configuration->getSymfonyLibDir().'/vendor/lime/lime.php';
 
function myTestPlugin_autoload_again($class)
{
  $autoload = sfSimpleAutoload::getInstance();
  $autoload->reload();
  return $autoload->autoload($class);
}
spl_autoload_register('myTestPlugin_autoload_again');
 
if (file_exists($config = dirname(__FILE__).'/../../config/myTestPluginConfiguration.class.php'))
{
  require_once $config;
  $plugin_configuration = new myTestPluginConfiguration($configuration, dirname(__FILE__).'/../..', 'myTestPlugin');
}
else
{
  $plugin_configuration = new sfPluginConfigurationGeneric($configuration, dirname(__FILE__).'/../..', 'myTestPlugin');
}

Diese Datei wird von allen (lime) Unit Tests inkludiert, um für eine Standard Laufzeitumgebung zu sorgen.

Zwei Dinge sind interessant.

  1. Es wird davon ausgegangen, dass die Variable $_SERVER['SYMFONY'] gesetzt ist.
  2. Die aktuelle sfProjectConfiguration wird aus dem “Fixture Projekt” geladen.

Die $_SERVER['SYMFONY'] Variable ist soweit ich weiss immer gesetzt, wenn symfony via PEAR installiert worden ist. Das ist aber wohl bei den meisten symfony Projekten nicht der Fall, jedenfalls nicht in meinen.

Als kleine Abhilfe kann hier folgendes Kommando auf der Shell dienen:

$ export SYMFONY="/absoluter/pfad/zu/deinem/projekt/lib/vendor/symfony/lib"

Aber das war nicht die eigentliche Besonderheit. Worum es eigentlich geht ist diese Zeile:

11
$configuration = new sfProjectConfiguration(dirname(__FILE__).'/../fixtures/project');

Statt also die Konfiguration des Projektes zu laden, in welchem unser Plugin eingebunden ist, wird die des Fixture Projektes gelesen. Aber was für Vorteile kann das bringen?

Nun zum einen werden so sämtliche verbliebenen Abhängigkeiten zum wirklichen Projekt beseitigt. Dies ist ohnehin nötig, da die Unit Tests in unserem Plugin unabhängig vom Projekt funktionieren müssen.

Eine dieser Abhängigkeiten ist, die zur Datenbank Konfiguration. Statt darauf zu bauen, dass der Entwickler, der unser Plugin verwenden will auch gleich ein Test Environment für uns anlegt, können wir innerhalb des Plugins konfigurieren, was wir zum Testen benötigen. Am einfachsten ist da sicherlich eine SQLite Datenbank, die wir ebenfalls im Fixture Porjekt ablegen können.

Eine weitere Abhängigkeit ist, dass unser Plugin im Projekt enabled sein muss und die Tests connected. Auch das können wir im Fixture Projekt kontrollieren.

Bis auf die Abhängigkeit zu symfony selbst können wir tatsächlich alles innerhalb des Plugins kapseln. Theoretisch könnten wir sogar symfony in das Fixture Projekt packen, aber das würde unseren Plugin Code wirklich unnötig aufblähen. Ausserdem können wir symfony vorraussetzen, schliesslich ist unser Plugin ein symfony Plugin und wird ohne eh nicht laufen.

Sinn und Zweck des Fixture Projektes ist es also, eine Testbarkeit mit minimalen Abhängigkeiten herzustellen. Einzig symfony muss vorhanden sein und es muss bekannt sein, wo es liegt ($_SERVER['SYMFONY']).

Wie das Ganze mit meinen PHPUnit Tests der letzten Woche aussieht, werde ich in den nächsten Tagen zeigen.

RSS Feed

2 Comments for Bootstrap Besonderheiten für Unit Tests von symfony Plugins

• Bootstrap Besonderheiten für Unit Tests von symfony Plugins – Teil 2 | test.ical.ly | 9. February 2010 at 04:54

[...] ein paar mehr Gedanken gemacht zum Bootstrapping von symfony Plugin Unit Tests. Gestern habe ich ja bereits gezeigt, welche Struktur symfony generiert und welche Dateien dabei angelegt werden. Auf meine Frage auf [...]

Symfony - fixtures/project | ausgebloggt.de | 26. April 2010 at 15:24

[...] wird gleich eine ganze Symfony-Projekt-Struktur angelegt. Meine Vermutung, dass es mit der Testbarkeit des Plugins zusammenhängt, hat dann dieser sehr gute Artikel bestätigt. [...]

Leave a comment!

<<

>>

Find it!

Theme Design by devolux.org