Nachmachen hilft
Ein Test sollte möglichst wenig von anderen Bestandteilen des Systems abhängen, damit die Testsoftware eventuell auftretende Fehler auch an der richtigen Stelle meldet. In der Praxis bestehen aber in jedem System Abhängigkeiten, die das Testen schwieriger machen. Problematisch sind vor allem nicht immer verfügbare Ressourcen oder Funktionen, deren Aufruf unerwünschte Nebeneffekte hat. Je nach Art der Ressource muss der Programmierer hier andere Vorkehrungen zu treffen.
So genannte Mock-Objekte (Nachahmung) bieten die Möglichkeit, ein zu testendes Objekt von solchen Abhängigkeiten und Unwägbarkeiten zu isolieren, indem sie das Interface der benötigten Klasse nachahmen. Ein Mock ist also eine einfache Ersatzimplementation einer vom Produktionscode benötigten Klasse. Der Test parametrisiert ein Mock-Objekt mit den gewünschten Ein- und Ausgabewerten. Damit überprüft er, ob der getestete Code die richtigen Werte an das Objekt übergibt oder mit verschiedenen Rückgabewerten zurechtkommt. Mock-Objekte können auch ein praktischer Bestandteil des Test Driven Development sein, wenn man aus ihnen das Interface für den eigentlichen Produktionscode ableitet.
Selbstverständlich ist es keine Option, nur für den Test den Produktionscode zu verändern, damit statt des eigentlichen Objekts das Mock-Objekt aufgerufen wird. Schließlich sollen Unit-Tests automatisiert ablaufen. Um dieses Problem zu lösen, kann bereits im Produktionscode das entsprechende Objekt der Klasse als Parameter übergeben werden. Der Test übergibt stattdessen das Mock-Objekt an die Klasse. Dieser Ablauf erhöht aber möglicherweise die Komplexität des Code. Eine andere Lösung ist es, das Objekt nicht im Produktionscode zu initialisieren, sondern diesen Vorgang an eine eigene Methode zu delegieren. Die Testklasse wiederum überschreibt diese Methode, um das Mock-Objekt zurückzugeben. Ein Beispiel dazu findet sich inListing 3.
Es gibt mehrere Module, die die Erstellung von Mock-Objekten erleichtern. Flexmock[2] ist sehr einfach anzuwenden, bietet aber auch nur wenige Funktionen. Wer mehr Flexibilität benötigt, ist bei Test::Unit::Mock[3] gut aufgehoben. Beide sind als Rubygem[4] verfügbar. Die Installation gestaltet sich bei einem bereits vorhandenen Rubygems-Paket sehr einfach: »gem install flexmock« oder »gem install test-unit-mock«.
01 require 'test/unit'
02 require 'article'
03 require 'rubygems'
04 require_gem 'flexmock'
05
06 class Article
07 attr_accessor :mock
08 def createConnection
09 return @mock
10 end
11 end
12
13 class TestArticle < Test::Unit::TestCase
14 def setup
15 @article = Article.new
16 @year, @month = 2004,5
17 @url_base = 'http://www.linux-magazin.de' +
18 '/Artikel/ausgabe/' + sprintf('%s/%02d', @year, @month)
19 @no_content = 'keine verwertbaren Daten'
20 @html = <<html
21 <UL><li>Aktuell: News aus der Linux-Welt
22 <li><A href="userspace/userspace.html">Userspace-Dateisysteme</A>
23 </UL><UL><LI></UL>
24 html
25 end
26
27 def test_parse_articles_no_content
28 assert_nil(@article.parse_articles(@no_content))
29 end
30
31 def test_parse_articles
32 result = @article.parse_articles(@html)
33 assert_instance_of(Array, result)
34 assert_equal(2, result.length, 'falsche Anzahl an Artikeln')
35 end
36
37 def test_load_article_page
38 mock = FlexMock.new
39 mock.mock_handle(:get) { [nil, 'testhtml'] }
40 @article.mock = mock
41 html = @article.load_article_page(@year, @month)
42 assert_equal('testhtml', html)
43 end
44
45 def test_load_article_page_network_error
46 mock = FlexMock.new
47 mock.mock_handle(:get) { raise SocketError, 'Netzwerkfehler' }
48 @article.mock = mock
49 assert_raise(SocketError) { @article.load_article_page(@year,@month) }
50 end
51
52 def test_get_address
53 url = @article.send(:get_address, @year, @month, 'suffix')
54 assert_equal(@url_base + 'suffix', url)
55 end
56
57 def test_read_articles
58 mock = FlexMock.new
59 mock.mock_handle(:get) { |param|
60 assert_equal(@url_base + '/index_html?print=y', param, 'Falsche URL')
61 [nil, @html]
62 }
63 @article.mock = mock
64 result = @article.read_articles(@year, @month)
65 assert_equal('Userspace-Dateisysteme',result[1][0])
66 assert_equal(@url_base + '/userspace/userspace.html',result[1][1])
67 assert_equal(2, result.length, 'falsche Anzahl an Artikeln')
68 end
69
70 def test_read_articles_no_content
71 mock = FlexMock.new
72 mock.mock_handle(:get) { [nil, @no_content] }
73 @article.mock = mock
74 assert_nothing_raised { @article.read_articles(@year, @month) }
75 assert_instance_of(String, @article.read_articles(@year, @month))
76 end
77
78 def test_read_articles_network_error
79 mock = FlexMock.new
80 mock.mock_handle(:get) { raise SocketError, 'simulierter Netzwerkfehler' }
81 @article.mock = mock
82 assert_nothing_raised { @article.read_articles(@year, @month) }
83 assert_instance_of(String, @article.read_articles(@year, @month))
84 end
85 end
|
Internetzugriff testen
Ein Beispiel: Die Website des Linux-Magazins bietet die Inhaltsverzeichnisse aller Ausgaben seit 1994. Die Klasse »Article« (Listing 2) liest zu einer bestimmten Ausgabe die Titel der Artikel und - falls vorhanden - die URL des Artikelinhalts aus. Der Zugriff auf eine Quelle im Internet ist aber fehleranfällig und vergleichsweise langsam. Ein Mock-Objekt macht das Testbeispiel unabhängig von externen Ressourcen.
In der gekürzt abgebildeten Klasse »Article« in Listing 2 übernimmt die Methode »read_articles« Jahr und Monat des gewünschten Hefts und gibt eine Liste mit den Titeln und URLs der Artikel zurück. Der komplette Programmcode ist auf dem Server des Linux-Magazins verfügbar[6]. Die Testklasse in Listing 3 testet auf einige der wichtigsten Fehlerquellen wie fehlende Netzwerkverbindung oder nicht interpretierbare Rückgabewerte.
| Whitepaper |
|
Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele (Folge 2)
Der zweite Teil des Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele White Papers beleuchtet anhand weiterer ausgewählter Case Studies die Implementierung von Open Source Datenintegration in der Praxis und benennt die daraus resultierenden Vorteile.
Download PDF (Registrierung erforderlich)
|
|
Usage Landscape Enterprise Open Source Data Integration
Die Nachfrage nach Datenintegrationslösungen für Unternehmen ist zunehmend gestiegen und vor allem das Interesse an Open Source Technologien wird immer größer. Doch wie und von wem werden Open Source Datenintegrationslösungen genutzt und welches Nutzungsverhalten lässt sich daraus ableiten? Das vorliegende White Paper präsentiert die Erfahrungswerte von über 1000 Open Source Nutzern und liefert fundierte Antworten auf diese Fragen.
Download PDF (Registrierung erforderlich)
|
Dieser Online-Artikel kann Links enthalten, die auf nicht mehr vorhandene Seiten verweisen. Wir ändern solche "broken links"
nur in wenigen Ausnahmefällen. Der Online-Artikel soll möglichst unverändert der gedrucken Fassung entsprechen.
|