5
magazin Java Architekturen Web Agile www.javamagazin.de Österreich € 10,80 Schweiz sFr 19,50 Luxemburg € 11,15 Deutschland € 9,80 JAVA Mag 5.2014 Kommentar: Wie praxistauglich ist JSF wirklich? 74 WildFly 8 Neue Features plus Interview 64 MongoDB Big Data schemafrei verwalten 56 Alle Infos hier im Heft! 35 Clojure Testing: Alternatives Testframework Midje 14 Software- architektur: Beschränkte Mittel 36 Design for Diagnosability: Wenn das System sagt, was ihm weh tut 44 REACTIVE PROGRAMMING Event-basierte Architekturen und ihre Vorteile > 18 „Die reaktive Zukunft der JVM sieht rosig aus.“ Interview mit Jonas Bonér > 26

Big Data schemafrei verwalten 56 Neue Features plus ......ihm weh tut 44 Reactive PRogRamming ... ein WORK TO DO aus: (future-fact "about a new fancy function" (fact "it returns fancy"

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Big Data schemafrei verwalten 56 Neue Features plus ......ihm weh tut 44 Reactive PRogRamming ... ein WORK TO DO aus: (future-fact "about a new fancy function" (fact "it returns fancy"

magazinJava • Architekturen • Web • Agile www.javamagazin.de

Österreich € 10,80 Schweiz sFr 19,50 Luxemburg € 11,15Deutschland € 9,80Java

Mag

5.2014

Kommentar: Wie praxistauglich ist JSF wirklich? 74

WildFly 8 Neue Features plus Interview 64

MongoDB Big Data schemafrei verwalten 56

Alle Infos hier im Heft!

35

Clojure Testing: Alternatives Testframework Midje 14

Software­architektur: Beschränkte Mittel 36

Design for Diagnosability: Wenn das System sagt, was ihm weh tut 44

Reactive PRogRamming

Event-basierte Architekturen und ihre Vorteile > 18

„Die reaktive Zukunft der JVM sieht rosig aus.“ Interview mit Jonas Bonér > 26

Page 2: Big Data schemafrei verwalten 56 Neue Features plus ......ihm weh tut 44 Reactive PRogRamming ... ein WORK TO DO aus: (future-fact "about a new fancy function" (fact "it returns fancy"

von Tobias Bayer

Midje (sprich [midʒ]) ist ein Testframework für Clojure und damit eine Alternative zu clojure.test. Große Stär-ken von Midje sind die bessere Lesbarkeit von Tests und das einfache Stubben und Mocken von Funktionen. Die Tests werden in einer Form geschrieben, die auch in Clo-jure-Büchern wie zum Beispiel „The Joy of Clo jure“ [2] für Beispiele verwendet wird. Eine sehr einfache Tester-wartung sieht etwa so aus:

(+ 1 1) => 2

Facts und CheckablesTests werden anhand von Fakten zusammengefasst und strukturiert. Das Makro fact bzw. facts kann op-tional um einen auch bei Clojure-Funktionen üblichen Docstring zur genaueren Erläuterung des Tests ergänzt werden. Die Verwendung dieser Dokumentation hat sich als sehr sinnvoll für den schnelleren Überblick über eine Testsuite erwiesen. Facts können beliebig ver-schachtelt werden, wobei facts lediglich ein Synonym für fact ist, um die Lesbarkeit zu verbessern (Listing 1).

Facts bestehen aus einem oder mehreren „Check-ables“. Ein Checkable besteht aus einem Pfeil (=>) und einer rechten und linken Seite. Die linke Seite enthält

die auszuführende Funktion mit ihren Argumenten, die rechte Seite das erwartete Ergebnis. Statt => kann auch =not=> verwendet werden, um direkt die Ungleichheit der beiden Seiten des Checkables zu prüfen.

In Listing 1 befinden sich auf der rechten Seite der Checkables jeweils einfache Werte. Statt einfacher Wer-te lassen sich über „Checker“ auch komplexere Bedin-gungen prüfen. Dazu später mehr.

Wenn Facts zur Spezifikation von gewolltem Soft-wareverhalten verwendet werden, werden diese, wie im TDD üblich, vor dem eigentlichen Verhalten implemen-tiert. Um einen Fact für ein später gewünschtes Verhal-ten zu implementieren, ohne die Tests fehlschlagen zu lassen, kann das Makro future-fact verwendet werden. Die Checkables in einem future-fact werden bei der Aus-führung der Tests nicht evaluiert. Midje gibt lediglich ein WORK TO DO aus:

(future-fact "about a new fancy function" (fact "it returns fancy" (fancy-function) => "fancy"))

Erzeugen eines Projekts mit Midje-TestsMidje bringt ein eigenes Leiningen-Plug-in zum Erzeu-gen der passenden Ordner- und Dateistruktur sowie zum Ausführen der Tests mit. Dieses muss einmal in der Datei ~/.lein/profiles.clj registriert werden:

{:user {:plugins [[lein-midje "3.1.3"]]}}

Ein neues Projekt mit Unterstützung für Midje kann dann per lein new midje projektname angelegt wer-den. Das Leiningen-Plug-in erzeugt automatisch die in Listing 2 dargestellte Dateistruktur und füllt den Test-Name space mit einem kleinen Beispiel.

Listing 1

(facts "about '+'" (fact "1 plus 1 equals 2" (+ 1 1) => 2) (fact "adding negative numbers results in a negative number" (+ -1 -1) => -2))

Midje als alternatives Testframework für Clojure

Fakten, Fakten, Fakten! Midges [1] sind kleine, aber unangenehme Zeitgenossen, die einen Aufenthalt in den schot-tischen Highlands ohne die richtige Vorbereitung zur Hölle machen können. Das Clojure-Test-framework Midje hat mit diesen Mücken zum Glück nur den Namen gemein. Im Gegensatz zu ihnen macht es das Entwicklerleben nicht schwerer, sondern das Testen von Clojure-Program-men auch ohne große und aufwändige Vorbereitung und Einarbeitung sehr angenehm.

Vollendete Technik und die Harmonie zwischen Körper und Geist sind das oberste Ziel im Kendo. Die hohe Kunst der Software Monetarisierung besteht darin, im Einklang mit den unterschiedlichsten Markt- und Kundenanforderungen, das Maximum aus ihrer Software zu holen.

Jetzt können auch Sie diese Stufe der Perfektion erreichen. Mit den bewährten und innovativen Lösungen für Softwarelizenzierung und Management von SafeNet bringen Sie in kurzer Zeit eine Vielzahl von Lizenzmodellen sowie flexible Preis- und Paketvarianten mühelos mit Ihren Geschäftsmodellen in Einklang – unabhängig davon ob Sie eine On-Premise, Cloud-basierte oder hybride Lizenzierung wählen.

Erreichen auch Sie den Meistergrad der Software Monetarisierung und erfahren Sie mehr über die SafeNet Sentinel Produktfamile unter www.safenet-inc.com/jax2014

SOFTWARELIZENZIERUNG UND -MANAGEMENT

The Art of Software Monetization

Besuchen Sie uns auf unserem Stand auf der JAX 2014 (13.- 15. Mai 2014) und erfahren Sie mehr darüber, wie Sie Ihre Software Monetarisierung mit der SafeNet Produktfamilie verwirklichen können. Und mit ein bisschen Glück gewinnen Sie eine von drei OUYA Spielekonsolen.

SafeNet SFNT Germany GmbH Gabriele-Münter-Str. 1 | 82110 Germering | Germany | +49 (0) 89 894 221 -0 javamagazin 5 | 2014

Tools Clojure Testing

14 www.JAXenter.de

Page 3: Big Data schemafrei verwalten 56 Neue Features plus ......ihm weh tut 44 Reactive PRogRamming ... ein WORK TO DO aus: (future-fact "about a new fancy function" (fact "it returns fancy"

Natürlich kann diese Struktur auch manuell in ein be-reits bestehendes Projekt eingepflegt werden. Ein Midje-Test-Namespace verwendet zumindest den getesteten Namespace und midje.sweet, in dem alle relevanten Funktionen und Makros von Midje deklariert sind:

(ns midje_demo.t-core (:use midje.sweet) (:use [midje_demo.core]))

(facts ...)

Ausführen von Midje-TestsIm Projektverzeichnis können alle vorhandenen Midje-Tests per lein midje ausgeführt werden. Dieser Aufruf hat den Nachteil, dass das Starten der JVM und der Clo-jure-Laufzeitumgebung etwas Zeit in Anspruch nimmt und man so relativ lange auf die Testergebnisse warten muss.

Startet man die Tests hingegen mit lein midje :auto-test, wird für den ersten Start zwar genau so viel Zeit benötigt, aber Midje bleibt dann aktiv und erkennt Än-derungen an den Tests oder den getesteten Namespaces und führt diese bei jeder Änderung automatisch erneut in der anfangs gestarteten Laufzeitumgebung aus.

Wenn man die Tests aus Listing 1 ausführt, erhält man die Ausgabe in Listing 3 unter „Testausführung 1“.

Hier zeigt sich auch der Vorteil der Verwendung eines Docstrings für die Fakten. Das Testprotokoll ist dann gut lesbar. Für die zweite Testausführung in Listing 3 wur-de der zweite Fakt absichtlich so angepasst, dass er fehlschlägt, um die entsprechende Ausgabe zu demonstrieren. (Die Erwartung wurde von -2 auf 2 geändert.)

CheckersAuf der rechten Seite eines Checkables können statt einfa-cher Werte, die gegen das Funk-tionsergebnis verglichen werden, auch von Midje vordefinierte Funktionen, „Checkers“, verwendet werden. Midje ruft den Checker mit dem Er-gebnis der Funktion auf der linken Seite des Checkables als Argument auf. Midje bringt bereits eine große An-zahl von Checkern mit. Im Folgenden betrachten wir einige davon exemplarisch. Weitere Checker sind im Midje-Wiki [3] dokumentiert.

truthy, falseyDiese Checker können verwendet werden, wenn das Er-gebnis einer Funktion true oder nicht nil bzw. false oder

Listing 2: Midje- Projektdateistruktur

$ lein new midje midje-demo=>|____project.clj|____README.md|____src| |____midje_demo| | |____core.clj|____test| |____midje_demo| | |____t_core.clj

Anzeige

Vollendete Technik und die Harmonie zwischen Körper und Geist sind das oberste Ziel im Kendo. Die hohe Kunst der Software Monetarisierung besteht darin, im Einklang mit den unterschiedlichsten Markt- und Kundenanforderungen, das Maximum aus ihrer Software zu holen.

Jetzt können auch Sie diese Stufe der Perfektion erreichen. Mit den bewährten und innovativen Lösungen für Softwarelizenzierung und Management von SafeNet bringen Sie in kurzer Zeit eine Vielzahl von Lizenzmodellen sowie flexible Preis- und Paketvarianten mühelos mit Ihren Geschäftsmodellen in Einklang – unabhängig davon ob Sie eine On-Premise, Cloud-basierte oder hybride Lizenzierung wählen.

Erreichen auch Sie den Meistergrad der Software Monetarisierung und erfahren Sie mehr über die SafeNet Sentinel Produktfamile unter www.safenet-inc.com/jax2014

SOFTWARELIZENZIERUNG UND -MANAGEMENT

The Art of Software Monetization

Besuchen Sie uns auf unserem Stand auf der JAX 2014 (13.- 15. Mai 2014) und erfahren Sie mehr darüber, wie Sie Ihre Software Monetarisierung mit der SafeNet Produktfamilie verwirklichen können. Und mit ein bisschen Glück gewinnen Sie eine von drei OUYA Spielekonsolen.

SafeNet SFNT Germany GmbH Gabriele-Münter-Str. 1 | 82110 Germering | Germany | +49 (0) 89 894 221 -0

ToolsClojure Testing

Page 4: Big Data schemafrei verwalten 56 Neue Features plus ......ihm weh tut 44 Reactive PRogRamming ... ein WORK TO DO aus: (future-fact "about a new fancy function" (fact "it returns fancy"

nil sein soll, ohne dass es auf die genaue Ausprägung des Ergebnisses ankommt.

anything, irrelevantIn manchen Fällen ist ein Test so aufgebaut, dass das Ergebnis der Funktion für den Test nicht relevant ist. Üblicherweise trifft das bei Funktionen mit Nebeneffek-ten (z. B. Datenbankinserts) zu. Dann kann die Funktion

ausgeführt werden, ohne dass der Rückgabewert Aus-wirkungen auf den Test hat (Listing 4). Ein weiteres An-wendungsgebiet ist die Verwendung von Prerequi sites, die wir später betrachten.

throwsDer throws-Checker verlangt, dass ein Funktionsaufruf eine Exception wirft:

(fact (throwing-function) => (throws Exception))

Auch das Prüfen der Exception-Message ist möglich:

(fact (throwing-function) => (throws Exception "foo"))

Die Exception-Message kann auch gegen einen regulä-ren Ausdruck geprüft werden:

(fact (throwing-function) => (throws Exception #"(foo|bar)"))

Listing 5: contains-Checker

(facts "about my sequence" (fact "it contains the value 5" '(1 2 3 4 5 6) => (contains 5)) (fact "it contains the values 2 and 3" '(1 2 3 4 5 6) => (contains 2 3)) (fact "it contains an odd number followed by an even number" '(1 2 3 4 5 6) => (contains odd? even?)))

(facts "about my map" (fact "the value of x is 1" {:x 1 :y 2} => (contains {:x 1})) (fact "the value of y is even" {:x 1 :y 2} => (contains {:y even?})))

Listing 6: Eigener Checker

(defn each-element-is-one-of [expected-elements] (fn [actual] (every? (set expected-elements) actual)))

(fact "each element is one of 1-10" '(1 2 3 4 5 6) => (each-element-is-one-of (range 1 11)))

Listing 7: Stubbing mit der provided-Form

(defn find-user [username] ;; Code, der den User anhand des Namens in der DB sucht und zurückgibt )(defn authenticate [username password] (let [user (find-user username)] (if (= (:password user) password) user)))

(fact "it authenticates a user with a valid password" (authenticate "the fly" "12345") => truthy (provided (find-user "the fly") => {:name "the fly" :password "12345"}))

Listing 8: Aufrufhäufigkeiten beim Mocken

(fact "it calls the second function 5 times with argument 'foo'" (first-function) => irrelevant (provided (second-function "foo") => irrelevant :times 5))

(fact "it never calls the third function with any argument" (first-function) => irrelevant (provided (third-function anything) => irrelevant :times 0))

Listing 3: Testergebnis

;; Testausführung 1$ lein midje

= Namespace midje_demo.t-coreChecking about '+'Checking 1 plus 1 equals 2Checking adding negative numbers results in a negative numberAll checks (2) succeeded.

;; Testausführung 2 mit absichtlich fehlerhaftem Test$ lein midje

= Namespace midje_demo.t-coreChecking about '+'Checking 1 plus 1 equals 2Checking adding negative numbers results in a negative number

FAIL "about '+' - adding negative numbers results in a negative number" at ... Expected: 2 Actual: -2FAILURE: 1 check failed. (But 1 succeeded.)

Listing 4: anything-Checker

(facts "about db inserts" (fact "it finds the entry after an insert" (insert-name 1 "the inserted name") => anything (find-name 1) => "the inserted name"))

javamagazin 5 | 2014

Tools Clojure Testing

16 www.JAXenter.de

Page 5: Big Data schemafrei verwalten 56 Neue Features plus ......ihm weh tut 44 Reactive PRogRamming ... ein WORK TO DO aus: (future-fact "about a new fancy function" (fact "it returns fancy"

containsDieser Checker kann auf Sequences oder Maps angewendet werden. Er prüft, ob sich ein bestimmter Wert bzw. ein Schlüssel-Wert-Paar darin befindet. Es können beliebig viele Werte bzw. Paare als Argument übergeben werden. Außerdem kön-nen statt konkreten Werten auch Funktionen verwendet werden, die Eigenschaften der Werte prüfen (Listing 5).

Man kann eine Checker-Funktion auch selbst implementieren. Dazu schreibt man eine Higher-Order-Function, die eine Funktion zurückgibt, die als erstes Ar-gument das zu prüfende Funktionsergebnis erwartet (Listing 6).

PrerequisitesStubs und Mocks sind aus der objektorientierten Welt bekannt. Sie werden dort verwendet, um ein Objekt unabhängig von seinen Kollaborateuren testen zu kön-nen. In der funktionalen Welt gibt es zwar keine kollaborierenden Objekte, aber andere Funktionen, die von der zu testenden Funktion aufgerufen werden. Um die zu testende Funktion unabhängig zu machen, bietet Midje die provided-Form. Unter Verwendung von provided lassen sich einerseits vorgefertigte Ergebnisse aus einer Funktion (Prerequisites) zurückgeben und andererseits die Aufrufe der Funk-tion protokollieren und abprüfen.

Nehmen wir an, wir wollen eine Funktion authenticate implementieren, die an-hand ihrer Argumente einen User in der Datenbank sucht und dann prüft, ob des-sen Passwort korrekt angegeben wurde. Ist das Passwort korrekt, wird der User zurückgegeben, ansonsten nil. Wollen wir diese Funktion ohne Datenbankanbin-dung testen, so müssen wir die Datenbanksuche so stubben, dass ein passender Test user zurückgegeben wird. Dazu geben wir zusätzlich zum eigentlichen Check-able eine provided-Form an, in der wir den gewünschten Rückgabewert der ge-stubbten Funktion für unseren Test spezifizieren (Listing 7).

Gleichzeitig kann man die provided-Form auch zum Mocken verwenden. Der Test in Listing 7 würde auch fehlschlagen, wenn authenticate nicht find-user mit dem in der provided-Form angegebenen Argument – dem Usernamen "the fly" – aufruft.

Ist für das Mocken auch die Aufrufhäufigkeit einer Funktion interessant, kann die-se Erwartung ebenfalls ergänzt werden. Im Beispiel soll second-function beim Aufruf von first-function fünf Mal, aber third-function nie ausgeführt werden. Die Rückga-bewerte der aufgerufenen Funktionen sind für diesen Test nicht relevant (Listing 8).

FazitMidje ist ein mächtiges und zugleich sehr einsteigerfreundliches Framework zum Implementieren von Tests in Clojure. Die damit entstehenden Tests sind leichter zu lesen als die Pendants in clojure.test, was nicht zuletzt der Pfeilschreibweise (=>) und den einfachen Stubbing- und Mocking-Möglichkeiten zu verdanken ist, die in clojure.test nur durch das Schreiben eigener Makros oder das Einbinden wei-terer Bibliotheken zu erreichen sind. Die gute Unterstützung durch das passende Leiningen-Plug-in rundet das positive Gesamtbild zusätzlich ab.

Midje bietet noch eine Reihe weiterer Möglichkeiten, um Tests zu implementie-ren. Diese fortgeschrittenen Elemente würden den Rahmen dieses Einführungsarti-kels sprengen. Deshalb sei auf das sehr ausführliche Wiki auf den GitHub-Seiten [3] von Midje verwiesen.

Tobias Bayer ist Softwarearchitekt und Senior-Developer bei der inovex GmbH. Seine Schwerpunkte lie-gen auf der Entwicklung von Webapplikationen mit Java und mobilen Apps für iOS. Außerdem beschäf-tigt er sich mit funktionaler Programmierung in Clojure.

[email protected]

Links & Literatur

[1] http://en.wikipedia.org/wiki/Highland_midge

[2] Fogus, Michael; Houser, Chris (2013): „The Joy of Clojure“, Manning Publications Company, Birmingham

[3] https://github.com/marick/Midje/wiki

www.JAXenter.de

www.qfs.de

Quality First Software GmbHTulpenstraße 41

82538 GeretsriedDeutschland

Fon: + 49. (0)8171. 38 64 80

Das GUI Testtool für Java und Web

„Die Vollkommenheit besteht nicht in der Quantität, sondern in der

Baltasar Gracian v. Morales

QUALITÄT.“

FX/Swing/SWT/RCP und WebCapture/Replay & Skripting

Für Entwickler und TesterSystem- und Lasttests

HTML und AJAXBenutzerfreundlich

Robust und zuverlässigPlattform- & BrowserübergreifendEtabliert bei 600 Kunden weltweit

Deutsches HandbuchDeutscher Support

!Jetzt auch

JavaFX!