MochiTest-Lite

Just a reminder to myself, because I want to try that extension:

Mochitest is a unit testing framework created by contributors to Mozilla projects. Mochitest is based on MochiKit , the incredibly useful Javascript library. MochiKit as the basis for writing unit tests has been proven very useful to developing Mozilla applications because of the thick layers of Javscript code in applications like Firefox.

What then, is Mochitest-Lite?
Mochitest, as it is used at Mozilla, requires Python to drive the command line interface, and automate the testing. Python is a very powerful tool for this purpose because, along with automation, it can overwrite and then rewrite configuration files like manifests and preferences, all while having a minimal impact on the application being tested. Mochitest also uses a client-server architecture to serve test documents to the application being tested. On top of that, an application needs to be built with the Mozilla build system to work with Mochitest.

This makes sense for large applications like Firefox, but what about a unit testing framework for developers of small XULrunner applications and extensions for existing Mozilla applications? These developers have different requirements. Mochitest-Lite is a way to get the same test writing tools and automation without the overhead of running Mochitest the same way it is used to test Mozilla code.

Javascript dynamisch laden

Heute habe ich mich hauptsächlich damit beschäftigt, wie man Javascript-Dateien innerhalb von Javascript-Dateien includiert. Mein erster Ansatz war (etwas XUL-spezifisch, aber prinzipiell klappt das auch im HTML-DOM):

var jsFiles = [
    "chrome://myEntension/content/lib/domain.js",
		"chrome://myExtension/content/lib/helper.js",
    "chrome://myExtension/content/lib/js_locale.js",
		"chrome://myExtension/content/lib/urlParser.js"
    ];
var root = document.getElementById("someId")
for (var i = 0; i < jsFiles.length; i++) {
	var scriptElement = document.createElement("script");
	scriptElement.setAttribute("type", "application/x-javascript");
	scriptElement.setAttribute("src", jsFiles[i]);
  root.appendChild(scriptElement);
}

Das hat auch eigentlich soweit ganz gut geklappt, im DOM waren alle drin. Nur war irgendwie keine der includierten Funktionen … verfügbar. So als ob die Knoten in den DOM reingehängt wurden, aber das src-Attribute nicht ausgelesen und .. geparst.

Nunja, nachdem ich damit eine Weile rumgedoktert habe, wurde im im Mozilla-IRC-Channel auf Components.utils.import hingewiesen. Das ist doch genau das was ich brauche. Also sieht das jetzt so aus:

var jsFiles = [
    "chrome://myEntension/content/lib/domain.js",
		"chrome://myExtension/content/lib/helper.js",
    "chrome://myExtension/content/lib/js_locale.js",
		"chrome://myExtension/content/lib/urlParser.js"
    ];
for (var i = 0; i < jsFiles.length; i++) {
  Components.utils.import(jsFiles[i]);
}

Wunderhübsch. Klappt nur nicht, weil chrome://-URLs nicht erlaubt sind. Man braucht file:// oder resource://. Also schreibt man ins chrome.manifest:

resource jslibs content/lib/

und schreibt obige chrome://-URL um in:

"resource://jslibs/helper.js"

Wunderprächtig. Jetzt klappts. Fast. In jede Datei die man importiert muss man noch reinschreiben was denn exportiert werden soll. Klingt umständlich, der tiefere Sinn hat sich mir noch verschlossen, aber erstmal egal für die Funktionalität:

var EXPORTED_SYMBOLS = ["LOG"];
function LOG(msg) {
    Components.classes["@mozilla.org/consoleservice;1"]
            .getService(Components.interfaces.nsIConsoleService);
            .logStringMessage(new Date().toLocaleString() + ": " + msg);
}

Am obigen EXPORTED_SYMBOLS gibt man an welche Variablen nach außen hin sichtbar sein sollen. Voila, es ist geschafft.

XML, XUL, XSLT und XPath

Jede Menge X kommen in dieser Überschrift vor. Ich erzähle hier nichts Neues, und wer schon damit was gemacht hat, wird mich vermutlich sofort korrigieren (warum hält sich bei mir eigentlich immer noch die falsche Schreibweise „korregieren“?). Kommen wir also mal zu

XML

XML kommt aus der Gegend Gemünden, Rheinland-Pfalz, Menge SGML. Vielfach wird XML als Dialekt beschrieben, allerdings ist XML „nur“ eine Untermenge von SGML. Letztendlich ist aber eigentlich jedem klar was man mit XML meint, egal ob Dialekt oder Untermenge. Wer den genauen Unterschied wissen will, kann das gerne beim W3 (http://de.wikipedia.org/wiki/World_Wide_Web_Consortium) nachlesen (XML vs. SGML).

Nunja, als XML erfunden wurde, legte man folgende Ziele für XML fest (*):

  • XML soll sich im Internet auf einfache Weise nutzen lassen.
  • XML soll ein breites Spektrum von Anwendungen unterstützen.
  • XML soll zu SGML kompatibel sein.
  • Es soll einfach sein, Programme zu schreiben, die XML-Dokumente verarbeiten.
  • Die Zahl optionaler Merkmale in XML soll minimal sein, idealerweise Null.
  • XML-Dokumente sollten für Menschen lesbar und angemessen verständlich sein.
  • Der XML-Entwurf sollte zügig abgefasst sein.
  • Der Entwurf von XML soll formal und präzise sein.
  • XML-Dokumente sollen leicht zu erstellen sein.
  • Knappheit von XML-Markup ist von minimaler Bedeutung.

(*) Im Originalwortlaut heisst es hier shall, was eigentlich sollen bedeutet. RFC 2119 sagt allerdings das shall dasselbe bedeutet wie must. In der deutschen Übersetzung steht wieder sollen. Der feine Unterschied wurde mir freundlicherweise vom W3C.DE/AT klargestellt: Wenn shall grossgeschrieben ist (SHALL), dann ist es eine zwingende Anforderung, wenn es klein geschrieben ist, dann ist es keine formale Anforderung. Also: SHALL == müssen und shall == sollen.

XML sollte also klein, schön und leicht lesbar sein. Diese Ziele wurden tatsächlich erreicht.

XSLT und XPath

Zuallererst: XSL ist nicht dasselbe wie XSLT. Deswegen definieren wir erstmal den Unterschied.

XSL

XSL ist die Extensible Stylesheet Language, d.h. die erweiterbare Gestaltungssprache. Furchtbare Übersetzung. Letztendlich definiert XSL zwei Teile:

  1. XSLT, als Sprache zur Transformierung von XML-Dokumenten
  2. XSL-FO, eine Seitenbeschreibungssprache. Diese dient dazu den exakten Aufbau einer Seite zu beschreiben, so dass diese nachher unverändert an den Drucker oder sonstige Ausgabegeräte geschickt werden kann.

Um XSLT ordentlich benutzen zu können (wir stellen uns mal ein XML-Dokument als Baum vor), muss man ja irgendie die einzelnen Äste und Zweige des Baums ansprechen können. Da die nicht auf Hans oder Georg hören, wurde „XPath“ erfunden.

XPath

XPath kann man sich vorstellen wie den Verzeichnisbaum unter *nux. /home/pennywise greift auf den Knoten pennywise zu, der an den Knoten home gehängt wurde. Es gibt noch implizit den root-Knoten, da wurde dann home dran gehängt.

Genau so kann man sich auch XPath vorstellen. Ich nehm hier mal das Beispiel aus der Wikipedia:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<dok>
  <!-- ein XML-Dokument -->
  <kap title="Nettes Dokument">
    <pa>Ein Absatz</pa>
    <pa>Noch ein Absatz</pa>
    <pa>Und noch ein Absatz</pa>
    <pa>Nett, oder?</pa>
  </kap>
  <kap title="Zweites Kapitel">
    <pa>Ein Absatz</pa>
  </kap>
</dok>

Beispiele für XPath-Ausdrücke:

  • /dok selektiert das Wurzel-Element dok
  • /* selektiert das Wurzel-Element unabhängig vom Namen (jedes wohlgeformte XML-Dokument hat genau ein Wurzel-Element)
  • /dok/kap selektiert alle kap-Elemente innerhalb eines dok Elements
  • /dok/kap[1] selektiert das erste kap-Element innerhalb eines dok Elements
  • //pa selektiert alle pa-Elemente auf allen Ebenen (Vorsicht: langsam)
  • //kap[@title=“Nettes Dokument“]/pa selektiert alle Absätze des Kapitels „Nettes Dokument“.

Jetzt können wir also auf ein XML-Dokument zugreifen, fangen wir an mit dem transformieren:

XSLT

Auch hier will ich nichts neues erfinden und verweise einfach auf die Wikipedia.

XUL

Und was hat XUL damit zu tun? Nun, XUL, XML User Interface Language, wird z.B. benutzt um den Firefox anzuzeigen. Dieser ist komplett in XUL gefertigt. Bevor ich in meinem nächsten Post mit weiteren Begriffen um mich schmeisse, langt das erstmal.

Firefox Addons selbst erstellen

Dieser Artikel ist aus dem Jahr 2008. Inzwischen hat sich jede Menge geändert, insbesondere im Zusammenhang mit Firefox Addons. Nachfolgende Informationen sind veraltet und werden höchstwahrscheinlich nicht mehr funktionieren. Ich empfehle jetzt eher die Lektüre von https://addons.mozilla.org/en-US/developers/builder

Meine Diplomarbeit wird ein Firefox-Addon sein (früher hiessen die noch Extensions), also schreib ich hier gleich mal meine Erfahrungen bezüglich dessen nieder. Wird mir helfen Text für meine Diplomarbeit zu generieren. Zuerst ein paar Links

Dann die Erklärung, wie man die Entwicklung „leichter“ gestaltet. Alles prima erklärt auf der Seite von Mozilla, aber ich schreibs auch nochmal hin. Zuerst brauchen wir einen Entwickler-Firefox, als besser gesagt, ein Entwickler-Profil. Dazu machen wir Folgendes

  1. Erstelle eine Batchdatei (z.B. auf deinem Desktop): firefox-dev.bat
  2. Innerhalb dieser Batchdatei schreibst du:
    • start "" "%ProgramFiles%\Mozilla Firefox\firefox.exe" -no-remote -P dev
  3. Speichern und schliessen.

Dieses Profil füttern wir dann mit ein paar hilfreichen Extensions

Ich benutze zur Zeit die Spket IDE, allerdings ist die schon etwas älter, d.h. die Extensions sind erstmal nur FF 2.0 kompatibel. Das lässt sich zwar mit einer Zeilenänderung ändern, aber ist lästig.

Um dem neuen Profil („dev“) auch die Erweiterung bekannt zu machen, gibt es folgende Möglichkeit:

  1. Herausfinden an welcher Stelle die chrome.manifest Datei liegt. Bei mir z.B. unter ~/workspace/projektA/chrome.manifest
  2. In das Profilverzeichnis von „dev“ gehen. Dort in den Unterordner extensions
  3. Im selben Verzeichnis wie die chrome.manifest befindet sich auch die install.rdf. In dieser gibt es den XML-Knoten <em:id>foobar@example.com</em:id>. Diese Id merken wir uns (hier: foobar@example.com).
  4. Wir erstellen im Profilverzeichnis/extensions eine Datei mit dem Namen foobar@example.com. Innerhalb dieser Datei geben wir den Pfad zur chrome.manifest an (z.B. ~/workspace/projektA/)

Fertig. Ich werde diesen Artikel wohl noch erweitern und verbessern im Laufe des nächsten halben Jahres 🙂