<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-4194361870903955864</id><updated>2009-03-15T12:32:04.813+01:00</updated><title type='text'>mllog</title><subtitle type='html'>Testing with MATLAB and Simulink</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-662818492277723676</id><published>2008-04-11T21:14:00.004+02:00</published><updated>2008-04-11T21:43:04.118+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testen'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><title type='text'>mlUnit 2.0 Beta</title><content type='html'>&lt;p&gt;Vor ein paar Tagen habe ich die neueste Version von mlUnit (genannt "2.0-beta1") bei SourceForge &lt;a href="http://sourceforge.net/forum/forum.php?forum_id=809055"&gt;veröffentlicht&lt;/a&gt;. mlUnit 2 ist die Re-Implementierung von mlUnit mit der &lt;a href="http://mllog.blogspot.com/2008/03/objektorientierte-programmierung-mit.html"&gt;neuen objektorientierter Syntax&lt;/a&gt; von MATLAB R2008a. Daraus ergeben sich drei wesentliche Unterschiede zur alten Version: (1) man kann mehrere Testmethoden einer Testfallklasse nun in einer einzelnen Datei definieren; (2) man kann mehrere solcher Testfallklassen in einem Paket mit einem eigenen Namensraum zusammenfassen; (3) man benötigt zwingend MATLAB R2008a oder neuer.&lt;/p&gt;

&lt;p&gt;Die Installation erfolgt durch den Download des &lt;a href="http://downloads.sourceforge.net/mlunit/mlunit_2.0-beta1.zip?modtime=1207686449&amp;big_mirror=0&amp;filesize=51172"&gt;bereitgestellten Archivs&lt;/a&gt;, das Entpacken in einen beliebigen Ordner und dem Hinzufügen des Quellverzeichnisses zum MATLAB-Pfad:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; addpath('$MLUNIT\mlunit2\src');&lt;/pre&gt;
&lt;p&gt;Mit $MLUNIT wird hierbei das Rootverzeichnis von mlUnit 2 bezeichnet.&lt;/pre&gt;

&lt;p&gt;Ein Beispieltestfall mit mlUnit 2 sieht wie folgt aus:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; edit test.sin.m 
    classdef test_sin &lt; mlunit.test_case 
        methods 
            function self = test_sin(varargin) 
                self = self@mlunit.test_case(varargin{:}); 
            end 
 
            function self = test_null(self) 
                mlunit.assert_equals(0, sin(0)); 
            end 
 
            function self = test_sin_cos(self) 
                mlunit.assert_equals(cos(0), sin(pi/2)); 
            end 
        end 
    end&lt;/pre&gt;
&lt;p&gt;Es wird die Testfallklasse test_sin erstellt, die von der Basisklasse test_case abgeleitet ist, und über zwei Testmethoden verfügt: test_null und test_sin_cos. Wie man sieht, sind die Klassen und Methoden von mlUnit selbst nun in dem gleichnamigen Paket gekapselt. Dadurch werden Konflikte mit MATLAB-eigenen Methoden verhindert.&lt;/p&gt;

&lt;p&gt;Der Testfall wird wie folgt ausgeführt:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; runner = mlunit.text_test_runner(1, 1); 
&gt;&gt; loader = mlunit.test_loader; 
&gt;&gt; run(runner, load_tests_from_test_case(loader, 'test_sin')); &lt;/pre&gt;

&lt;p&gt;Wie auch schon bei mlUnit 1.5 werden alle Testfälle, die während der Entwicklung von mlUnit entstanden sind, mitgeliefert. In der neuen Version sind diese im Paket mlunit_test enthalten:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; addpath('$MLUNIT\mlunit2\test');
&gt;&gt; mlunit_test.run;&lt;/pre&gt;

&lt;p&gt;Zum Schluss noch ein Hinweis in eigener Sache: mlUnit 2.0-beta1 ist ein Beta-Release. Bitte melden Sie Fehler per E-Mail an &lt;a href="mailto:thomas@dohmke.de"&gt;thomas@dohmke.de&lt;/a&gt; (am besten "mlunit" im Betreff verwenden), hinterlassen Sie einen Kommentar zu diesem Artikel oder verwenden Sie den &lt;a href="http://sourceforge.net/tracker/?atid=841178&amp;group_id=166995&amp;func=browse"&gt;Bugtracker des Projekts&lt;/a&gt;. Danke.&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-662818492277723676?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/662818492277723676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=662818492277723676&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/662818492277723676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/662818492277723676'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2008/04/mlunit-20-beta.html' title='mlUnit 2.0 Beta'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05611762638556486297</uri><email>thomas@dohmke.de</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08020833314722503912'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-8919393946893672644</id><published>2008-03-05T19:52:00.001+01:00</published><updated>2008-03-05T20:08:10.961+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='objektorientiert'/><title type='text'>Objektorientierte Programmierung mit MATLAB R2008a</title><content type='html'>&lt;p&gt;Wie ich schon in meinem &lt;a href="http://mllog.blogspot.com/2008/03/r2008a.html"&gt;letzten Beitrag&lt;/a&gt; schrieb, wurde in der neuen MATLAB-Version &lt;a href="http://www.mathworks.com/products/new_products/latest_features.html?s_cid=HP_RH_2008a"&gt;R2008a&lt;/a&gt; die Art und Weise der &lt;a href="http://www.mathworks.com/products/matlab/object_oriented_programming.html"&gt;objektorientierten Programmierung&lt;/a&gt; mit der Programmiersprache m verändert. Dazu wurde eine völlig neue Syntax definiert, die im folgenden vorgestellt werden soll.&lt;/p&gt;

&lt;p&gt;Bis Version R2007b war es notwendig, für eine Klasse ein neues Verzeichnis zu erzeugen, dessen Name mit einem @ beginnt. Diese Vorgehensweise kann auch weiterhin verwendet werden, und zwar immer dann, wenn die Methoden der Klasse auf mehrere Dateien verteilt werden soll. Ansonsten kann eine Klasse nun auch in einer einzelnen Datei untergebracht haben, die nach dem Bezeichner der Klasse benannt wird. Als Beispiel soll eine Klasse für ein Testergebnis dienen. Der Name der Klasse ist "test_result", dementsprechend wird eine Datei mit dem Namen "test_result.m" erstellt:&lt;/p&gt;

&lt;pre&gt;
classdef test_result
end
&lt;/pre&gt;

&lt;p&gt;Die Anweisung &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/bree1u6.html"&gt;"classdef"&lt;/a&gt; leitet die neue Klasse ein, es folgt der Name des Klasse und in üblicher MATLAB-Manier wird der Block mit einem "end" beendet. Mit dieser simplen Konstruktion ist die Klasse bereits funktionsfähig und kann auf der Kommandozeile instanziiert werden (vorausgesetzt, die Datei "test_result.m" ist entweder im aktuellen Verzeichnis oder im MATLAB-Pfad auffindbar):

&lt;pre&gt;
&gt;&gt; result = test_result	

result = 

test_result with no properties.
list of methods
&lt;/pre&gt;

&lt;p&gt;Wie MATLAB richtig bemerkt, hat die Klasse noch keine Eigenschaften. Das Wort "methods" wird hingegen als Link dargestellt und klickt man darauf, erscheint folgende Ausgabe mit dem Standardkonstruktor der Klasse:&lt;/p&gt;

&lt;pre&gt;
Methods for class test_result:

test_result  
&lt;/pre&gt;

&lt;p&gt;Zur Definition einer Eigenschaft wurde der Block &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/bqs9ybb-1.html"&gt;"properties"&lt;/a&gt; eingeführt, für Methoden der Block "methods":&lt;/p&gt;

&lt;pre&gt;
classdef test_result
    properties
        should_stop = 0;
    end
    
    methods
        function should_stop = get_should_stop(self)
            should_stop = self.should_stop;
        end
    end
end
&lt;/pre&gt;

&lt;p&gt;Im Beispiel wird die Eigenschaft "should_stop" definiert, die innerhalb des Testergebnisses anzeigt, dass die Testausführung beendet werden soll. Auf die Eigenschaft kann mittels der Methode "get_should_stop" zugegriffen werden.&lt;/p&gt; 

&lt;p&gt;Wie schon in R2007b und allen vorherigen Versionen, müssen bei der Veränderung einer Klasse alle Objekte dieser Klasse aus dem Workspace entfernt werden. Immerhin reicht aber jetzt ein einfaches &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/ref/clear.html"&gt;"clear"&lt;/a&gt; statt dem bisherigen "clear all":&lt;/p&gt;

&lt;pre&gt;
&gt;&gt; clear
&gt;&gt; result = test_result

result = 

test_result

properties:
    should_stop: 0

list of methods
&lt;/pre&gt;

&lt;p&gt;Im Gegensatz zur alten Programmierweise ist es nun auch erlaubt, direkt auf die Eigenschaften zuzugreifen:&lt;/p&gt;

&lt;pre&gt;
&gt;&gt; result.should_stop

ans =

     0
&lt;/pre&gt;

&lt;p&gt;Soll ein solcher Zugriff unterbunden werden, kann der "properties"-Block mit einem zusätzlichen &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/bqs9ybb-1.html#bqs9ybb-4"&gt;Attribut&lt;/a&gt; versehen werden:&lt;/p&gt;

&lt;pre&gt;
classdef test_result
    properties (GetAccess = private)
        should_stop = 0;
    end
    
    methods
        function should_stop = get_should_stop(self)
            should_stop = self.should_stop;
        end
    end
end
&lt;/pre&gt;

&lt;p&gt;Damit wird der Zugriff auf "should_stop" als privat deklariert, alternativ ist auch das Schlüsselwort "protected" erlaubt, welches den Zugriff auf ein Paket beschränkt (siehe unten). Das ganze führt zu einem interessanten Effekt:&lt;/p&gt;

&lt;pre&gt;
&gt;&gt; clear
&gt;&gt; result = test_result

result = 

test_result with no properties.
list of methods
&lt;/pre&gt;

&lt;p&gt;Laut dieser Aussage hat test_result nun keine Eigenschaften mehr. Eine Lesezugriff auf "should_stop" ist nur noch über die definierte Methode möglich:&lt;/p&gt;

&lt;pre&gt;
&gt;&gt; result.should_stop
??? Getting the 'should_stop' property of the 'test_result' class is not allowed.

&gt;&gt; result.get_should_stop

ans =

     0
&lt;/pre&gt;

&lt;p&gt;Ein Schreibzugriff ist aber weiterhin möglich:&lt;/p&gt;

&lt;pre&gt;
&gt;&gt; result.should_stop = 1;
&gt;&gt; result.get_should_stop

ans =

     1
&lt;/pre&gt;

&lt;p&gt;Soll auch dieser verhindert werden, muss auch das Attribut "SetAccess" entsprechend auf "private" gesetzt werden.&lt;/p&gt; 

&lt;pre&gt;
classdef test_result
    properties (GetAccess = private, SetAccess = private)
        should_stop = 0;
    end
    
    methods
        function should_stop = get_should_stop(self)
            should_stop = self.should_stop;
        end
    end
end
&lt;/pre&gt;

&lt;p&gt;Neben "GetAccess" und "SetAccess" existieren diverse &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brjjwby.html"&gt;weitere Attribute&lt;/a&gt;, u.a. um Eigenschaften als Konstanten zu definieren (sprich als statische Eigenschaften) oder um diese von der Serialisierung auszuschließen. Will man Eigenschaften mit verschiedenen Attributen auszeichnen, fügt man einfach mehrere "properties"-Blöcke ein:&lt;/p&gt;

&lt;pre&gt;
classdef test_result
    properties
      errors = {};
    end
    properties (GetAccess = private, SetAccess = private)
        should_stop = 0;
    end
    
    methods
        function should_stop = get_should_stop(self)
            should_stop = self.should_stop;
        end
    end
end
&lt;/pre&gt;

&lt;p&gt;Ferner ist es möglich, &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brgsek9-1.html"&gt;spezielle Methoden&lt;/a&gt; für den Zugriff auf eine Eigenschaft zu erstellen. Dies ist insbesondere dann sinnvoll, wenn vor dem Zuweisen oder Lesen weitere Schritte ausgeführt werden sollen, beispielsweise eine Prüfung des Wertebereichs.&lt;/p&gt;

&lt;p&gt;Auch bei &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/f1-13781.html"&gt;Methoden&lt;/a&gt; hat sich einiges getan. Oben wurde bereits auf die Methode "get_should_stop" mit der neuen Syntax verwendet, es ist aber auch weiterhin die alte Variante möglich:&lt;/p&gt;

&lt;pre&gt;
&gt;&gt; get_should_stop(result); % alt
&gt;&gt; result.get_should_stop;  % neu
&lt;/pre&gt;

&lt;p&gt;Ebenfalls im "method"-Block kann der &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brd2m9e-1.html"&gt;Konstruktor&lt;/a&gt; der Klasse definiert werden, wobei die gleiche Syntax wie bei einer normalen Funktion verwendet wird. Der Name der Funktion muss dem Namen der Klasse entsprechen, der Rückgabewert muss stets eine Instanz der Klasse sein.&lt;/p&gt;

&lt;p&gt;Will man explizit eine Methode der jeweiligen Superklasse aufrufen, d.h. einer Klasse, von der die verwendete Klasse per Vererbung abgeleitet ist, muss dem Namen der Methode ein @ und dann der Name der Superklasse folgenden. Beispiel:&lt;/p&gt;

&lt;pre&gt;
classdef text_test_result &lt; test_result
    methods
        function should_stop = get_should_stop(self)
	    fprintf(1, 'Should stop.\n');
            should_stop = get_should_stop@test_result(self);
        end
    end
end
&lt;/pre&gt;

&lt;p&gt;Die Klasse "text_test_result" wird hier von der Klasse "test_result" abgeleitet. Die Methode "get_should_stop" gibt zunächst eine Meldung auf der Standardausgabe aus, und ruft dann selbige Methode der Superklasse auf.&lt;/p&gt;

&lt;p&gt;Wie auch bei den Eigenschaften lassen sich neuerdings &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brjjv0d.html"&gt;zusätzliche Attribute&lt;/a&gt; zu jedem "method"-Block hinzufügen, die den Zugriff auf die enthaltenen Methoden limitieren können sowie sie als statisch, abstrakt oder endgültig (MathWorks nennt das "sealed", bei Java würde man "final" schreiben) markieren.&lt;/p&gt;

&lt;p&gt;Schließlich können Klassen in &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brfynt_-1.html"&gt;Paketen&lt;/a&gt; organisiert werden. Dazu muss die Klassendatei in ein Verzeichnis verschoben werden, dessen Name mit einem + beginnt und nachfolgend dem Namen des Paketes entspricht. Verschiebt man die Beispieldatei "test_result.m" in das Verzeichnis "+mlunit", welches außerdem dem MATLAB-Pfad hinzugefügt wird, so gehört die Klasse "test_result" nun dem Paket "mlunit" an. Entsprechend wird sie über folgenden Aufruf verwendet:&lt;/p&gt;

&lt;pre&gt;
&gt;&gt; result = mlunit.test_result;
&lt;/pre&gt;

&lt;p&gt;Ferner ist es möglich, ein oder mehrere Pakete innerhalb einer Methode (und nur dort) zu &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/breo9l7.html"&gt;importieren&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
function test_foobar()
    import mlunit.*;
    result = test_result();
end
&lt;/pre&gt;

&lt;p&gt;Etwas merkwürdig ist jedoch, dass auch innerhalb eines Paketes dessen Name referenziert werden muss. Obiges Beispiel für die Klasse "text_test_result" wird demnach zu:&lt;/p&gt;

&lt;pre&gt;
classdef text_test_result &lt; mlunit.test_result
    methods
        function should_stop = get_should_stop(self)
	    fprintf(1, 'Should stop.\n');
            should_stop = get_should_stop@mlunit.test_result(self);
        end
    end
end
&lt;/pre&gt;

&lt;p&gt;Die Referenz auf den Paketnamen innerhalb von "get_should_stop" lässt sich wiederum durch die "import"-Anweisung verhindern, während die erbende Klasse in der ersten Zeile stets den Paketnamen tragen muss (jedenfalls habe ich keine Möglichkeit gefunden, dies zu umgehen).&lt;/p&gt;

&lt;p&gt;Damit endet dieser erste Einblick in die neue objektorientierten Programmierung mit MATLAB R2008a, der aber keinesfalls umfassend ist. Insbesondere fehlen noch die neuen &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/brfylzt-1.html"&gt;"handle"-Klassen&lt;/a&gt; sowie die Möglichkeit, neben Eigenschaften und Methoden auch &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/bqvggvt-1.html"&gt;Ereignisse&lt;/a&gt; ("events") zu definieren. Sobald ich mir diese genauer angeschaut haben, wird es deshalb einen weiteren Artikel geben.&lt;/p&gt;

&lt;p&gt;Auch kann man die Beispiele in diesem Artikel durchaus als Hinweis deuten, das mlUnit 2.0 in Arbeit ist... :)&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-8919393946893672644?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/8919393946893672644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=8919393946893672644&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/8919393946893672644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/8919393946893672644'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2008/03/objektorientierte-programmierung-mit.html' title='Objektorientierte Programmierung mit MATLAB R2008a'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05611762638556486297</uri><email>thomas@dohmke.de</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08020833314722503912'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-413224808017673092</id><published>2008-03-01T17:25:00.001+01:00</published><updated>2008-03-01T17:25:09.603+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='version'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><title type='text'>R2008a</title><content type='html'>&lt;p&gt;Da habe ich wohl falsch &lt;a href="http://mllog.blogspot.com/2008/02/neues-simulink-blog-bei-mathworks.html"&gt;getippt&lt;/a&gt;, als ich vor ein paar Tage mutmaßte, dass das neue MATLAB-Release am Montag erscheint. Zwar funktioniert der Download heute erst ab 18:00 Uhr (EST), sprich 00:00 Uhr (MEZ), aber die neuen Features werden schon auf der Seite &lt;a href="http://www.mathworks.com/products/new_products/latest_features.html?s_cid=HP_RH_2008a"&gt;What's New In Release 2008a&lt;/a&gt; vorgestellt. Highlight aus meiner Sicht sind die neuen Fähigkeiten für &lt;a href="http://www.mathworks.com/products/matlab/object_oriented_programming.html"&gt;"state-of-the art object-oriented programming"&lt;/a&gt;. Endlich entfällt das umständliche Definieren von Klassen in separaten Verzeichnissen und das Verteilen der Methoden auf einzelne Dateien, mit "handle classes" können Parameter als Referenz übergeben werden und der MATLAB Desktop unterstützt das Erzeugen von Klassen durch ein Template. Sobald ich die neue Version ein wenig ausprobieren konnte, werde ich einen ausführlichen Artikel darüber schreiben, und mich dann an die Arbeit für Version 2.0 von &lt;a href="http://mlunit.dohmke.de"&gt;mlUnit&lt;/a&gt; machen. :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-413224808017673092?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/413224808017673092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=413224808017673092&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/413224808017673092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/413224808017673092'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2008/03/r2008a.html' title='R2008a'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05611762638556486297</uri><email>thomas@dohmke.de</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08020833314722503912'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-4835015127722437243</id><published>2008-02-27T20:55:00.001+01:00</published><updated>2008-04-11T22:59:38.913+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='simulink'/><title type='text'>Neues Simulink-Blog bei MathWorks</title><content type='html'>&lt;p&gt;Nicht mehr lange, dann müsste, wenn es nach dem &lt;a href="http://www.mathworks.com/products/new_products/release_model.html"&gt;Release Scedule&lt;/a&gt; von MathWorks geht, das nächste MATLAB-Release R2008a erscheinen (ich tippe mal auf den 03.03.2008, sofern sie in Massachusetts nicht auch samstags arbeiten). Jedenfalls ist gestern erstmal ein neues Blog veröffentlicht worden, &lt;a href="http://blogs.mathworks.com/seth/"&gt;Seth on Simulink&lt;/a&gt;, das sich offenbar mit Simulink beschäftigen wird. In seinem ersten Post &lt;a href="http://blogs.mathworks.com/seth/2008/02/26/welcome/"&gt;Welcome&lt;/a&gt; gibt er unter anderem einen Überblick über die kommenden Themen:&lt;/p&gt;

&lt;blockquote&gt;
solvers, sample times, modeling, hacks, blocks, model reference, libraries, masking, custom code
&lt;/blockquote&gt;

&lt;p&gt;"hacks" könnte ganz spannend werden, ansonsten fehlen mir ein wenig die Themen für Fortgeschrittene wie z.B. Codegenerierung. Und von Testen ist auch keine Rede...&lt;/p&gt; 
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-4835015127722437243?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/4835015127722437243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=4835015127722437243&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/4835015127722437243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/4835015127722437243'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2008/02/neues-simulink-blog-bei-mathworks.html' title='Neues Simulink-Blog bei MathWorks'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05611762638556486297</uri><email>thomas@dohmke.de</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08020833314722503912'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-6021898285890927477</id><published>2008-02-15T21:08:00.001+01:00</published><updated>2008-04-11T22:59:47.722+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testen'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='simulink'/><category scheme='http://www.blogger.com/atom/ns#' term='modellbasiert'/><title type='text'>slUnit: Der Testkontext</title><content type='html'>&lt;p&gt;Textkontexte ermöglichen die Wiederverwendung von gemeinsamen Code mehrerer Testmethoden. Gewöhnlich werden sie im Zusammenhang mit der Klasse TestCase verwendet, die jeweils einen Textkontext mit den zugehörigen Testmethoden kapselt. Das Ziel eines Textkontextes ist die Vermeidung von doppeltem Code. Zudem stellt er sicher, dass die Ausführung einer Testmethode unabhängig von der Ausführung anderer Testmethoden ist, speziell auch dann, wenn die Tests auf externe Ressourcen zugreifen. Der wichtigste Teil des Testkontexts sind daher Methoden zur Vor- und Nachbereitung (zum "Aufräumen") eines Tests.&lt;/p&gt; 

&lt;h4&gt;Konzept (xUnit)&lt;/h4&gt;

&lt;p&gt;Die xUnit-Familie sieht zwei Methoden für den Testkontext vor: set_up und tear_down. Der folgende Pseudocode zeigt zwei Beispieltestmethoden, die einen einfachen Schalter mit zwei Zuständen testen: Die Testmethode test_off prüft den ausgeschalteten Zustand (der Default-Zustand), die Testmethode test_on das Einschalten.&lt;/p&gt;

&lt;pre&gt;external ignition; 
var switch;
 
set_up() { 
  switch = new generic_switch(ignition); 
} 

test_off() { 
  assert_equals(false, switch.is_on()); 
} 

test_on() { 
  switch.on(); 
  assert_equals(true, switch.is_on()); 
} 

tear_down() { 
  switch.off(); 
}&lt;/pre&gt; 

&lt;p&gt;Eine Dopplung der Variable switch wird hier verhindert, indem diese bereits in set_up angelegt wird. Als Beispiel einer externen Ressource wird diese Variable mit der Zündung eines Autos verbunden, die im Beispiel durch den Bezeichner ignition angedeutet wird. Da test_on den Schalter und damit die Zündung einschaltet, muss nach der Ausführung dieser Testmethode der Schalter wieder ausgeschaltet werden. Ansonsten schlägt die Ausführung von test_off fehl, wenn diese nach test_on ausgeführt wird. Das Ergebnis von test_off wäre also nicht mehr unabhängig von test_on. Folglich wird der Schalter in tear_down ausgeschaltet, wobei xUnit sicherstellt, dass diese Methode stets nach einer Testmethode und unabhängig von deren Ergebnis ausgeführt wird (also auch, wenn die Testmethode selbst mit einem Fehler beendet wird).&lt;/p&gt;

&lt;h4&gt;Realisierung (slUnit)&lt;/h4&gt;

&lt;p&gt;In slUnit werden Textkontexte durch die Aggregation von Testfällen in einen Testverbund realisiert. Damit ist es möglich, gemeinsamen Code der Testfälle innerhalb des Testverbundes zu kapseln. Die Ausgänge eines Testfalls sind dann nicht länger nur die Eingänge des Testobjekts, sondern können auch mit dem gemeinsam genutzten Code verbunden werden, dessen Ausgänge wiederum die Eingänge des Testobjekts und/oder der Testfälle sein können. Der Testverbund in der &lt;a href="http://2.bp.blogspot.com/_iTIPRnSAGjA/R69ZGYKP_zI/AAAAAAAAAPo/F8S1K6199Z0/s1600-h/slunit_architecture.png"&gt;Abbildung&lt;/a&gt; im Artikel &lt;a href="http://mllog.blogspot.com/2008/02/slunit-tests-definieren-und-ausfhren.html"&gt;slUnit: Tests definieren und ausführen&lt;/a&gt; verwendet dieses Konzept.&lt;/p&gt;

&lt;p&gt;Das Herstellen und Auflösen eines Textkontextes, wie er durch die Methoden set_up und tear_down erreicht wird, ist für modellbasierten Code, d.h. Simulink-Blöcke, nicht notwendig. Die einzige Ausnahme stellt die Interaktion mit der MATLAB-Umgebung dar, beispielsweise durch das Verwenden von MATLAB-Variablen in Konstanten. Die Integrität des Textkontextes kann dafür durch die von Simulink bereitgestellten Callback-Funktionen StartFcn und StopFcn sichergestellt werden, typischerweise indem in StartFcn die Parameter aus einer Datei geladen und in StopFcn die geladenen Werte zurückgesetzt werden.&lt;/p&gt;

&lt;h4&gt;Weitere Artikel in der Reihe&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/06/slunit-schnellstart.html"&gt;slUnit: Schnellstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/07/slunit-zusicherungen-mit-dem-assert.html"&gt;slUnit: Zusicherungen mit dem Assert-Block&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2008/02/slunit-tests-definieren-und-ausfhren.html"&gt;slUnit: Tests definieren und ausführen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Fragen, Kommentare, Fehler&lt;/h4&gt;

&lt;p&gt;Bei Fragen, Kommentaren oder Fehlern bitte einfach eine E-Mail an &lt;a href="mailto:thomas@dohmke.de"&gt;thomas@dohmke.de&lt;/a&gt; senden oder einen Kommentar hier im Blog hinterlassen. Gewöhnlich antworte ich innerhalb von 24 Stunden. Spam und vergleichbarer Müll wird automatisch aussortiert, daher bitte einen aussagekräftigen Betreff, z.B. "Frage zu slUnit", verwenden.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-6021898285890927477?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/6021898285890927477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=6021898285890927477&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/6021898285890927477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/6021898285890927477'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2008/02/slunit-der-testkontext.html' title='slUnit: Der Testkontext'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05611762638556486297</uri><email>thomas@dohmke.de</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08020833314722503912'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-2727716394212515435</id><published>2008-02-10T21:00:00.002+01:00</published><updated>2008-04-12T15:07:16.974+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testen'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='simulink'/><category scheme='http://www.blogger.com/atom/ns#' term='modellbasiert'/><title type='text'>slUnit: Tests definieren und ausführen</title><content type='html'>&lt;p&gt;Die Art und Weise der Erstellung und Ausführung von Testfällen ist eine der wesentlichen Eigenschaften eines Testing Frameworks, da sich aus ihr die grundlegende Architektur ergibt. Dieser Artikel beschreibt die Darstellung eines Testfalls in xUnit als generisches Konzept und anschließend die Realisierung dieses Konzepts in slUnit.&lt;/p&gt;

&lt;h4&gt;Konzept (xUnit)&lt;/h4&gt;

Ein einzelner Testfall wird in xUnit durch eine Methode (&lt;a href="http://xunitpatterns.com/Test%20Method.html"&gt;Test Method&lt;/a&gt;) repräsentiert, deren Name mit "test" beginnt.  Mittels eines solchem designierten Namens ist es einer Instanz der Klasse &lt;a href="http://xunitpatterns.com/Test%20Runner.html"&gt;Test Runner&lt;/a&gt; möglich, alle auszuführenden Testmethoden zu lokalisieren. Alternativ können in modernen Programmiersprachen auch sogenannte &lt;a href="http://de.wikipedia.org/wiki/Java_%28Programmiersprache%29#Annotations"&gt;Annotations&lt;/a&gt; für diese Kennzeichnung verwendet werden, beispielsweise wird mit &lt;a href="http://de.wikipedia.org/w/index.php?title=Java_%28Technologie%29#Version_5.0"&gt;Java 5&lt;/a&gt; und &lt;a href="http://www.frankwestphal.de/JUnit4.0.html"&gt;JUnit 4&lt;/a&gt; eine Testmethode wie folgt definiert:&lt;/p&gt;

&lt;pre&gt;@Test public void emptyStack() {
    stack = new Stack&lt;String&gt;();
    assertTrue(stack.isEmpty());
}&lt;/pre&gt;

&lt;p&gt;Die Annotation @Test markiert hier die Methode emptyStack als eine Testmethode.&lt;/p&gt;

&lt;p&gt;Im Allgemeinen kann eine Testmethode eine beliebige Anzahl von Zusicherungen enthalten, die nacheinander geprüft werden. Die Testmethode schlägt fehl, sobald eine der Zusicherungen falsch ist. Alle nachfolgenden Zusicherungen werden dann nicht mehr 
ausgeführt, da diese üblicherweise voneinander abhängig sind, z.B.:&lt;/p&gt;

&lt;pre&gt;
assert_not_equals(0, foo(x));
assert(0 &lt; (1 / foo(x)));&lt;/pre&gt;

&lt;p&gt;Zudem kann eine Testmethode auch die strukturellen Fähigkeiten der jeweiligen Programmiersprache verwenden, beispielsweise if-Verzweigungen und while-Schleifen, und als Teil dieser Zusicherungen bedingt oder zyklisch ausführen.&lt;/p&gt;

&lt;p&gt;Typischerweise werden Testmethoden innerhalb von Klassen organisiert, da die meisten Testing Frameworks, die auf xUnit basieren, in einer objektorientieren Programmiersprache realisiert sind. Eine Klasse kapselt dabei solche Testmethoden, die sich denselben Testkontext teilen. Der Begriff Testkontext dient hier als Übersetzung des englischen Begriffes &lt;a href="http://xunitpatterns.com/test%20fixture%20-%20xUnit.html"&gt;Test Fixture&lt;/a&gt;; er beschreibt den Kontext, den die Testfälle zur Ausführung und zur Überprüfung der Zusicherungen voraussetzen. Die Basisklasse für Testmethoden wird &lt;a href="http://xunitpatterns.com/Testcase%20Class.html"&gt;Test Case&lt;/a&gt; genannt. Instanzen dieser Klasse werden in Objekten der Klasse &lt;a href="http://xunitpatterns.com/Test%20Suite%20Object.html"&gt;Test Suite&lt;/a&gt; zusammengefasst.&lt;/p&gt; 

&lt;p&gt;Für die Ausführung der Testfälle stellen die Mitglieder der xUnit-Familie verschiedene kommandozeilenbasierte oder grafische Anwendungen zur Verfügung, die alle von der Basisklasse Test Runner abgeleitet sind und dadurch eine einheitliche Schnittstelle realisieren. Die auszuführenden Tests können durch verschiedene Techniken ausgewählt werden:&lt;/p&gt;

&lt;dl&gt;
&lt;dt&gt;Aufzählung (Enumeration)&lt;/dt&gt;
&lt;dd&gt;Jede Testmethode wird manuell hinzugefügt, in dem der Konstruktor der Testklasse mit dem Namen der Testmethode aufgerufen und so die Klasse instanziiert wird. Damit ist es außerdem möglich, nur eine einzige Testmethode als Test auszuführen.&lt;/dd&gt;
&lt;dt&gt;Auffindung (Discovery)&lt;/dt&gt;
&lt;dd&gt;Die Testmethoden werden automatisch durch den Test Runner ermittelt, in dem die obige Namenskonvention oder Annotations verwendet werden.&lt;/dd&gt;
&lt;dt&gt;Auswahl (Selection)&lt;/dt&gt;
&lt;dd&gt;Als Ergänzung zur letzten Technik werden dem Test Runner zusätzliche Kriterien zur Auswahl der Testmethoden übergeben, so dass eine Untermenge der Tests ausgeführt wird. Solche Kriterien basieren üblicherweise auf spezifischen Annotations für die Testklassen oder Testmethoden.&lt;/dd&gt;
&lt;/dl&gt;

&lt;h4&gt;Realisierung (slUnit)&lt;/h4&gt;

&lt;p&gt;Das Design von slUnit setzt diese klassenbasierte Architektur von xUnit um, in dem sowohl das Testobjekt als auch die Testfälle als Simulink-Subsysteme repräsentiert werden. Ein Subsystem für eine Testmethode wird mit einem spezifischen &lt;a href="www.mathworks.com/access/helpdesk/help/toolbox/simulink/ug/f8-19907.html"&gt;Mask-Type&lt;/a&gt; markiert, um es von anderen Subsystemen zu unterscheiden. Der Mask-Type ist ein Attribut, das Subsysteme in Simulink markiert. Man kann es mit den Annotations vergleichen, die in anderen xUnit-Frameworks verwendet werden. Neben Testmethoden werden auch die Klassen Test Case und Test Suite durch Subsysteme dargestellt. Tatsächlich gibt es zwischen diesen beiden Typen keine Unterschiede, so dass das zugehörige Subsystem nachfolgend als Testverbund (Test Composite) bezeichnet wird. Ein Testverbund beinhaltet mindestens ein weiteres Subsystem, das entweder eine Testmethode oder wiederrum ein Testverbund ist. Auch das Simulink-Modell selbst wird als Testverbund betrachtet, allerdings mit der Besonderheit, dass dieses auch das Testobjekt enthält. Die nachfolgende Abbildung zeigt die entsprechende Architektur eines slUnit-Modells.&lt;/p&gt;

&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_iTIPRnSAGjA/R69ZGYKP_zI/AAAAAAAAAPo/F8S1K6199Z0/s1600-h/slunit_architecture.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_iTIPRnSAGjA/R69ZGYKP_zI/AAAAAAAAAPo/F8S1K6199Z0/s320/slunit_architecture.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5165445263716777778" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Die Tests werden nun ausgeführt, indem das Simulink-Modell simuliert wird. Während der Simulation werden die Signale und Zustände des Modells für eine Anzahl von Zeitschritten berechnet werden. Eine einzelne Simulation entspricht der Ausführung eines einzelnen Testfalls. Da das Modell mehrere Testfälle enthält, muss sichergestellt werden, dass nur die Assert-Blöcke der jeweils aktiven Testmethode ihre Zusicherungen überprüfen. Alle anderen Assert-Blöcke sollen automatisch deaktiviert werden. Diese Funktionalität wird durch den Multiplexer-Block realisiert, der daher als das wichtigste Element des slUnit-Frameworks angesehen wird. Er aktiviert die Assert-Blöcke, die sich im Subsystem der aktiven Testmethode befinden, und deaktiviert alle anderen Assert-Blöcke. Zudem verbindet er den Ausgang der Testmethode mit dem Eingang des Testobjekts. Wie in der obigen Abbildung dargestellt, beinhaltet jeder Testverbund besitzt genau einen Multiplexer-Block. Dieser muss nicht zwangsläufig den Ausgang des Subsystems darstellen, sondern kann auch mit weiteren Subsystemen verbunden sein, die gemeinsame Funktionalitäten ("Common Code") aller vom Multiplexer berücksichtigen Testfälle beinhaltet.&lt;/p&gt;

&lt;p&gt;Wie bereits erwähnt, wird ein einzelner Testfall durch Starten der Simulation ausgeführt. Sollen indes mehrere Testfälle ausgeführt werden, kann dies ähnlichen wie bei xUnit realisiert werden. Einerseits beinhaltet jeder Testverbund einen Button "Run All", der alle zugehörigen Testfälle ausführt. Andererseits können die Testfälle mit zusätzlichen Blöcken versehen werden, die über keine eigentliche Funktion verfügen, sondern den Testfall lediglich über den Namen des Blocks und/oder dessen Farbe markieren. Ein solcher Block stellt eine Art Annotation. Durch Doppelklick des Blocks können dann alle Testfälle ausgeführt werden, die einen gleichen Block enthalten. Damit ist eine Bildung von Gruppen von Testfällen möglich, die orthogonal zur Hierachie aus Testfällen und Testverbünden steht.&lt;/p&gt;  

&lt;p&gt;Das Testergebnis wird als Hintergrundfarbe des Subystems einer Testmethode dargestellt. Dieser Hintergrundfarbe wird von der Hintergrundfarbe und damit den Ergebnissen der Assert-Blöcke geerbt. D.h. die Hintergrundfarbe wird auf rot gesetzt, wenn mindestens eine Zusicherung fehlgeschlagen ist. In gleicher Art und Weise wird die Hintergrundfarbe des Subsystems eines Testverbunds aus den Ergebnissen aller enthaltenen Testfälle gebildet.&lt;/p&gt;

&lt;h4&gt;Weitere Artikel in der Reihe&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/06/slunit-schnellstart.html"&gt;slUnit: Schnellstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/07/slunit-zusicherungen-mit-dem-assert.html"&gt;slUnit: Zusicherungen mit dem Assert-Block&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2008/02/slunit-tests-definieren-und-ausfhren.html"&gt;slUnit: Tests definieren und ausführen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2008/02/slunit-der-testkontext.html"&gt;slUnit: Der Textkontext&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Fragen, Kommentare, Fehler&lt;/h4&gt;

&lt;p&gt;Bei Fragen, Kommentaren oder Fehlern bitte einfach eine E-Mail an &lt;a href="mailto:thomas@dohmke.de"&gt;thomas@dohmke.de&lt;/a&gt; senden oder einen Kommentar hier im Blog hinterlassen. Gewöhnlich antworte ich innerhalb von 24 Stunden. Spam und vergleichbarer Müll wird automatisch aussortiert, daher bitte einen aussagekräftigen Betreff, z.B. "Frage zu slUnit", verwenden.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-2727716394212515435?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/2727716394212515435/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=2727716394212515435&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/2727716394212515435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/2727716394212515435'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2008/02/slunit-tests-definieren-und-ausfhren.html' title='slUnit: Tests definieren und ausführen'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05611762638556486297</uri><email>thomas@dohmke.de</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08020833314722503912'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_iTIPRnSAGjA/R69ZGYKP_zI/AAAAAAAAAPo/F8S1K6199Z0/s72-c/slunit_architecture.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-6642278350129630634</id><published>2007-12-27T20:54:00.000+01:00</published><updated>2007-12-27T21:06:05.306+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><title type='text'>Jahresabschluss 2007</title><content type='html'>&lt;p&gt;Das Jahr 2007 neigt sich dem Ende zu. Es war relativ still zuletzt hier, in diesem, meinem MATLAB Blog. Dies war im Wesentlichen der Arbeit an meiner Dissertation geschuldet, die ich endlich fertigstellen wollte. Tatsächlich stehe ich kurz vor der Vollendung, die Arbeiten am zweiten Release Candidate sind so gut wie abgeschlossen. Wenn also alles klappt, werde ich im Januar 2008 hier wieder regelmäßig schreiben, insbesondere um diese beiden Artikelreihen fertigzustellen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/09/slunit-mehrere-modelle-automatisch.html"&gt;slUnit: Mehrere Modelle automatisch testen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/06/slunit-die-verschmelzung-der.html"&gt;slUnit: Modellbasierte und testgetriebene Entwicklung verschmelzen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Geplant sind außerdem neue Versionen für mlUnit und slUnit, und wenn dann die Zeit noch reicht (und es nicht schon wieder Zeit für den Jahresabschluß 2008 ist), erblicken vielleicht auch noch ein oder zwei neue Projekte das Licht der Welt.&lt;/p&gt;

&lt;p&gt;In diesem Sinne: Guten Rutsch. :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-6642278350129630634?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/6642278350129630634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=6642278350129630634&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/6642278350129630634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/6642278350129630634'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/12/jahresabschluss-2007.html' title='Jahresabschluss 2007'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05611762638556486297</uri><email>thomas@dohmke.de</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='08020833314722503912'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-2085913923732040654</id><published>2007-09-11T19:43:00.000+02:00</published><updated>2008-04-11T23:00:01.495+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='funktion'/><category scheme='http://www.blogger.com/atom/ns#' term='testen'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='simulink'/><title type='text'>slUnit: Mehrere Modelle automatisch testen, Teil II</title><content type='html'>&lt;p&gt;Der erste und &lt;a href="http://mllog.blogspot.com/2007/06/slunit-mehrere-modelle-automatisch.html"&gt;ursprüngliche Artikel&lt;/a&gt; zu diesem Thema stellte einen Ansatz dar, wie man mit &lt;a href="http://slunit.dohmke.de/"&gt;slUnit&lt;/a&gt; mehrere Modelle automatisiert testen kann. Der Artikel schloss mit einer Aufzählung von Nachteilen, die in diesem zweiten Teil ausgebessert werden sollen.&lt;/hallo&gt;&lt;/p&gt;

&lt;p&gt;Zunächst &lt;a href="http://de.wikipedia.org/wiki/Refactoring"&gt;refactorn&lt;/a&gt; wir den erstellten &lt;a href="http://mlunit.dohmke.de/doc/mlunit/api/1.5.1/src/@function_test_case/function_test_case.html"&gt;function_test_case&lt;/a&gt; mit Name slunit_runner (siehe &lt;a href="http://mllog.blogspot.com/2007/06/slunit-mehrere-modelle-automatisch.html"&gt;Teil I&lt;/a&gt;) in eine Klasse slunit_test_case um.&lt;/p&gt;
&lt;pre&gt;
function self = slunit_test_case(varargin)

if (nargin == 1)
  self.sys_name = varargin{1};
end;
parent = test_case('run_test');
self = class(self, 'slunit_test_case', parent);
&lt;/pre&gt;
&lt;p&gt;Als Argument erwartet der Konstruktor den Namen des zu testenden Simulink-Modells, d.h. slUnit-Testbetts. Die Funktionen set_up, tear_down und run_test werden direkt übernommen und als einzelne Dateien gespeichert. Zusätzlich kommmt eine Funktion str hinzu, die den Namen des Simulink-Modells als Namen des Testfalls ausgibt:&lt;/p&gt;
&lt;pre&gt;
function s = str(self)

s = strrep(char(which(self.sys_name)), '\', '/');
&lt;/pre&gt;
&lt;p&gt;Angenommen, wir haben ein slUnit-Testbett test_save_min.mdl mit mehreren Testfällen, von denen einer fehlschlägt, so können wir dieses Testbett nun wie folgt ausführen:&lt;/p&gt;
&lt;pre&gt;
&gt;&gt; run(text_test_runner, slunit_test_case('test_save_min'));
======================================================================
FAIL: s:/temp/test_save_min.mdl
----------------------------------------------------------------------
Traceback (most recent call first):
In c:\projects\temp\slunit_runner.289\@slunit_test_case\run_test.m at line 5
In c:\projects\utils\mlunit\src\@test_case\run.m at line 38
In c:\projects\utils\mlunit\src\@text_test_runner\run.m at line 31
AssertionError: Tests of model test_save_min.mdl failed.
----------------------------------------------------------------------
Ran 1 test in 8.903s

FAILED (errors=0, failures=1)
&lt;/pre&gt;
&lt;p&gt;Immerhin wird nun gegenüber der ersten Lösung schon mal der Name des Simulink-Modells hinter "FAIL:" ausgegeben.&lt;/p&gt;
&lt;p&gt;Im nächsten Schritt soll statt der Textausgabe ein HTML-Bericht erzeugt werden. Dazu erstellen wir eine neue Klasse slunit_test_result, die von der &lt;a href="http://mlunit.dohmke.de/"&gt;mlUnit&lt;/a&gt;-Klasse &lt;a href="http://mlunit.dohmke.de/doc/mlunit/api/1.5.1/src/@test_result/index.html"&gt;test_result&lt;/a&gt; abgeleitet ist.&lt;/p&gt;
&lt;pre&gt;
function self = slunit_test_result(filename)

self.filename = filename;
self.stream = fopen(filename, 'w+');
self.slunit_failed = 0;
result = test_result();
self = class(self, 'slunit_test_result', result);

fprintf(self.stream, '&amp;lt;!DOCTYPE html PUBLIC [..]&gt;');
fprintf(self.stream, '&amp;lt;html xmlns=''http://www.w3.org/1999/xhtml''&gt;');
fprintf(self.stream, '&amp;lt;head&gt;&amp;lt;title&gt;slUnit Test Report&amp;lt;/title&gt;&amp;lt;/head&gt;');
fprintf(self.stream, '&amp;lt;body&gt;');
fprintf(self.stream, '&amp;lt;h1&gt;slUnit Test Report&amp;lt;/h1&gt;');
&lt;/pre&gt;
&lt;p&gt;Als Argument erwartet der Konstruktor den gewünschten Dateinamen des Berichts. Diese Datei wird dann initial erzeugt und das Handle in der Variable self.stream gespeichert. Als nächstes überschreiben wir die Methoden start_test,&lt;/p&gt;
&lt;pre&gt;
function self = start_test(self, test)

self.test_result = start_test(self.test_result, test);
self.slunit_failed = 0;

fprintf(self.stream, '&amp;lt;hr /&gt;');
fprintf(self.stream, ...
  '&amp;lt;h2&gt;Model: &amp;lt;a href="matlab:open_system(''%s'')"&gt;%s&amp;lt;/a&gt;&amp;lt;/h2&gt;', ...
  str(test), ...
  str(test));
clk = clock();
fprintf(self.stream, '&amp;lt;p&gt;Execution Time: %02d.%02d.%d %02d:%02d&amp;lt;/p&gt;', ...
  clk(3), clk(2), clk(1), clk(4), clk(5));
&lt;/pre&gt;
&lt;p&gt;stop_test,&lt;/p&gt;
&lt;pre&gt;
function self = stop_test(self, test)

self.test_result = stop_test(self.test_result, test);

fprintf(self.stream, '&amp;lt;h3&gt;Result&amp;lt;/h3&gt;');
if (self.slunit_failed)
  fprintf(self.stream, '&amp;lt;p&gt;At least one test failed.&amp;lt;/p&gt;');
else
  fprintf(self.stream, '&amp;lt;p&gt;All test passed.&amp;lt;/p&gt;');
end;
fprintf(self.stream, '&amp;lt;hr /&gt;');
&lt;/pre&gt;
&lt;p&gt;add_error,&lt;/p&gt;
&lt;pre&gt;
function self = add_error(self, test, error)

self.test_result = add_error(self.test_result, test, error);
self.slunit_failed = 1;
&lt;/pre&gt;
&lt;p&gt;und add_failure:&lt;/p&gt;
&lt;pre&gt;
function self = add_failure(self, test, failure)

self.test_result = add_failure(self.test_result, test, failure);
self.slunit_failed = 1;
&lt;/pre&gt;
&lt;p&gt;Diese Funktionen werden automatisch von der &lt;a href="http://mlunit.dohmke.de/doc/mlunit/api/1.5.1/src/@test_case/run.html"&gt;run&lt;/a&gt;-Funktion von &lt;a href="http://mlunit.dohmke.de/doc/mlunit/api/1.5.1/src/@test_case/index.html"&gt;test_case&lt;/a&gt; aufgerufen, und zwar immer dann, wenn ein Test gestartet oder gestoppt wird sowie ein Fehler aufgetreten ist. Zusätzlich wird in einer weiteren Funktion, finish, das Handle der Datei geschlossen:&lt;/p&gt;
&lt;pre&gt;
function self = finish(self)

fprintf(self.stream, '');
fprintf(self.stream, '');
fclose(self.stream);
&lt;/pre&gt;
&lt;p&gt;Mit Hilfe dieser Klasse können wir nun eine neue Funktion zum Ausführen der Tests schreiben, genannt slunit_test_runner:&lt;/p&gt;
&lt;pre&gt;
function slunit_test_runner

result = slunit_test_result('report.html');

suite = test_suite();
suite = add_test(suite, slunit_test_case('test_save_min'));
suite = add_test(suite, slunit_test_case('test_save_max'));

[suite, result] = run(suite, result); %#ok
finish(result);
web('report.html');
&lt;/pre&gt;
&lt;p&gt;Die Funktion kann direkt aus dem Editor mittels F5 ausgeführt werden, sie startet den Test der Modelle test_save_max.mdl sowie test_save_min.mdl und ruft anschließend den Bericht im MATLAB-eigenen Webbrowser auf. Die ausgeführten Modelle lassen sich per Link direkt in Simulink öffnen, und da diese nach der Ausführung der Tests gespeichert wurden, zeigt die Hintergrundfarbe der Tests innerhalb des Modells deren jeweiliges Ergebnis.&lt;/p&gt;
&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_QnyNXJ2dLNc/RubbtXXcaJI/AAAAAAAAAB0/zCPTImRXNrY/s1600-h/slunit_test_report.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_QnyNXJ2dLNc/RubbtXXcaJI/AAAAAAAAAB0/zCPTImRXNrY/s200/slunit_test_report.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5109012399711348882" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Will man das Aussehen des Berichts an die eigenen Bedürfnisse anpassen, kann man dies leicht in start_test und stop_test erreichen. Zum Beispiel wird durch folgende Modifikation von stop_test das Ergebnis mit farbigem Hintergrund ausgegeben:&lt;/p&gt;
&lt;pre&gt;
function self = stop_test(self, test)

self.test_result = stop_test(self.test_result, test);

fprintf(self.stream, '&amp;lt;h3&gt;Result&amp;lt;/h3&gt;');
if (self.slunit_failed)
    fprintf(self.stream, '&amp;lt;p style="background: #ffcccc;"&gt;At least one test failed.&amp;lt;/p&gt;');
else
    fprintf(self.stream, '&amp;lt;p style="background: #ccffcc;&gt;All test passed.&amp;lt;/p&gt;');
end;
fprintf(self.stream, '&amp;lt;hr /&gt;');
&lt;/pre&gt;
&lt;p&gt;Nicht so einfach ist es hingegen, das angezeigte Ergebnis von test_save_min.mdl zu verändern: "At least one test failed." Die Beschreibung "at least" deutet schon daraufhin, dass wir mit der derzeitigen Implementierung nicht genau wissen, wieviele der Tests innerhalb des slUnit-Testbetts fehlgeschlagen sind. Abhilfe schafft eine Schnittstelle zwischen slunit_test_case und slunit_test_result, aber dazu mehr in Teil III (mit dem auch alle Dateien zum Herunterladen veröffentlicht werden).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-2085913923732040654?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/2085913923732040654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=2085913923732040654&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/2085913923732040654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/2085913923732040654'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/09/slunit-mehrere-modelle-automatisch.html' title='slUnit: Mehrere Modelle automatisch testen, Teil II'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_QnyNXJ2dLNc/RubbtXXcaJI/AAAAAAAAAB0/zCPTImRXNrY/s72-c/slunit_test_report.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-4961890053534872680</id><published>2007-07-14T15:55:00.001+02:00</published><updated>2008-04-11T23:00:07.225+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testen'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='simulink'/><category scheme='http://www.blogger.com/atom/ns#' term='modellbasiert'/><title type='text'>slUnit: Zusicherungen mit dem Assert-Block</title><content type='html'>&lt;p&gt;Die &lt;a href="http://de.wikipedia.org/wiki/Assertion"&gt;Zusicherung&lt;/a&gt; (engl.: assertion) ist das grundlegende Element für das automatisierte Testen, da durch ihre Auswertung bestimmt wird, ob ein Test fehlgeschlagen ist oder nicht. Die Auswertung erfolgt dabei üblicherweise durch den Vergleich von Erwartungswerten mit den Ausgangswerten des Testobjekts.&lt;/p&gt;

&lt;h4&gt;Konzept (xUnit)&lt;/h4&gt;

&lt;p&gt;Die meisten &lt;a href="http://de.wikipedia.org/wiki/Framework"&gt;Frameworks&lt;/a&gt; der &lt;a href="http://xunitpatterns.com"&gt;xUnit&lt;/a&gt;-Familie bieten eine Grundmenge an eingebauten Methoden für Zusicherungen, die sich in folgende Gruppen einteilen lassen:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Konstante Zusicherungen&lt;/dt&gt;
&lt;dd&gt;Diese, im Englischen als &lt;a href="http://xunitpatterns.com/Assertion%20Method.html#Single%20Outcome%20Assertion"&gt;Single Outcome Assertion&lt;/a&gt; bezeichnete Zusicherung, führt stets zum gleichen Ergebnis, d.h. sie verfügt über keine Eingänge, die ihr Verhalten beeinflussen. Ihr Ziel ist es, entweder einen unfertigen Test fehlschlagen zu lassen oder innerhalb des &lt;em&gt;try&lt;/em&gt;-Zweiges eines &lt;em&gt;try/catch&lt;/em&gt;-Blockes eine fehlende erwartete Ausnahme (engl.: exception) zu erkennen. Der einzige Parameter einer solchen Funktion ist - wie bei allen Zusicherungsmethoden - eine Fehlermeldung, die im Testergebnis gespeichert und nach der Ausführung aller Tests angezeigt wird. Beispiel:
&lt;pre&gt;
fail('Test unvollständig.');
&lt;/pre&gt;
&lt;/dd&gt;

&lt;dt&gt;Variable Zusicherungen&lt;/dt&gt;
&lt;dd&gt;Die variable Zusicherung verarbeitet im Gegensatz zur konstanten Zusicherung einen Parameter, der aussagt, ob die Zusicherung erfüllt wird oder nicht. Im Englischen wird von der &lt;a href="http://xunitpatterns.com/Assertion%20Method.html#Stated%20Outcome%20Assertion"&gt;Stated Outcome Assertion&lt;/a&gt; gesprochen. Weit verbreitet ist die Variante mit einem booleschen Parameter, z.B.&lt;/p&gt;
&lt;pre&gt;
assert(y &gt; foo(x));
&lt;/pre&gt;
&lt;p&gt;wobei y hier den Erwartungswert und foo(x) die zu testende Funktion darstellt. Diese Zusicherung schlägt fehl, wenn das Ergebnis von foo(x) kleiner oder gleich dem Wert von y ist, d.h. der boolesche Ausdruck nicht wahr ist.
&lt;/dd&gt;

&lt;dt&gt;Vergleichende Zusicherungen&lt;/dt&gt;
&lt;dd&gt;Diese Art von Zusicherungen (engl.: &lt;a href="http://xunitpatterns.com/Assertion%20Method.html#Equality%20Assertion"&gt;Equality Assertions&lt;/a&gt;) vergleichen zwei Eingangsparameter - den Erwartungswert und den Ausgangswert des Testobjekts - miteinander und werden erfüllt, wenn der definierte Vergleich zutrifft. Der Vergeichsoperator wird üblicherweise durch den Namen der Funktion spezifiziert, z.B. vergleicht&lt;/p&gt;
&lt;pre&gt;
assert_equals(y, foo(x));
&lt;/pre&gt; 
&lt;p&gt;ob die Werte von y und foo(x) exakt gleich sind. Die Idee hinter einer solch spezialisierten Zusicherung ist, eine hilfreichere Fehlermeldung als bei den beiden anderen Arten von Zusicherungen auszugeben. Nehmen wir an, der Wert von y ist 2 und die Funktion foo(x) liefert als Ergebnis 3 zurück, so würde automatisch folgende Fehlermeldung erzeugt werden (mit einem xUnit-Framework, welches über eine deutsche Lokalisierung verfügt):&lt;/p&gt;
&lt;pre&gt;
Erwarteter Wert ist &lt;2&gt;, aber das Ergebnis lautete &lt;3&gt;.
&lt;/pre&gt;
&lt;p&gt;Weiterhin erlaubt ein optionaler dritter Parameter, eine Toleranz zu spezifizieren, z.B. wird die folgende Zusicherung erfüllt, wenn das Ergebnis von sqrt(2) größer oder gleich 1.40 und kleiner oder gleich 1.42 ist:&lt;/p&gt;
&lt;pre&gt;
assert_equals(1.41, sqrt(2), 0.01);
&lt;/pre&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Komplexere Zusicherungen können gewöhlich mit Hilfe der Konstrukte der jeweiligen Programmiersprache erzeugt werden. Das Ziel solcher benutzerdefinierten Zusicherungen ist die Vermeidung von Dopplungen (Duplikate) durch wiederverwendeten Quelltext und von verschachtelten Logikausdrücken.&lt;/p&gt;
&lt;p&gt;Wird eine Zusicherung nicht erfüllt, so wird die Ausführung der jeweiligen Testmethode an der Stelle der Zusicherung abgebrochen, d.h. der nachfolgende Quelltext wird nicht mehr ausgeführt. Nicht abgebrochen wird hingegen die Ausführung der nachfolgenden Testmethoden, da diese mit xUnit stets unabhängig voneinander sind. Wenn alle Zusicherungen eines Tests erfüllt wurden, wird auch der Test als erfüllt betrachtet und üblicherweise durch einen grünen Fortschrittsbalken symbolisiert. Schlägt hingegen eine Zusicherung fehl, so schlägt auch der Test fehl und der Fortschrittsbalken wechselt zu einer roten Farbe. Diese Farbe wird beibehalten, unabhängig davon, ob weitere Tests erfüllt werden oder nicht. D.h. nach der Ausführung aller Tests lässt sich allein durch die Farbe des Fortschrittsbalkens ablesen, ob alle Tests erfolgreich waren (grün) oder nicht (rot). Zusammen mit einem roten Balken wird dann eine Liste von Fehlern ausgegeben, die je nach verwendeter Zusicherung den Erwartungswert, den Ausgangswert, die Zeile des Fehlers oder auch den optionalen Fehlertext enthält. Dadurch ist der Entwickler relativ leicht in der Lage, an die entsprechende Stelle im Code zu springen und das Problem zu analysieren.&lt;/p&gt;

&lt;h4&gt;Realisierung (slUnit)&lt;/h4&gt;

&lt;p&gt;Mit slUnit wird die Zusicherung durch den Assert-Block umgesetzt. Dieser hat einen booleschen Eingang vergleichbar zur Methode assert, der beschreibt ob die Zusicherung erfüllt wird - der boolesche Eingang ist wahr - oder nicht - der boolesche Eingang ist falsch. Der Zustand der Zusicherung wird durch die Hintergrundfarbe des Blocks dargestellt - grün für Erfolg, rot für Fehlschlag. Dies erlaubt einerseits die Auswertung des Tests, ohne das eine grafische Benutzeroberfläche oder eine Ausgabe auf der Kommandozeile notwendig ist, andererseits ist es so sehr einfach die fehlgeschlagenen Zusicherungen im grafischen Modell zu lokalisieren.&lt;/p&gt;
&lt;p&gt;Im Gegensatz zu den Zusicherungen von xUnit soll der Assert-Block das zeitabhängige Verhalten seines Eingangssignals berücksichtigen. Eine Zusicherung durch den Assert-Block schlägt fehl, wenn dessen Eingangssignal den booleschen Wert falsch annimmt, und bleibt in diesem Zustand für die restliche Zeit des Tests, ohne jedoch die Testausführung anzuhalten. Dadurch sind die Zusicherungen eines slUnit-Tests unabhängig voneinander, was typisch für Simulink-basierte Test ist, da sie meist das Verhalten verschiedener Signale analysieren. Falls dennoch Zusicherungen benötigt werden, die nacheinander zu prüfen sind, kann dies durch zusätzliche Simulink-Blöcke wie beispielsweise Enabled-Subsysteme erfolgen.&lt;/p&gt;
&lt;p&gt;Eine Erweiterung des Assert-Blocks ist der Assert-State-Change-Block - die Zusicherung eines Zustandswechsels. Der Block evaluiert, ob sein Eingangssignal während der Simulation von einem Wert x auf einen Wert y wechselt. Der Unterschied zwischen beiden Blöcken ist, dass der Assert-State-Change-Block solange nicht fehlschlagen kann, bis die Simulation beendet ist, da vorher nicht bewiesen ist, dass der Zustandswechsel nicht doch noch stattfinden wird. Die folgende Abbildung zeigt die Unterschiede zwischen beiden Blöcken anhand von verschiedenen statischen und dynamischen Eingangswerten.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QnyNXJ2dLNc/RpjogYn_YzI/AAAAAAAAABs/YO91xMIihbo/s1600-h/slunit_assertions.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_QnyNXJ2dLNc/RpjogYn_YzI/AAAAAAAAABs/YO91xMIihbo/s200/slunit_assertions.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5087071422178616114" /&gt;&lt;/a&gt;

&lt;p&gt;Ein vergleichbarer Block zur Methode assert_equals ist in slUnit nicht enthalten, u.a. weil der Vergleich zweier zeitabhängiger Signale in den meisten Fällen ungleich komplizierter als der Fall a = b ist. Stattdessen wird mit dem Propagate-Block eine Möglichkeit zur Verfügung gestellt, das kumulierte Ergebnis aller Assert-Blöcke eines Subsystems auf dessen Hintergrundfarbe zu propagieren. D.h. schlägt eine oder mehrere Zusicherungen eines Subsystems fehl, wird die Hintergrundfarbe des Subsystem-Blocks durch den Propagate-Block rot, sind alle Zusicherungen erfüllt wird sie grün. Damit ist es möglich, benutzerdefinierte Zusicherungen zu erstellen, die auf den beiden Grundblöcken - Assert und Assert-State-Change - und allen anderen Simulink-Blöcken aufbauen können. Die nachfolgende Abbildung zeigt eine Beispielzusicherung, die prüft, ob das Eingangssignal y innerhalb der definierten Grenzen h und l liegt.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QnyNXJ2dLNc/RpjntYn_YyI/AAAAAAAAABk/48YHT7iqRDA/s1600-h/slunit_user_assert.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_QnyNXJ2dLNc/RpjntYn_YyI/AAAAAAAAABk/48YHT7iqRDA/s200/slunit_user_assert.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5087070546005287714" /&gt;&lt;/a&gt;

&lt;h4&gt;Weitere Artikel in der Reihe&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/06/slunit-schnellstart.html"&gt;slUnit: Schnellstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2008/02/slunit-tests-definieren-und-ausfhren.html"&gt;slUnit: Tests definieren und ausführen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2008/02/slunit-der-testkontext.html"&gt;slUnit: Der Textkontext&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Fragen, Kommentare, Fehler&lt;/h4&gt;

&lt;p&gt;Bei Fragen, Kommentaren oder Fehlern bitte einfach eine E-Mail an &lt;a href="mailto:thomas@dohmke.de"&gt;thomas@dohmke.de&lt;/a&gt; senden oder einen Kommentar hier im Blog hinterlassen. Gewöhnlich antworte ich innerhalb von 24 Stunden. Spam und vergleichbarer Müll wird automatisch aussortiert, daher bitte einen aussagekräftigen Betreff, z.B. "Frage zu slUnit", verwenden.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-4961890053534872680?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/4961890053534872680/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=4961890053534872680&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/4961890053534872680'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/4961890053534872680'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/07/slunit-zusicherungen-mit-dem-assert.html' title='slUnit: Zusicherungen mit dem Assert-Block'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_QnyNXJ2dLNc/RpjogYn_YzI/AAAAAAAAABs/YO91xMIihbo/s72-c/slunit_assertions.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-4375314460822994259</id><published>2007-06-29T21:03:00.001+02:00</published><updated>2008-04-11T23:00:13.904+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='funktion'/><category scheme='http://www.blogger.com/atom/ns#' term='testen'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='simulink'/><title type='text'>slUnit: Mehrere Modelle automatisch testen, Teil I</title><content type='html'>&lt;p&gt;Unlängst erreichte mich die Frage, ob es mit slUnit auch möglich ist, mehr als ein Modell automatisiert zu testen. Die Antwort ist: nicht direkt. :) Während es relativ einfach ist, alle Tests eines Testbetts mittels dem "RunAll"-Button auszuführen, können nicht zwei Modelle mit den Bordmitteln von slUnit automatisch hintereinander gestartet werden. Abhilfe schafft der Befehl &lt;a href="http://mlunit.sourceforge.net/doc/slunit/api/1.0/src/slunit_start.html"&gt;slunit_start&lt;/a&gt;, der drei Parameter akzeptiert:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;den Namen des Subsystems,&lt;/li&gt;
&lt;li&gt;einen Modus: 0 für alle Tests, 1 für eine Liste von Tests, 2 für das geöffnete Subsystem, und&lt;/li&gt;
&lt;li&gt;eine Liste von Tests für die Modi 1 und 2.&lt;/li&gt;
&lt;/ul&gt;
Angenommen, man hat zwei Testbetten, "test_sample1.mdl" und "test_sample2.mdl", könnte man beide mitsamt aller Tests hintereinander mit folgender m-Funktion testen:
&lt;pre&gt;function slunit_runner

open_system('test_sample1.mdl');
slunit_start('test_sample1.mdl', 0);
close_system('test_sample1.mdl', 1);

open_system('test_sample2.mdl');
slunit_start('test_sample2.mdl', 0);
close_system('test_sample2.mdl', 1);&lt;/pre&gt;
Dieser Ansatz hat den Nachteil, dass bei einem Fehler während der Tests des ersten Testbetts, die Tests des zweiten Testbetts niemals ausgeführt werden. Außerdem erinnert die Funktion stark an das, was sich bei xUnit &lt;a href="http://xunitpatterns.com/test%20fixture%20-%20xUnit.html"&gt;Fixture&lt;/a&gt; nennt (sinngemäßg ins Deutsche übersetzt: Testkontext). Ein solcher Kontext beinhaltet alle für die Ausführung des Tests notwendigen Dinge und verhindert unter anderem Dopplungen im Code, in unserem Beispiel beispielsweise die Abfolge open_system, slunit_start und close_system, die bis auf den jeweils ersten Parameter identisch für beide Modelle ist. Diese Aufgabe kann &lt;a href="http://mllog.blogspot.com/2007/04/unit-tests-mit-matlab-und-mlunit.html"&gt;mlUnit&lt;/a&gt; für uns erledigen, und zwar im einfachsten Fall mit einem &lt;a href="http://mlunit.dohmke.de/doc/mlunit/api/1.5.1/src/@function_test_case/function_test_case.html"&gt;function_test_case&lt;/a&gt;:
&lt;pre&gt;function suite = slunit_runner

   function set_up(sys)
      
       open_system(sys);

   end

   function run_test(sys)

       slunit_start(sys, 0);
       failed = slunit_get_failed(sys);
       assert_equals(0, failed, sprintf('Tests of model %s.mdl failed.', sys));

   end

   function tear_down(sys)

       save_system(sys);
       close_system(sys);
      
   end

   function handle = make_test(sys)
      
       handle = function_test_case(@() run_test(sys), ...
           @() set_up(sys), ...
           @() tear_down(sys));
      
   end

   suite = test_suite;
   suite = set_name(suite, 'slunit_runner');
   suite = add_test(suite, make_test('sample1'));
   suite = add_test(suite, make_test('sample2'));

end
&lt;/pre&gt;
Das Vorgehen ist eigentlich ganz einfach. Zunächst wird eine &lt;a href="http://mlunit.dohmke.de/doc/mlunit/api/1.5.1/src/@test_suite/test_suite.html"&gt;test_suite&lt;/a&gt; erzeugt, die für jedes slUnit-Testbett einen function_test_case aufnimmt. Diese werden wiederum durch die Funktion make_test erzeugt, welche die lokalen Funktionen set_up, run_test und tear_down dem Konstruktor von function_test_case übergibt. Da dieser jedoch Funktionen ohne Parameter erwartet, wir aber den Dateinamen des Modells als Parameter übergeben wollen (sonst müssten wir alle drei Funktionen für jedes Modell neu schreiben), erstellen wir mit dem &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/index.html?/access/helpdesk/help/techdoc/ref/function_handle.html&amp;http://www.google.de/search?q=matlab%20function_handle"&gt;@-Operator&lt;/a&gt;  (quasi das &lt;a href="http://de.wikipedia.org/wiki/Lambda-Kalk%C3%BCl"&gt;Lambda-Kalkül&lt;/a&gt; unter MATLAB) drei anonyme Funktionen. Die Auswertung erfolgt über eine Zusicherung, die die Funktion &lt;a href="http://mlunit.sourceforge.net/doc/slunit/api/1.0/src/slunit_get_failed.html"&gt;slunit_get_failed&lt;/a&gt; benutzt, um festzustellen, ob einer oder mehrere Tests innerhalb des Testbetts fehlgeschlagen sind.

Die Ausführung dieser Funktion erfolgt dann mit
&lt;pre&gt;&gt;&gt; run(text_test_runner(1, 2), slunit_runner);&lt;/pre&gt;
Im Beispiel schlägt im Model "sample1.mdl" ein Test fehl, wodurch folgende Ausgabe erzeugt wird:
&lt;pre&gt;@()run_test(sys)(function_test_case) ... FAIL
@()run_test(sys)(function_test_case) ... OK

======================================================================
FAIL: @()run_test(sys)(function_test_case)
----------------------------------------------------------------------
Traceback (most recent call first):
 In s:\temp\slunit_runner\slunit_runner.m at line 13
 In s:\temp\slunit_runner\slunit_runner.m at line 26
 In s:\mlunit\src\@function_test_case\run_test.m at line 21
 In s:\mlunit\src\@test_case\run.m at line 38
 In s:\mlunit\src\@test_suite\run.m at line 24
 In s:\mlunit\src\@text_test_runner\run.m at line 31
AssertionError: Tests of model sample1.mdl failed.
----------------------------------------------------------------------
Ran 2 tests in 0.984s

FAILED (errors=0, failures=1)&lt;/pre&gt;
Zwei Dinge sind hierbei unbefriedigend:
&lt;ol&gt;
&lt;li&gt;Der Traceback ist im Kontext von slUnit nicht brauchbar. Zwar ist tatsächlich die Zusicherung in Zeile 13 fehlgeschlagen, allerdings ist dies nicht hilfreich bei der Analyse des Ergebnisses. Eine sinnvolle Angabe wäre, welche Tests innerhalb des Modells fehlgeschlagen sind.&lt;/li&gt;
&lt;li&gt;Gerade bei Batch-Tests, die automatisiert beispielsweise über Nacht ausgeführt werden, wird häufig ein Testreport erzeugt, der neben dem eigentlichen Testergebnis auch die verwendeten Test- und Ergebnisvektoren dokumentiert, beispielsweise als Plots. Erst kürzlich hat &lt;a href="http://blogs.ethz.ch/kejeblos/"&gt;Alexander Duschau-Wicke&lt;/a&gt; in einem &lt;a href="http://blogs.ethz.ch/kejeblos/2007/06/24/simulink-unit-testing/"&gt;Blog-Eintrag&lt;/a&gt;  auf diesen Mangel in slUnit hingewiesen und sehr treffend festgestellt:
&lt;blockquote&gt;
slunit [..] is clearly more intended for interactive testing [..].
&lt;/blockquote&gt;
Der interaktive Test im Sinne der test-getriebenen Entwicklung war tatsächlich die Hauptmotivation für die Entwicklung von slUnit, insofern fehlt derzeit ein Reportgenerator in dessen Repertoire. Im Prinzip dient das jeweilige Modell selbst als Dokumentation, da beim Abspeichern auch die Ergebnisse aller Zusicherungen und Tests in Form der Hintergrundfarbe beibehalten werden. D.h. wenn wie oben realisiert, mehrere Modelle nacheinander simuliert werden, lässt sich im Nachhinein zuerst an der Fehlermeldung erkennen, ob ein Test fehlgeschlagen ist, und dann das entsprechende Modell öffnen, um den Test nachzuvollziehen bzw. zu wiederholen. &lt;a href="http://de.wikipedia.org/wiki/Nichtsdestotrotz"&gt;Nichtsdestotrotz&lt;/a&gt; stimme ich Andreas zu, dass ein vollständiger Testreport sinnvoll ist, insbesondere wenn die Tests nicht dem Design, sondern der Verifikation dienen. Daher arbeite ich derzeit an einer Beispielimplementierung.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-4375314460822994259?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/4375314460822994259/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=4375314460822994259&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/4375314460822994259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/4375314460822994259'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/06/slunit-mehrere-modelle-automatisch.html' title='slUnit: Mehrere Modelle automatisch testen, Teil I'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-7345622274840845269</id><published>2007-06-22T10:00:00.000+02:00</published><updated>2008-04-11T23:00:21.137+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testen'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='simulink'/><category scheme='http://www.blogger.com/atom/ns#' term='modellbasiert'/><title type='text'>slUnit: Schnellstart</title><content type='html'>Dies ist der zweite Artikel der Reihe &lt;a href="http://mllog.blogspot.com/2007/06/slunit-die-verschmelzung-der.html"&gt;slUnit: Modellbasierte und testgetriebene Entwicklung verschmelzen&lt;/a&gt;.
&lt;h4&gt;Installation&lt;/h4&gt;
Zunächst muss slUnit &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=166995&amp;package_id=191882"&gt;runtergeladen&lt;/a&gt; und in ein beliebiges Verzeichnis entpackt werden, z.B. &lt;pre&gt;c:\Programme\MatlabTools\slunit&lt;/pre&gt;
Als nächstes fügt man die Unterverzeichnisse von slUnit zum MATLAB-Pfad hinzu (falls nicht schon geschehen, muss spätestens jetzt MATLAB gestartet werden):
&lt;pre&gt;&gt;&gt; addpath('c:\Programme\MatlabTools\slunit\src');
&gt;&gt; addpath('c:\Programme\MatlabTools\slunit\test');&lt;/pre&gt;
Sofern &lt;a href="http://mllog.blogspot.com/2007/04/unit-tests-mit-matlab-und-mlunit.html"&gt;mlUnit&lt;/a&gt; installiert ist, kann man die Testfälle von slUnit benutzen, um die Installation zu prüfen:
&lt;pre&gt;&gt;&gt; slunit_test
...................
----------------------------------------------------------------------
Ran 19 tests in 23.875s

OK&lt;/pre&gt;
Hinweis: Wenn unter "File &gt; Preferences &gt; Simulink &gt; Window reuse" die Option "reuse" eingestellt ist, schlägt der Test @test_slunit_multiplexer\test_activate.m fehl. Dies ist ein Fehler im Testfall, die Funktion von slUnit ist davon nicht beeinträchtigt. Ebenso kommt es zum Fehler, wenn unter "File &gt; Preferences &gt; Simulink &gt; Simulation &gt; Launch Model Explorer &gt; Solver &gt; Stop time" der Wert "inf" gesetzt ist. Mit unendlichen Simulationszeiten kann slUnit derzeit nicht umgehen. Beide Probleme werden mit der kommenden Version 1.1 behoben sein.

&lt;h4&gt;Wie erzeugt man ein einfaches Testbett?&lt;/h4&gt;
Ein einfaches Testbett wird mit dem Befehl
&lt;pre&gt;&gt;&gt; sys = slunit_create_test_bed;&lt;/pre&gt;
erzeugt. 
&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_QnyNXJ2dLNc/RntrjWTJK3I/AAAAAAAAAA8/VPZ1TiCaw2E/s1600-h/slunit.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_QnyNXJ2dLNc/RntrjWTJK3I/AAAAAAAAAA8/VPZ1TiCaw2E/s200/slunit.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5078771259815832434" /&gt;&lt;/a&gt;&lt;/p&gt;
Es wird das gezeigte Simulink-Modell geöffnet, das über folgende Bestandteile verfügt: Die zwei Subsysteme "System" und "Test1" stellen das zu testende System (auch Testobjekt genannt) und einen einfachen Testfall dar. Mit dem Button "RunAll" können alle Tests, mit dem Button "Run" genau ein Test gestartet werden. Der Fortschrittsbalken "ProgressBar" zeigt den Fortschritt der Tests an und färbt sich abhängig vom Testergebnis rot oder grün. Das letzte Element ist der Multiplexer, der zwischen verschiedenen Testfällen umschaltet und damit mehrere, voneinander unabhängige Testfälle erlaubt.

&lt;h4&gt;Wie fügt man einen Testfall hinzu?&lt;/h4&gt;

&lt;p&gt;Der einfachste Weg ist, einen bestehenden Testfall mit Hilfe der rechten Maustaste zu kopieren. Danach führt man einen Doppelklick auf den Multiplexer aus und erhöht die Anzahl der Eingänge (inputs) um eins. Schließlich verbindet man den neuen Testfall mit dem neuen Eingang des Multiplexers.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_QnyNXJ2dLNc/RntvfmTJK4I/AAAAAAAAABE/7A4jFdllU40/s1600-h/slunit_add_test.png"&gt;&lt;img style="cursor:hand;" src="http://1.bp.blogspot.com/_QnyNXJ2dLNc/RntvfmTJK4I/AAAAAAAAABE/7A4jFdllU40/s400/slunit_add_test.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5078775593437834114" /&gt;&lt;/a&gt;

&lt;h4&gt;Wie fügt man einen Ausgang zu einem Testfall hinzu?&lt;/h4&gt;

&lt;p&gt;Der erste Test verfügt bereits über einen Ausgang, der mit "Out1" bezeichnet ist. Ein zweiter Ausgang kann wiederum durch Kopieren erzeugt werden. Soll der neue Ausgang ebenfalls vom Multiplexer zum Testobjekt geleitet werden, so müssen zunächst beide Ausgänge zu einem Vektor vereinigt werden (mittels eines Mux-Blockes). Dann führt man erneut einen Doppelklick auf den Multiplexer aus und erhöht den Parameter "Signals" um eins. Es ist zu beachten, dass der Multiplexer nur Eingänge mit derselben Breite akzeptiert, d.h. auch bei allen anderen Testfällen muss nun ein Vektor bestehend aus 2 Signalen gebildet werden.&lt;/p&gt;

&lt;h4&gt;Wie führt man einen einzelnen Testfall aus?&lt;/h4&gt;

&lt;p&gt;Es gibt drei Wege, einen Testfall auszuführen:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Man öffnet das Subsystem des Testfalls und führt einen Doppelklick auf dessen Run-Button aus.&lt;/li&gt;
&lt;li&gt;Man führt einen Doppelklick auf den Run-Button des Testbetts aus (siehe obige Grafik). Der Testfall wird dann nach folgenden Kriterien selektiert:
&lt;ul&gt;&lt;li&gt;Wenn kein Subsystem eines Testfalls geöffnet ist, wird der zuletzt ausgeführte Testfall gestartet.&lt;/li&gt;
&lt;li&gt;Wenn genau ein Subsystem eines Testfalls geöffnet ist, wird dieser Testfall gestartet.&lt;/li&gt;
&lt;li&gt;Wenn mehrere Subsysteme verschiedener Testfälle geöffnet sind, wird der zuletzt ausgeführte Testfall gestartet.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;Man startet die Simulation über den Button "Start Simulation" oder den entsprechenden Menüpunkt. Der Testfall wird nach den oben beschriebenen Kriterien ausgewählt.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;Wie führt man alle Testfälle aus?&lt;/h4&gt;

&lt;p&gt;Alle Testfälle werden durch den Button "RunAll" ausgeführt.&lt;/p&gt;

&lt;h4&gt;Wie werden die Testergebnisse angezeigt?&lt;/h4&gt;

&lt;p&gt;Die Testergebnisse werden durch die Hintergrundfarbe der Subsysteme der Testfälle dargestellt. Grün bedeutet, dass alle Zusicherungen (Assertions) eingetroffen sind, und rot bedeutet, dass eine oder mehrere Zusicherungen verletzt wurden. Außerdem kann das Subsystem grau gefärbt werden, was darauf hindeutet, dass entweder der Testfall oder eine der enthaltenden Zusicherungen nicht ausgeführt wurden. Letzteres kann dann der Fall sein, wenn die Zusicherung in einem Enabled-Subsystem platziert wurde.&lt;/p&gt;

&lt;p&gt;Das Gesamtergebnis der Tests wird zusätzlich als Farbe des Fortschrittsbalkens angezeigt.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_QnyNXJ2dLNc/Rnt1EWTJK5I/AAAAAAAAABM/FYMkqhptJbU/s1600-h/slunit_run.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_QnyNXJ2dLNc/Rnt1EWTJK5I/AAAAAAAAABM/FYMkqhptJbU/s200/slunit_run.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5078781722356165522" /&gt;&lt;/a&gt;

&lt;h4&gt;Wie kann man Parameter laden?&lt;/h4&gt;

&lt;p&gt;Häufig werden in Simulink Constant-Blöcke mit Werten aus dem MATLAB-Workspace verwendet. Damit diese reproduzierbar getestet werden können, sollten sie bei jedem Start der Simulation neu geladen werden, beispielsweise mit einer Funktion "load_parameters". Dazu wählt man im Kontextmenü des Modells (rechten Maustaste) die Option "Model Properties". Auf dem Reiter "Callbacks" findet sich unter "Model callbacks" die Option "InitFcn", in der bereits die Funktion slunit_init_fcn aufgerufen wird. Die Funktion zum Laden der Paramter kann hier vor diesem Eintrag ergänzt werden, also z.B.&lt;/p&gt;
&lt;pre&gt;load_parameters
slunit_init_fcn&lt;/pre&gt;
&lt;p&gt;Hinweis: Der Eintrag slunit_init_fcn darf nicht verändert werden, da sonst slUnit nicht mehr korrekt funktioniert.&lt;/p&gt;

&lt;h4&gt;Weitere Artikel in der Reihe&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/07/slunit-zusicherungen-mit-dem-assert.html"&gt;slUnit: Zusicherungen mit dem Assert-Block&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2008/02/slunit-tests-definieren-und-ausfhren.html"&gt;slUnit: Tests definieren und ausführen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2008/02/slunit-der-testkontext.html"&gt;slUnit: Der Textkontext&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Fragen, Kommentare, Fehler&lt;/h4&gt;

&lt;p&gt;Bei Fragen, Kommentaren oder Fehlern bitte einfach eine E-Mail an &lt;a href="mailto:thomas@dohmke.de"&gt;thomas@dohmke.de&lt;/a&gt; senden oder einen Kommentar hier im Blog hinterlassen. Gewöhnlich antworte ich innerhalb von 24 Stunden. Spam und vergleichbarer Müll wird automatisch aussortiert, daher bitte einen aussagekräftigen Betreff, z.B. "Frage zu slUnit", verwenden.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-7345622274840845269?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/7345622274840845269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=7345622274840845269&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/7345622274840845269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/7345622274840845269'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/06/slunit-schnellstart.html' title='slUnit: Schnellstart'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_QnyNXJ2dLNc/RntrjWTJK3I/AAAAAAAAAA8/VPZ1TiCaw2E/s72-c/slunit.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-2179891930443466854</id><published>2007-06-18T20:25:00.002+02:00</published><updated>2008-04-11T23:00:31.668+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testen'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><category scheme='http://www.blogger.com/atom/ns#' term='simulink'/><category scheme='http://www.blogger.com/atom/ns#' term='modellbasiert'/><title type='text'>slUnit: Modellbasierte und testgetriebene Entwicklung verschmelzen</title><content type='html'>&lt;p&gt;Dieser Artikel ist der Anfang einer Reihe von Beiträgen zu &lt;a href="http://slunit.dohmke.de"&gt;slUnit&lt;/a&gt;, einem Testing Framework für &lt;a href="http://www.mathworks.com/products/simulink/"&gt;Simulink&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Einführung&lt;/h4&gt;
&lt;p&gt;Die Entwicklung von &lt;a href="http://slunit.dohmke.de"&gt;slUnit&lt;/a&gt; geht zurück auf das Jahr 2003, als ich mit der Arbeit an meiner Dissertation begann. slUnit ist ein Testing Framework, das die Erstellung und Ausführung von Testfällen während der modellbasierten Entwicklung erlaubt. Es basiert auf der grafischen Umgebung &lt;a href="http://www.mathworks.com/products/simulink/"&gt;Simulink&lt;/a&gt;, die wie MATLAB von der Firma &lt;a href="http://www.mathworks.com"&gt;The Mathworks&lt;/a&gt; stammt.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://de.wikipedia.org/wiki/Modellgetriebene_Softwareentwicklung"&gt;Modellbasierte Entwicklung&lt;/a&gt; bedeutet, dass die zu realisierenden Systeme durchgängig durch Modelle beschrieben werden, die die zentralen Artifakte während des Entwicklungsprozesses bilden. Obwohl solche Modelle nicht zwangsläufig grafisch dargestellt werden müssen, hat sich gerade diese Notationsweise in den letzten Jahren durchgesetzt. Im Bereich der eingebetteten System bzw. der Regelungstechnik ist insbesondere Simulink stark verbreitet. Es unterstützt den kompletten Entwicklungsprozess von der Modellbildung über die Simulation bis hin zur automatischen Codeerzeugung mittels des &lt;a href="http://www.mathworks.com/products/rtw/"&gt;Real-Time Workshops&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Ein anderer Trend in der Softwaretechnik ist die &lt;a href="http://de.wikipedia.org/wiki/Testgetriebene_Entwicklung"&gt;testgetriebene Entwicklung&lt;/a&gt;, bei der im Gegensatz zu traditionellen Vorgehensweisen wie dem &lt;a href="http://de.wikipedia.org/wiki/V-Modell"&gt;V-Modell&lt;/a&gt; die Tests vor der Implementierung erstellt werden und damit nicht nur der Verifikation, sondern auch dem Design dienen. In diesem Zusammenhang hat sich eine Familie von Testing Frameworks herausgebildet, die so genannte &lt;a href="http://xunitpatterns.com/"&gt;xUnit-Familie&lt;/a&gt;, die nicht nur über eine vergleichbare Architektur verfügen, sondern auch eine einheitliche Herangehensweise erlauben, unabhängig von der verwendeten Programmiersprache.&lt;/p&gt;
&lt;p&gt;Zwar gab und gibt es auch für Simulink zahlreiche Testing Frameworks, u.a. &lt;a href="http://www.mathworks.com/products/systemtest/index.html"&gt;SystemTest&lt;/a&gt;, &lt;a href="http://www.dspace.de/ww/de/gmb/home/products/sw/expsoft/mtest.cfm"&gt;MTest&lt;/a&gt; oder &lt;a href="http://www.reactive-systems.com/tester.msp"&gt;Reactis Tester&lt;/a&gt;, diesen eignen sich aber nur unzureichend für die testgetriebene Entwicklung. Einerseits werden die Testfälle durch die Analyse des Testobjekts automatisch erstellt (was bei TDD nicht möglich ist, da dass Testobjekt ja noch nicht existiert), andererseits wird der Testprozess von der Erstellung über die Ausführung bis hin zur Auswertung nicht mit den Mitteln der Programmiersprache selbst, sondern über externe Tools und grafischen Benutzeroberflächen realisiert. Dies widerspricht einem Paradigma von xUnit, welches die Erstellung der Testfälle in derselben Programmiersprache wie das Testobjekt vorsieht.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://slunit.dohmke.de"&gt;slUnit&lt;/a&gt; ist also eine Modultestsoftware für Simulink, die nach den &lt;a href="http://de.wikipedia.org/wiki/Entwurfsmuster"&gt;Entwurfsmustern&lt;/a&gt; von xUnit implementiert wurde. Oder anders gesagt, die Simulink Variante von &lt;a href="http://de.wikipedia.org/wiki/JUnit"&gt;JUnit&lt;/a&gt;. slUnit ist &lt;a href="http://www.fsfeurope.org/documents/freesoftware.de.html"&gt;freie Software&lt;/a&gt; im Sinne der GNU &lt;a href="http://www.gnu.org/licenses/gpl.html"&gt;General Public License (GPL)&lt;/a&gt; (&lt;a href="http://www.gnu.de/documents/gpl.de.html"&gt;deutsche Übersetzung&lt;/a&gt;), veröffentlicht von der &lt;a href="http://www.fsfeurope.org/index.de.html"&gt;Free Software Foundation&lt;/a&gt;. slUnit wird als Subprojekt von &lt;a href="http://mlunit.dohmke.de"&gt;mlUnit&lt;/a&gt; bei &lt;a href="http://www.sourceforge.net/projects/mlunit"&gt;SourceForge&lt;/a&gt; geführt. Die aktuelle Version ist slUnit 1.0.&lt;/p&gt;
&lt;h4&gt;Artikel in der Reihe&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/06/slunit-schnellstart.html"&gt;slUnit: Schnellstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2007/07/slunit-zusicherungen-mit-dem-assert.html"&gt;slUnit: Zusicherungen mit dem Assert-Block&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mllog.blogspot.com/2008/02/slunit-der-testkontext.html"&gt;slUnit: Der Textkontext&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-2179891930443466854?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/2179891930443466854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=2179891930443466854&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/2179891930443466854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/2179891930443466854'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/06/slunit-die-verschmelzung-der.html' title='slUnit: Modellbasierte und testgetriebene Entwicklung verschmelzen'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-6259394684719901494</id><published>2007-04-26T19:19:00.000+02:00</published><updated>2007-06-22T09:33:55.621+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='version'/><category scheme='http://www.blogger.com/atom/ns#' term='funktion'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><title type='text'>Welches ist die installierte MATLAB Version?</title><content type='html'>&lt;p&gt;Manchmal ist es innerhalb von Funktionen oder Skripten notwendig, die Version des
installierten MATLABs zu überprüfen, um Abwärtskompatibilität zu gewährleisten. &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/rn/bq1zizq.html"&gt;MATLAB 7.4&lt;/a&gt; bietet dafür die Funktion &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/ref/verlessthan.html"&gt;verLessThan&lt;/a&gt;, die man wie folgt aufruft:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; verLessThan('MATLAB', '7.0');

ans =

     0&lt;/pre&gt;

&lt;p&gt;Der Rückgabewert 0 bedeutet, dass meine MATLAB Version größer oder gleich der &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/rn/bqsq45p.html"&gt;Version 7.0&lt;/a&gt; ist. Soweit so gut. Leider gibt es dabei ein konzeptionelles Problem: Ältere MATLAB Versionen kennen den Befehl verLessThan nicht. Beispielsweise führt die obige Eingabe in &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/rn/bqsq452.html"&gt;Version 7.0.4&lt;/a&gt; zu folgender Ausgabe:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; verLessThan('MATLAB', '7.0')
??? Undefined command/function 'verLessThan'.&lt;/pre&gt;
&lt;p&gt;Daher stellt MathWorks die Datei verLessThan.m 
&lt;a href="http://www.mathworks.com/support/solutions/data/1-38LI61.html?solution=1-38LI61"&gt;frei&lt;/a&gt; zur Verfügung. Der Benutzer muss sich diese herunterladen und nach $MATLABROOT\toolbox\matlab\general kopieren, wobei $MATLABROOT das Verzeichnis angibt, welches von der Funktion
&lt;pre&gt;&gt;&gt; matlabroot&lt;/pre&gt;
&lt;p&gt;zurückgegeben wird.&lt;/p&gt;

&lt;p&gt;Der Nachteil dieser Lösung ist, dass die Datei urheberrechtlich geschützt ist und damit nicht mit eigener Software verteilt werden darf. Alternativ habe ich daher eine eigene kleine Funktion als Open Source erstellt, die zwei Strings vergleicht (und damit auch gleich das eigenartige &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/ref/strcmpi.html"&gt;strcmp&lt;/a&gt; von MATLAB &lt;a href="http://www.strcmp.de"&gt;ersetzt&lt;/a&gt;):&lt;/p&gt;
&lt;pre&gt;function result = ml_strcmp(str1, str2)

strs{1} = str1;
strs{2} = str2;
cmp = find(strcmp(sort(strs), str1));

if (cmp == 2)
    result = 1;
elseif (cmp == 1)
    result = -1;
else
    result = 0;
end;&lt;/pre&gt;
&lt;p&gt;Der Versionsvergleich erfolgt dann durch folgenden Aufruf:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; ver_matlab = ver('MATLAB');
&gt;&gt; ml_str_cmp(ver_matlab.Version, '7.0.4') == -1&lt;/pre&gt;
&lt;p&gt;Daraus kann man natürlich auch eine Funktion machen:&lt;/p&gt;
&lt;pre&gt;function result = ml_verLessThan(product, version)

ver_product = ver(product);
result = (ml_str_cmp(ver_product.Version, version) == -1);&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-6259394684719901494?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/6259394684719901494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=6259394684719901494&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/6259394684719901494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/6259394684719901494'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/04/welches-ist-die-installierte-matlab.html' title='Welches ist die installierte MATLAB Version?'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-3824296540683030766</id><published>2007-04-21T11:08:00.000+02:00</published><updated>2007-04-21T10:09:27.801+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testen'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><title type='text'>mlUnit: Eine Einführung</title><content type='html'>&lt;p&gt;Beim näheren Betrachten fiel mir heute auf, dass es auch zu meinen eigenen MATLAB Projekten, nämlich &lt;a href="http://mlunit.dohmke.de"&gt;mlUnit&lt;/a&gt;, &lt;a href="http://mlproj.dohmke.de"&gt;mlProj&lt;/a&gt; und &lt;a href="http://slunit.dohmke.de"&gt;slUnit&lt;/a&gt; keinerlei deutschsprachige Dokumentation gibt. Das muss anders werden, demzufolge gibt es heute den ersten Text. Thema: mlUnit und wie man damit testet.&lt;/p&gt;

&lt;h4&gt;Was ist mlUnit&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://mlunit.dohmke.de"&gt;mlUnit&lt;/a&gt; ist eine &lt;a href="http://de.wikipedia.org/wiki/Liste_von_Modultest-Software"&gt;Modultestsoftware&lt;/a&gt; für MATLAB, die nach den &lt;a href="http://de.wikipedia.org/wiki/Entwurfsmuster"&gt;Entwurfsmustern&lt;/a&gt; von xUnit implementiert wurde. Oder anders gesagt, die MATLAB Variante von &lt;a href="http://de.wikipedia.org/wiki/JUnit"&gt;JUnit&lt;/a&gt;. mlUnit ist &lt;a href="http://www.fsfeurope.org/documents/freesoftware.de.html"&gt;freie Software&lt;/a&gt; im Sinne der GNU &lt;a href="http://www.gnu.org/licenses/gpl.html"&gt;General Public License (GPL)&lt;/a&gt; (&lt;a href="http://www.gnu.de/documents/gpl.de.html"&gt;deutsche Übersetzung&lt;/a&gt;), veröffentlicht von der &lt;a href="http://www.fsfeurope.org/index.de.html"&gt;Free Software Foundation&lt;/a&gt;. Es wurde von mir irgendwann zwischen Weihnachten und Neujahr 2004 während des Lesens eines Buchs  über &lt;a href="http://de.wikipedia.org/wiki/Testgetriebene_Entwicklung"&gt;testgetriebene Entwicklung&lt;/a&gt; quasi als Übung geschrieben und dann als Reaktion auf einen &lt;a href="http://groups.google.com/group/comp.soft-sys.matlab/browse_frm/thread/52e448701b94ab9d/"&gt;Beitrag&lt;/a&gt; in der &lt;a href="http://groups.google.com/group/comp.soft-sys.matlab/topics"&gt;MATLAB Newsgroup&lt;/a&gt; veröffentlicht.&lt;/p&gt;

&lt;h4&gt;Installation&lt;/h4&gt;

&lt;p&gt;Die aktuelle Version von ist &lt;a href="http://downloads.sourceforge.net/mlunit/mlunit_1.5.1.zip"&gt;mlUnit 1.5.1&lt;/a&gt;. Nach dem Runterladen der zip-Datei diese einfach entpacken, z.B. nach&lt;/p&gt;
&lt;pre&gt;c:\projekte&lt;/pre&gt;
&lt;p&gt;so dass das Verzeichnis&lt;/p&gt;
&lt;pre&gt;c:\projekte\mlunit&lt;/pre&gt;
&lt;p&gt;entsteht.&lt;/p&gt;

&lt;p&gt;Im nächsten Schritt sind die Unterverzeichnisse dem MATLAB Pfad hinzuzufügen:&lt;/p&gt;
&lt;pre&gt;addpath('c:\projekte\mlunit\src');
addpath('c:\projekte\mlunit\test');&lt;/pre&gt;

&lt;h4&gt;Der erste Test&lt;/h4&gt;

&lt;p&gt;Ein einfacher Test kann als eine einzelne m-Funktion definiert werden:&lt;/p&gt;
&lt;pre&gt;function test = test_mlunit

test = load_tests_from_mfile(test_loader);

    function test_erfolg
        x = 10;
        y = 10;
        
        assert_equals(x, y);
    end

    function test_fehler
        x = 10;
        y = 20;
        
        assert_equals(x, y);
    end
end
&lt;/pre&gt;
&lt;p&gt;Der Test enthält zwei sogenannte Testmethoden: test_success und test_failure, und kann mit dem folgendem Befehl ausgeführt werden:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; run(gui_test_runner, 'test_mlunit')&lt;/pre&gt;
&lt;p&gt;Während die erste Testmethode ohne Fehler durchläuft, schläge die zweite fehl. Ursache ist die Zusicherung (in xUnit als &lt;a href="http://de.wikipedia.org/wiki/Assertion"&gt;Assertion&lt;/a&gt; bezeichnet), dass x und y gleich sind, was offensichtlich nicht der Fall ist. Entsprechend dieser nicht erfüllten Zusicherung zeigt mlUnit einen &lt;a href="http://www.ito.tu-darmstadt.de/publs/pdf/FraikinGruenerBalken.pdf"&gt;roten Balken&lt;/a&gt; mit der Liste der Fehler an:&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_QnyNXJ2dLNc/Rim4A7_yhSI/AAAAAAAAAAk/-GYoU3xQXGM/s1600-h/test_mlunit.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_QnyNXJ2dLNc/Rim4A7_yhSI/AAAAAAAAAAk/-GYoU3xQXGM/s320/test_mlunit.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5055774382944847138" /&gt;&lt;/a&gt;

&lt;h4&gt;Wiederverwendung durch Testkontexte&lt;/h4&gt;

&lt;p&gt;Ein wichtiges Konzept von xUnit ist die sogenannte &lt;a href="http://xunitpatterns.com/test%20fixture%20-%20xUnit.html"&gt;Fixture&lt;/a&gt; (zu deutsch: der Einbau, die Vorrichtung). Mit ihr wird alles das beschrieben, was zum Durchführen eines Tests notwendig ist. In diesem Sinne kann man die Fixture auch als Testkontext bezeichnen. Zur Realisierung werden die Methoden set_up und tear_down verwendet. Erstere wird vor, letztere nach jeder Testmethode aufgerufen. Dabei ist es egal, ob die jeweilige Testmethode erfolgreich ist oder fehlschlägt.&lt;/p&gt;

&lt;p&gt;Als Beispiel soll das folgende Simulink-Modell, welches einen einfachen &lt;a href="http://de.wikipedia.org/wiki/Regelkreis"&gt;Regelkreis&lt;/a&gt; beschreibt, getestet werden.&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_QnyNXJ2dLNc/RinDdb_yhTI/AAAAAAAAAAs/Vg-ARiYPzG8/s1600-h/test_regelkreis.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_QnyNXJ2dLNc/RinDdb_yhTI/AAAAAAAAAAs/Vg-ARiYPzG8/s320/test_regelkreis.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5055786967199024434" /&gt;&lt;/a&gt;

&lt;p&gt;Zunächst soll überprüft werden, wie das Verhalten des Regelkreis mit Nullwerten ist:&lt;/p&gt;
&lt;pre&gt;function test = test_regelung

test = load_tests_from_mfile(test_loader);

    function test_null
        open_system('test_regelkreis');
        assignin('base', 'r', 0);
        assignin('base', 'z', 0);
        sim('test_regelkreis', 10, simset(simget('test_regelkreis'), 'DstWorkspace', 'base'));
        assert_equals(0, evalin('base', 'y'));
        close_system('test_regelkreis');
    end
end&lt;/pre&gt;
&lt;p&gt;Der Test wird wieder mit&lt;/p&gt;
&lt;pre&gt;&gt;&gt; run(gui_test_runner, 'test_regelung')&lt;/pre&gt;
&lt;p&gt;ausgeführt. Als nächstes soll die Referenzgröße auf 1 gesetzt werden. Pre Copy&amp;Paste könnte man folgende Testmethode erstellen:&lt;/p&gt;
&lt;pre&gt;    function test_referenz
        open_system('test_regelkreis');
        assignin('base', 'r', 1);
        assignin('base', 'z', 0);
        sim('test_regelkreis', 10, simset(simget('test_regelkreis'), 'DstWorkspace', 'base'));
        assert_equals(1, evalin('base', 'y');
        close_system('test_regelkreis');
    end&lt;/pre&gt;
&lt;p&gt;Wie man jedoch sieht, sind die erste, dritte, vierte und sechste Zeile Duplikate der ersten Testmethode. Sie stellen den Testkontext dar, und werden daher in die Methoden set_up und tear_down verschoben. Es ergibt sich der folgende Test:&lt;/p&gt;
&lt;pre&gt;function test = test_regelung

test = load_tests_from_mfile(test_loader);

    function set_up
        open_system('test_regelkreis');
        assignin('base', 'r', 0);
        assignin('base', 'z', 0);
    end

    function tear_down
        close_system('test_regelkreis');
    end

    function sim_regelkreis
        sim('test_regelkreis', 10, simset(simget('test_regelkreis'), 'DstWorkspace', 'base'));
    end

    function test_null
        sim_regelkreis
        assert_equals(0, evalin('base', 'y'));
    end

    function test_referenz
        assignin('base', 'r', 1);
        sim_regelkreis
        assert_equals(1, evalin('base', 'y'));
    end
end&lt;/pre&gt;

&lt;h4&gt;Zusammenfassung&lt;/h4&gt;

mlUnit erlaubt die Definition und Ausführung von Unit-Tests unter MATLAB unter Berücksichtigung der Muster von xUnit. Die zwei Beispiele zeigen die prinzipielle Verwendung von mlUnit. Weitere Dokumentation folgt in nächster Zeit.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-3824296540683030766?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/3824296540683030766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=3824296540683030766&amp;isPopup=true' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/3824296540683030766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/3824296540683030766'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/04/unit-tests-mit-matlab-und-mlunit.html' title='mlUnit: Eine Einführung'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_QnyNXJ2dLNc/Rim4A7_yhSI/AAAAAAAAAAk/-GYoU3xQXGM/s72-c/test_mlunit.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-8451853202846768299</id><published>2007-04-13T22:11:00.000+02:00</published><updated>2007-04-13T22:27:35.351+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sonstiges'/><category scheme='http://www.blogger.com/atom/ns#' term='funktion'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><title type='text'>Neue Dateien erzeugen mit edit</title><content type='html'>&lt;p&gt;Gibt man im Command Window von MATLAB den Befehl &lt;em&gt;edit&lt;/em&gt; mit einem Dateinamen ein, der noch nicht existiert, so fragt der Editor höflich, ob diese Datei vielleicht erzeugt werden soll. Also so:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; edit test.m&lt;/pre&gt;
&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_QnyNXJ2dLNc/Rh_lleRLMkI/AAAAAAAAAAM/vljik1vtCNY/s1600-h/matlab_edit.png"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_QnyNXJ2dLNc/Rh_lleRLMkI/AAAAAAAAAAM/vljik1vtCNY/s320/matlab_edit.png" alt="" id="BLOGGER_PHOTO_ID_5053009738876006978" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dies funktioniert aber nicht, wenn die Datei bereits irgendwo im Pfad von MATLAB existiert, d.h. ein
&lt;pre&gt;&gt;&gt; edit eval.m&lt;/pre&gt;
&lt;p&gt;öffnet immer die Datei &lt;em&gt;$MATLABROOT\R2007a\toolbox\matlab\lang\eval.m&lt;/em&gt;. Abhilfe schafft eine kleine Funktion:&lt;/p&gt;
&lt;pre&gt;function mledit(filename)

com.mathworks.mlservices.MLEditorServices.openDocument(filename);&lt;/pre&gt;
&lt;p&gt;Damit gilt dann folgende Semantik:&lt;/p&gt;
&lt;pre&gt;&gt;&gt; edit eval.m   % Öffnet die Datei im Pfad
&gt;&gt; mledit eval.m % Öffnet die Datei im derzeitigen Verzeichnis&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-8451853202846768299?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/8451853202846768299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=8451853202846768299&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/8451853202846768299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/8451853202846768299'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/04/neue-dateien-erzeugen-mit-edit.html' title='Neue Dateien erzeugen mit &lt;em&gt;edit&lt;/em&gt;'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_QnyNXJ2dLNc/Rh_lleRLMkI/AAAAAAAAAAM/vljik1vtCNY/s72-c/matlab_edit.png' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-9080296245357041996</id><published>2007-04-12T20:18:00.000+02:00</published><updated>2007-04-13T21:45:54.091+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='online'/><category scheme='http://www.blogger.com/atom/ns#' term='literatur'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><title type='text'>Deutsche Quellen zu MATLAB</title><content type='html'>&lt;p&gt;Der deutschsprachige Startpunkt zu MATLAB ist natürlich die Homepage des Herstellers &lt;a href="http://www.mathworks.de"&gt;The MathWorks&lt;/a&gt;, die allerdings nach ein paar Links, z.B. beim Klick auf &lt;a href="http://www.mathworks.de/products/matlab/demos.html"&gt;Demos und Webinare&lt;/a&gt;, ohne Vorwarnung zur englischen Sprache übergeht.&lt;/p&gt;

&lt;p&gt;Zweite Anlaufstation: &lt;a href="http://de.wikipedia.org"&gt;Wikipedia&lt;/a&gt;. Der &lt;a href="http://de.wikipedia.org/wiki/Matlab"&gt;Artikel über MATLAB&lt;/a&gt; ist jedoch nicht wirklich umfangreich und besteht zu grob einem Drittel aus der Aufzählung von Alternativen.&lt;/p&gt;

&lt;p&gt;Was gibts sonst noch... vor allem &lt;a href="http://rosewood.fernuni-hagen.de/steuerdvi/"&gt;eine&lt;/a&gt; &lt;a href="http://www.physik.uni-regensburg.de/edv/schriften/matlab/matkurs.html"&gt;ganze&lt;/a&gt; &lt;a href="http://www1.uni-hamburg.de/W.Wiedl/Skripte/Matlab/"&gt;Reihe&lt;/a&gt; &lt;a href="http://www-com.physik.hu-berlin.de/~bunk/kurs/matlab/matlab.html"&gt;von&lt;/a&gt; &lt;a href="http://www.ica1.uni-stuttgart.de/Courses_and_Lectures/Mathematik_mit_MATHLAB/Html/mscript.html"&gt;Links&lt;/a&gt; zu Universitäten, die teilweise &lt;a href="http://homepages.fh-regensburg.de/~wah39067/Matlab/"&gt;übersetzte Original-Handbücher&lt;/a&gt; zum Download anbieten oder aber mit &lt;a href="http://www.oldimrt.ethz.ch/education/tutorials/matlab/"&gt;ansprechend gemachter Navigation&lt;/a&gt; Lust auf mehr machen.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-9080296245357041996?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/9080296245357041996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=9080296245357041996&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/9080296245357041996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/9080296245357041996'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/04/deutsche-quellen-zu-matlab.html' title='Deutsche Quellen zu MATLAB'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-6095060916120840801</id><published>2007-04-12T19:33:00.000+02:00</published><updated>2007-04-20T06:29:21.532+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><category scheme='http://www.blogger.com/atom/ns#' term='matlab'/><title type='text'>Warum dieses Blog?</title><content type='html'>&lt;p&gt;&lt;a href="http://www.mathworks.de/products/matlab/"&gt;MATLAB&lt;/a&gt; ist wohl einer der &lt;a href="http://www.eetimes.com/news/design/showArticle.jhtml;jsessionid=WNFN0DJUZXZC2QSNDLPCKHSCJUNN2JVN?articleID=49400392"&gt;meist genutzten&lt;/a&gt; Anwendungen zur numerischen Lösung von mathematischen Problemstellungen, zur Signalverarbeitung oder zur Modellbildung. Dennoch gibt es nur relativ wenige deutschsprachige Quellen dazu im Netz, darunter kein einziges Blog... jedenfalls habe ich keines gefunden. Eine &lt;a href="http://www.google.de/search?as_q=matlab+blog&amp;hl=de&amp;amp;num=10&amp;btnG=Google-Suche&amp;amp;as_epq=&amp;as_oq=&amp;amp;as_eq=&amp;lr=lang_de&amp;amp;as_ft=i&amp;as_filetype=&amp;amp;as_qdr=all&amp;as_occt=any&amp;amp;as_dt=i&amp;as_sitesearch=&amp;amp;as_rights=&amp;amp;safe=images"&gt;Suche&lt;/a&gt;  bei Google fördert nur einzelne Einträge in verschiedenen Blogs zu Tage, darunter sowohl &lt;a href="http://moritz.faui2k3.org/blog/nie-wieder-matlab"&gt;kritische&lt;/a&gt; als auch &lt;a href="http://www.quixotic-project.de/blog/?p=21"&gt;spannende&lt;/a&gt; Sachen.&lt;/p&gt;

&lt;p&gt;Im Gegensatz dazu gibt es eine Reihe von englischen Blogs zum Thema, allen voran &lt;a href="http://blogs.mathworks.com/loren/"&gt;Loren on the Art of MATLAB&lt;/a&gt;, &lt;a href="http://blogs.mathworks.com/pick/"&gt;Doug's Pick of the Week&lt;/a&gt;, &lt;a href="http://blogs.mathworks.com/steve/"&gt;Steve on Image Processing&lt;/a&gt; oder &lt;a href="http://2math.blogspot.com/"&gt;2Math&lt;/a&gt; (drei von diesen vier werden von Mitarbeitern von &lt;a href="http://www.mathworks.com/"&gt;The MathWorks&lt;/a&gt; geschrieben). Andere scheinen eher versandet zu sein, z.B. &lt;a href="http://www.ecogito.net/matlab/"&gt;MATLAB Tips and Tricks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Es fehlt also ein deutsches Blog (hm... vielleicht vermisst es auch niemand), und da ich mich faktisch tagtäglich mit stetiger Begeisterung mit MATLAB beschäftige und einfach Lust habe, etwas über MATLAB zu schreiben, startet heute dieses Blog. Das Bloggen schon seit &lt;a href="http://www.kopfhoch-studio.de/blog/?p=1345"&gt;zwei Jahren&lt;/a&gt; oder auch erst seit &lt;a href="http://sbp.twoday.net/stories/3209075/"&gt;Januar&lt;/a&gt; out ist, interessiert mich dabei nicht die Bohne.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-6095060916120840801?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mllog.blogspot.com/feeds/6095060916120840801/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4194361870903955864&amp;postID=6095060916120840801&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/6095060916120840801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/6095060916120840801'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/04/warum-dieses-blog.html' title='Warum dieses Blog?'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4194361870903955864.post-8702083883474211096</id><published>2007-04-12T19:00:00.001+02:00</published><updated>2008-04-10T21:19:41.124+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><category scheme='http://www.blogger.com/atom/ns#' term='impressum'/><title type='text'>Impressum</title><content type='html'>&lt;p&gt;Alle im mllog veröffentlichten Texte, Bilder und Quellcodes unterliegen, sofern nicht anders gekennzeichnet, dem Urheberrecht von Thomas Dohmke und dürfen nur mit ausdrücklicher Erlaubnis kopiert, weitergeleitet oder vervielfältig werden. Bitte kontaktieren Sie mich per E-Mail für solch eine Erlaubnis.&lt;/p&gt;
&lt;h4&gt;Anschrift&lt;/h4&gt;
&lt;p&gt;Thomas Dohmke&lt;br /&gt;
Hindenburgstr. 71&lt;br /&gt;
72762 Reutlingen&lt;/p&gt;
&lt;h4&gt;E-Mail&lt;/h4&gt;
&lt;p&gt;&lt;a href="mailto:thomas@dohmke.de"&gt;thomas@dohmke.de&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Wenn Sie mir eine E-Mail schicken wollen, dann beachten Sie bitte folgende Regeln:&lt;/p&gt;
&lt;ul class="para"&gt;
&lt;li&gt;Benutzen Sie ein aussagekräftigen Betreff (kein "Hallo Thomas" oder ähnliches).&lt;/li&gt;
&lt;li&gt;Senden Sie keine HTML oder RTF E-Mails.&lt;/li&gt;
&lt;li&gt;Senden Sie keine Anhänge.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ansonsten besteht die Gefahr, das Ihre E-Mail durch meinen Spam-Filter automatisch aussortiert wird.&lt;/p&gt;

&lt;h4&gt;Links auf meine Seiten setzen&lt;/h4&gt;
&lt;p&gt;Grundsätzlich ist es ausdrücklich erlaubt, Links auf meine Seiten zu setzen! Bitte sehen Sie jedoch davon ab, meine Seiten innerhalb Ihres eigenen Framesets aufzurufen.&lt;/p&gt;
&lt;h4&gt;Links zu anderen Seiten&lt;/h4&gt;
&lt;p&gt;Zum Thema Links und Disclaimer gibt es einige interessante Seiten, zum Beispiel:&lt;/p&gt;
&lt;ul class="para"&gt;
&lt;li&gt;Tim Berners-Lee, &lt;a href="http://www.w3.org/DesignIssues/LinkLaw"&gt;Links and Law&lt;/a&gt;, übersetzt ins Deutsche: &lt;a href="http://www.artikel5.de/archiv/tbl.html"&gt;Was ist ein Link?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Michael Jendryschik, &lt;a href="http://jendryschik.de/misc/disclaimer"&gt;Warum Disclaimer dem WWW schaden&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Michael Nahrath, &lt;a href="http://www.subotnik.net/misc/disclaimer.html"&gt;Links setzen und sich davon distanzieren&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Boris Piwinger, &lt;a href="http://piology.org/dsr/linklehre.html"&gt;pi's kleine Linklehre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Christoph Schneegans, &lt;a href="http://schneegans.de/distanzierung-von-links/"&gt;Wirksamkeit von Disclaimern für Webseiten&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Im Dokument von &lt;cite&gt;Tim Berners-Lee&lt;/cite&gt; ist unter anderem folgender Abschnitt zu lesen:&lt;/p&gt;
&lt;blockquote cite="http://www.artikel5.de/archiv/tbl.html"&gt;
&lt;p&gt;Normale Hypertext Links implizieren nicht, daß das Dokument, auf das verwiesen wird,&lt;/p&gt;
&lt;ul class="para"&gt;
&lt;li&gt;Teil ist von,&lt;/li&gt;
&lt;li&gt;bestätigt wird von,&lt;/li&gt;
&lt;li&gt;bestätigt,&lt;/li&gt;
&lt;li&gt;eine verwandte Urheberschaft oder Bedingungen für die Weiterverbreitung hat&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;wie das Dokument, das den Verweis (Link) enthält.&lt;/p&gt;
&lt;/blockquote&gt;
In diesem Kontext sind alle von mir gesetzten Links zu verstehen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4194361870903955864-8702083883474211096?l=mllog.blogspot.com'/&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/8702083883474211096'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4194361870903955864/posts/default/8702083883474211096'/><link rel='alternate' type='text/html' href='http://mllog.blogspot.com/2007/04/alle-im-mllog-verffentlichten-texte.html' title='Impressum'/><author><name>Thomas Dohmke</name><uri>http://www.blogger.com/profile/05861278796383511356</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15778698596725981126'/></author></entry></feed>