Howto eStudy

Aus THM-Wiki
Wechseln zu: Navigation, Suche
Important.png
Die Seite wird überarbeitet oder erweitert.
Important.png

Der folgende Artikel soll allen, die eStudy weiterentwickeln, einen Überblick über das Projekt verschaffen. Dazu haben wir eine Art "eStudy Guidelines" zusammengestellt, indem wir vorhandene Artikel aktualisiert, ergänzt und – strukturiert in zwei Leitartikeln – verlinkt haben.

Der erste Leitartikel ist dieser und beschreibt die Schritte, um eine eStudy-Entwicklungsumgebung zu installieren und nach eigenen Wünschen anzupassen.

Der zweite Leitartikel fasst Artikel zusammen, die bei der eigentlichen Entwicklung hilfreich sind.

Was benötige ich?

Jeder Entwickler braucht eine lokale lauffähige Installation. Diese kann man sich entweder selber einrichten (empfohlen) oder man verwendet die vorkonfigurierte eStudy Entwicklungsumgebung für VirtualBox. Es gibt auch die Möglichkeit, sich eine eigene eStudy Live-CD zu erstellen.

Entwicklungsumgebung

Wir empfehlen entweder Eclipse PDT oder Zend Studio. Letzteres gibt es in einer kostenfreien Testversion, die 30 Tage im vollen Funktionsumfang nutzbar ist. Außerdem besitzt Zend Studio bereits das Subversion-Plugin Subversive. Dieses muss bei Eclipse PDT erst noch installiert werden. Beide IDE's basieren auf Eclipse und bieten zahlreiche nützliche Plugins.

Für das eStudy-Projekt in Zend Studio müssen folgende Einstellungen gesetzt werden:

Rechtsklick auf das Projekt und "Properties" anklicken:

  1. Resource
    • Text file encoding: UTF-8
    • New text file line delimiter: Unix
  2. Code Style > Formatter
    • Enable project specific settings
    • Datei estudy-conventions.xml aus dem Ordner /trunk/doku des eStudy SVN importieren und auswählen
  3. PHP Interpreter
    • Enable project specific settings
    • PHP Version: PHP 5.3
  4. Save Actions
    • Enable project specific settings
    • Remove trailing whitespace
    • Ignore empty lines

Die gleichen Einstellungen gelten auch für Eclipse PDT. Dort steht der "Formatter" jedoch nicht zur Verfügung.

LAMP-Umgebung

eStudy benötigt einen Webserver mit PHP-Unterstützung und ein Datenbankmanagementsystem (DBMS) zum Verwalten der Datenbank. Da sehr viele Webanwendungen diese Kombination mit Linux als Betriebsystem, Apache als Webserver, MySQL als DBMS und PHP als Skriptsprache nutzen, hat sich dafür das oft genutzte Kürzel LAMP gebildet.

XAMPP

Aufgrund der häufigen LAMP-Kombination gibt es diese als Komplettpaket XAMPP für diverse Plattformen, um eine Installation zu vereinfachen.

Bei der Entwicklung empfiehlt es sich, dass so viele Fehler wie möglich angezeigt werden. Dazu muss in der Datei php.ini von XAMPP der Wert von error_reporting geändert werden: error_reporting = E_ALL | E_STRICT.

Die von XAMPP mitgelieferten PEAR-Pakete sind in der Regel veraltet und müssen aktualisiert werden. Dafür müssen in der Konsole folgende Befehle eingetippt werden:

pear update-channels
pear upgrade

Neben der regulären XAMPP-Installation empfiehlt es sich, das zugehörige Entwicklungspaket zu installieren. Dies ist zum Beispiel notwendig, um Xdebug zu aktivieren.

Installation aus Linux-Paketquellen

Wer unter Linux entwicklen möchte, kann natürlich auch die dort angebotenen Paketquellen nutzen. Hier empfielt es sich zunächst einmal PHP, den Apache-Webserver, MySQL oder MariaDB (Fork von MySQL 5.1 der zu MySQL kompatibel ist) zu installieren.

Je nachdem, welche Distribution verwendet wird, kommen hier verscheidene Paketmanager zum Einsatz. Es empfielt sich, zunächst nach den benötigten Paketen zu suchen. Als Beispiel hierzu der Apache-Webserver:

  • aptitude search apache2 bei debianbasierten Systemen wie Debian, (K)Ubuntu u.ä.
  • yum search apache2 bei Fedora und openSUSE
  • zypper search apache2 bei openSUSE

Installiert werden die Pakete jeweils mit dem Befehl install anstelle von search, gefolgt vom gefundenen Paketnamen.

Wurden alle benötigten Pakete installiert, kann unter Linux der Webserver, und mit ihm auch PHP, mit dem Befehl: /etc/init.d/apache2 start gestartet werden. Um den MySQL/MariaDB-Datenbankserver zu starten, muss der Befehl: /etc/init.d/mysql start ausgeführt werden. Beide Befehle müssen, wie auch die Installation von Paketen, mit Administratorrechten ausgeführt werden. Um den Web- oder Datenbankserver wieder zu stoppen, wird anstelle von start ein stop, für einen Neustart ein restart benötigt.

SCM-Account

eStudy ist freie Software und kann somit von jedem Interessierten herruntergeladen werden. Wer jedoch an dem Projekt aktiv mitwirken möchte, benötigt einen Clone des Git-Repositories von eStudy. Dieses wird mit dem verteilten Versionsverwaltungssystem (engl.: Source-Code-Management, SCM) Git verwaltet. Die Quellen von eStudy können über das Projektmanagementsystem Gitorious und den Bugtracker Redmine eingesehen werden. Über Gitorious ist es ebenfalls möglich als Benutzer mit einem TH-Account einen privaten Clone des eStudy-Quellcodes anzulegen, an ihm Veränderungen vorzunehmen und diese, mit Hilfe eines Mergerequests, in die aktuelle Entwicklung einfließen zu lassen. Beide vorgestellten Systeme (Gitorious und Redmine) benötigen eine Anmeldung mit dem TH-Account, wie er auch für den Empfang von E-Mails benötigt wird. Sollte es Probleme mit den Systemen geben, so erhält man vom Helpdesk Hilfe.

Weiteres

Nach dem Checkout von eStudy befindet sich im Wurzelordner die Datei install.txt [1]. Diese enthält alle noch nötigen Schritte, um eStudy installieren zu können. Hier sind auch noch einmal alle PHP-Erweiterungen aufgelistet, die bei einer Installation aus Linux-Paketquellen installiert sein müssen.

Vorgaben

Konventionen

Wer eigenen Code beisteuern möchte, der muss sich an die Projektkonventionen halten. Dazu zählen die Programmiervorgaben. Diese Vorgaben werden bei einem Commit automatisch überprüft. Verstößt der Code gegen die Richtlinien, wird der gesamte Commit abgewiesen und die Mängel müssen behoben werden.

Vor dem Start in die Entwicklung empfiehlt sich der Blick auf den Artikel Getting Started. Hier werden alle wichtigen Informationen an einer zentralen Stelle verlinkt. Damit sollten die wichtigsten Fragen zur Projektorganisation beantwortet sein.

Softwarequalität

Möchte man sich nicht als Software Developer, sondern als Software Professional bezeichnen, so achte man auf die Qualität seines Codes. Dazu zählt vor allen Dingen das Erstellen von Tests vor dem Entwickeln des eigentlichen Programmcodes. eStudy fordert alle Entwickler dazu auf, ihre Module mit Testfällen abzusichern.

Ein Modul folgt immer dieser Ordnerstruktur:

  • modulname/
    • classes/
      • Klassen und Pakete nach eigener Definition
    • tests/
      • Tests zu allen Klassen, folgt der Struktur von classes
    • PHP-Dateien, mit denen das Modul aufgerufen wird

Die Testfälle werden also innerhalb der Module organisiert und sollen außerdem zu Test-Suites zusammengefasst werden.

eStudy-Tests

Für die Entwicklung der Testfälle ist es wichtig, in zumindest den folgenden beiden Kategorien zu denken: Unit Tests und Datenbanktests. Daher sollte ein Modul seine Test-Suites auch in diese beiden Typen aufteilen. eStudy selbst besitzt drei Kategorien von Test-Suites: Neben den zwei schon genannten gibt es zusätzlich eine Suite für Security-Tests. Alle drei Test-Suites befinden sich im Wurzelordner im Verzeichnis unit-tests. Die eigenen zusammengefassten Testklassen müssen eigenhändig in die passenden Suites eingetragen werden, damit sie auch von allen Entwicklern ausgeführt werden.

AllTests.php

In dieser Datei werden alle klassischen Unit Tests der Module zusammengefasst. Diese Tests dürfen keinerlei Datenbankzugriffe oder sonstige Ein- und Ausgabe tätigen.

AllDBTests.php

In dieser Suite befinden sich alle Tests, die Zugriff auf die Datenbank benötigen. Damit diese Tests durchlaufen, muss der Datenbankserver aktiviert sein.

AllSecurityTests.php

Hier werden alle Test-Suites zusammengefasst, welche zur Überprüfung der Sicherheit der Module erstellt wurden. Auch diese Tests sollen nach Möglichkeit reine Unit Tests sein.

Tests ausführen

Die Tests führt man am Besten über Ant aus. Im Wurzelverzeichnis von eStudy befindet sich dafür die Datei build.xml. Des Weiteren gibt es die Datei build.properties.dist. Auch diese Datei kann wieder kopiert und unter dem Namen build.properties gespeichert werden. Darin müssen die Zugriffsdaten der Datenbank hinterlegt werden. Hierbei handelt es sich jedoch nicht um die Zugangsdaten für den eStudy-Benutzer, sondern es muss sich um einen Benutzer handeln, der MySQL-Benutzer und Datenbanken erstellen darf. Bei einer XAMPP-Standardinstallation ist dies der Benutzer "root" ohne Passwort, so ist es auch in der Datei build.properties.dist hinterlegt. Seine persönlichen Buildproperties kann man auch im eigenen Benutzer-Verzeichnis (z.B. /Users/<MeinName> unter Mac OS) speichern. Hier muss der Name allerdings eStudy.build.properties lauten.

Ein einfaches

$ ant

im Wurzelverzeichnis von eStudy reicht zum Aufruf der Tests. Es wird eine neue config.inc.php erstellt, die alte (falls vorhanden) wird umbenannt. Diese neue Konfigurationsdatei bleibt während des gesamten Testlaufs bestehen. Im Anschluss wird sie wieder gelöscht und die ürsprüngliche Konfiguration wiederhergestellt.

Eigene Suites erstellen

Eine Suite-Klasse sieht folgendermaßen aus:

class MyModuleAllTests {
  public static function suite() {
    $suite = new PHPUnit_Framework_TestSuite('All MyModule tests');
    	
    $suite->addTest(AnotherTestSuiteOfMyModule::suite());
    $suite->addTestSuite("MyTestClass");
    
    return $suite;
  }
}

Das Beispiel zeigt die Test-Suite "MyModuleAllTests". Zu ihr gehört eine weitere Test-Suite namens "AnotherTestSuiteOfMyModule". Außerdem gehört zu ihr die einzelne Testklasse "MyTestClass". Zu beachten ist also, dass die Terminologie umgedreht ist: Weitere Test-Suites fügt man über die Methode addTest(..) hinzu, einzelne Testklassen mit der Methode addTestSuite(..).

Testfälle entwickeln

Hier beschränken wir uns auf die Beschreibung von Datenbanktests, da das Erstellen von reinen Unit Tests mit PHPUnit ausreichend im Internet dokumentiert ist. Um einen solchen Datenbanktest für eStudy zu entwickeln, leitet man seine Testklasse von der von eStudy bereitgestellten Klasse AbstractEStudyDatabaseTest ab. Sie befindet sich im Wurzelverzeichnis unter unit-tests/database/.

Diese Klasse bietet die Möglichkeit, das für den Test benötigte Datenbankschema zu importieren. Dies sollte man in der Methode beforeClass() erledigen. Beispiel:

public function beforeClass() {
  $this->loadSchema(__DIR__ . "/../news.sql");
}

Verwendet man eine eigene setUp()- und/oder tearDown()-Methode, so muss man in jedem Fall darin die Oberklasse aufrufen über parent::setUp() bzw. parent::tearDown().

Die Testklasse muss die Methode getDataSet() implementieren. Diese Methode dient zur Initialisierung der Datenbank vor jedem einzelnen Testfall. Der Rückgabewert der Methode muss vom Typ PHPUnit_Extensions_Database_DataSet_IDataSet sein. Typischerweise verwendet man hierfür die Methoden createFlatXMLDataSet bzw. createXMLDataSet, welche als Parameter den Pfad zu einem Dataset erwarten.

Datasets sind XML-Dateien, welche den Inhalt der Datenbank simulieren. Sie können dazu verwendet werden, Inhalte in die Datenbank zu schreiben (z.B. vor einem Test) oder um den Inhalt der Datenbank mit den erwarteten Werten im Dataset zu vergleichen (z.B. als Test-Assertion). Eine genauere Beschreibung findet sich in der Dokumentation von PHPUnit.

Die Datasets gehören in den speziellen Ordner datasets, welcher im Testordner und auf der gleichen Ebene wie die Testklasse liegt. Beispiel:

  • web/
    • news/
      • classes/
      • tests/
        • datasets/
          • seed.xml
        • Testklasse.php

Typischerweise initialisiert man seinen Datenbanktest mit leeren Tabellen. Die in dem Beispiel gezeigte Datei seed.xml ist daher am Einfachsten ein flaches Dataset. Die oben genannte Methode getDataSet() würde also mit folgendem Code implementiert werden:

return $this->createFlatXMLDataSet(dirname(__FILE__) . "/datasets/seed.xml");

In PHP 5.3 kann statt dirname(__FILE__) auch direkt __DIR__ verwendet werden. Benötigt man für seinen Test die Methode getDataSet() nicht, so kann man ein leeres Dataset zurückliefern. Dazu kann man folgende Implementierung verwenden:

return $this->createEmptyDataSet();

Möchte man innerhalb eines Testfalls ein Dataset in die Datenbank laden, kann man die Methode insertIntoDatabase verwenden. Diese erwartet als Parameter einen Pfad zu einem Dataset, genau wie die zuvor vorgestellten Methoden create(Flat)XMLDataSet. Zu beachten ist, dass evtl. vorhandene Datenbankinhalte vor dem Einfügen in die entsprechenden Tabellen entfernt werden. Das Dataset darf diesmal auch kein flaches XML-Dataset sein.

Die gleiche Einschränkung bzgl. der Datasets gilt auch für die Methode assertTableEquals: Hier ist der erste Parameter der Pfad zu einem XML-Dataset (das erwartete Ergebnis), der zweite Parameter ist der Name der Tabelle in der Datenbank (das tatsächliche Ergebnis), mit der das Dataset verglichen werden soll.

Der letzte Baustein für einen Test ist die Verbindung zur eStudy-Datenbank. Diese Verbindung steht ebenfalls innerhalb der Testklasse zur Verfügung, und zwar mit dem privaten Feld $db. Die grundsätzliche Idee ist, dass eine Datenbankklasse die Verbindung zur Datenbank über ihren Konstruktor zugewiesen bekommt. Die Klasse sollte also nicht global $db; verwenden, um auf die Datenbank zuzugreifen.

Sollte man doch global $db; verwenden (wovon wir noch einmal abraten möchten), wird PHPUnit diese globale Variable, nachdem die Testklasse ausgeführt wurde, zurücksetzen. Alle weiteren Datenbanktestklassen werden somit nicht mehr funktionieren! Damit dies nicht geschieht, müssen folgende Annotationen überhalb der Datenbanktestklasse geschrieben werden:

/**
* @backupGlobals disabled
* @backupStaticAttributes disabled
*/
class MeineDatenbankTestKlasse extends AbstractEStudyDatabaseTest {
[..]

Des Weiteren gibt es einen Ersatz für die Data-Klasse, welche den Namen DummyData trägt und die toMysql-Methode überschreibt. Die ursprüngliche Methode benötigt eine bestehende Verbindung zur Datenbank. Dies ist möglicherweise nicht gewünscht und für von der Datenbank unabhängige Testfälle kann man daher die Klasse DummyData verwenden. Vorraussetzung ist, dass die Data-Klasse nicht über statische Aufrufe verwendet wird (siehe dazu auch Static Methods are Death to Testability).

Wir möchten diesen Abschnitt mit einem Beispiel beenden, welches auch gleich die Möglichkeit des Filterns von Tabellen demonstriert: Der folgende Testfall wurde verwendet, um einen Bug im Nachrichtenmodul von eStudy zu finden (siehe Ticket #315).

public function messageShouldReceiveUserOnBuddylist() {
  $this->insertIntoDatabase(__DIR__ . "/datasets/buddylist.xml"); // (1)
  
  $sender = $this->createMessageSender(); // (2)
  $sender->send(null, null);
  
  $this->assertInboxEquals(__DIR__  . "/datasets/inbox-after-sending.xml"); // (3)
}

Der Test beginnt bei Punkt (1) mit dem Initialisieren der Datenbank mit einem speziellen Seed. Danach wird in Punkt (2) ein Objekt der Klasse MessageSender erzeugt. Diese Klasse erwartet im Konstruktor sehr viele Parameter, welche alle für diese Testklasse irrelevant sind. Daher verwenden wir eine Factory-Methode, welche lediglich noch einen Parameter benötigt. Auch dieser ist für diesen konkreten Testfall egal, daher übergeben wir nichts. Anschließend versenden wir eine Nachricht, auch hier sind uns die Parameter der Methode egal, daher übergeben wir diesmal null. In Punkt (3) schauen wir schließlich, ob die versendete Nachricht auch wirklich in dem entsprechenden Posteingang angekommen ist. Dies war nicht der Fall, somit konnte der Bug identifiziert werden.

Wie sieht nun die Methode assertInboxEquals aus? Sie verwendet einen Dataset-Filter, damit wir in unserem Dataset inbox-after-sending.xml nur die relevanten Tabellenspalten angeben müssen. Beispielsweise wäre es auch gar nicht möglich mittels Dataset zu prüfen, ob eine Spalte mit dem Wert von NOW() befüllt wurde.

private function assertInboxEquals($expectedDataSet) {
  $expected = $this->createXMLDataSet($expectedDataSet); // (1)
  $actual = new PHPUnit_Extensions_Database_DataSet_DataSetFilter(
    $this->getConnection()->createDataSet(array('messaging_inbox')), // (2)
    array('messaging_inbox' => array('ID', 'subject', 'message', 'date', 'isRead', 'isArchived')) // (3)
  );
  $this->assertDataSetsEqual($expected, $actual); // (4)
}

Zunächst lädt die Methode das Dataset mit dem erwarteten Inhalt des Posteingangs (1). Dann wird das Filter-Objekt erstellt und aus der Datenbank die Tabelle messaging_inbox geladen (2). Das aus der Tabelle gewonnene Dataset soll schließlich nur noch die in Punkt (3) genannten Spalten (die Werte des Unterarrays) enthalten. Alle übrigen Spalten tauchen im Dataset nicht mehr auf. Schließlich verwenden wir die PHPUnit-Methode assertDataSetsEqual um den tatsächlichen Posteingang mit dem Erwarteten zu vergleichen (4).

Softwareanforderungen von eStudy

Server Dienste

Apache Webserver

Eine einzelne Apache-Installation kann mehrere, virtuelle Hosts (vhosts) zu Verfügung stellen. Diese werden über verschiedene Domains und/oder verschiedene Ports aufgerufen.

Apache ist modular aufgebaut, so dass der Server in seiner Funktionalität extrem vielfältig ist. Für Entwicklungsysteme reicht in der Regel die Standardkonfiguration. Wer jedoch den Indianer ans Internet hängen will, sollte den Webserver und die PHP-Konfiguration gründlich auf Sicherheitseinstellungen prüfen. Sicherheit ist ein Gesamtkonzept, keine noch so sauber und sicher implementierte Anwendung ist sicher, wenn die Basis es nicht ist. Es macht ja auch keiner Gitter vor sein Fenster wenn er keine Haustür hat...

Mysql Datenbank

Mysql ist vieleicht nicht das Beste, aber sicherlich unter Webanwendungen das verbreiteste DBMS.

PHP

PHP ist ein Server Dienst? Nein, nätürlich nicht. PHP ist an dieser Stelle vermerkt, da es in den meisten Fällen durch ein Apachemodul verfügbar gemacht wird und somit ein Bestandteil des Webservers ist. Umfangreiche Infos zu PHP & Sicherheit von der Installation bis zur Implementierung sind unter PHP-Sicherheit zu finden.

Optionale Dienste

LDAP Server slapd

eStudy bietet die Möglichkeit sich gegenüber den FH eigenen LDAP-Server zu authentifizieren. Dieser lässt sich aber nur innerhalb des FH-Netzes benutzen. Für lokale Tests ist man gezwungen den LDAP-Baum der FH nachzubauen.

memcached

Memcached ist ein Caching System, man setzt es ein um die Performance von Dynamischen Seiten zu steigern.

Entwicklungswerkzeuge

Allgemein

Testen

Security

Server Dienste zur Entwicklung

Eine eStudy Installation

Wer die Installation einer Entwicklungsumgebung durchführen will, benötigt erstmal unabhängig von der eingesetzten Plattform die gleichen Dinge wie z.B. einen Webserver. Dazu haben wir eine sortierte Liste der relevanten Artikel aller Schritte erstellt. Diese Liste soll als Orientierung dienen.


Info.png

Wer XAMPP installiert hat startet in dieser Anleitung bei dem Anlegen der eStudy-Datenbank und macht danach weiter bei "Eclipse einrichten"

Wo bin ich?

  1. Übersicht
  2. Apache Installation
  3. Mysql Installation
  4. PHP Installation
  5. Datenbank einrichten
  6. Eclipse einrichten
  7. eStudy-Code besorgen
  8. PEAR installieren
  9. PHPUnit installieren
  10. eStudy installieren
  11. Xdebug installieren
  12. Entwickler Infos

Hinweise

Ausserdem sollte man folgendes wissen:

  1. Um Code in das Subversion-Repository zu stellen, benötigt man einen Trac-Account.
  2. Ein Trac-Account erhält nur Schreibrechte auf Anfrage bei einem Administrator.

Wiki

Das Wiki besitzt eine Wiki-Hilfe die erweitert werden kann. Ausserdem ist es nicht schwer Vorlagen zu gestalten und zu benutzten.

eStudy Links

eStudy-Trac