Private Methode in Funktionalem Test überprüfen


#1

Hallo,

ich arbeite mich gerade in der Testgetriebenen Entwicklung ein und habe
noch etwas Startschwierigkeiten.

In einem Controller habe ich folgende (private) Methode angelegt:

private
def get_geocode(address)
g = GeoKit::Geocoders::MultiGeocoder.geocode(address)
return {:success => true, :lat => g.lat, :lng => g.lng, :city =>
g.city }
end

Um die korrekte Funktion dieser Methode zu testen, habe ich in der Datei
*_controller_test.rb folgenden Test geschrieben:

test “should get city from geocode” do
geocode = “52.409645,13.059826”
location = get_geocode(geocode)

assert_equal "Potsdam", assigns(:location)

end

Beim Ausführen des Tests, erhalte ich die Fehlermeldung:

  1. Error:
    test_should_get_city_from_geocode(HotspotsControllerTest):
    NoMethodError: undefined method `get_geocode’ for
    #HotspotsControllerTest:0x243f5ec

Kann ich in Funktionalen Tests überhaupt private Methoden testen?

Viele Grüße,
Christian


#2

Hallo,

Am 01.02.2009 um 11:01 schrieb Christian Beier:

test “should get city from geocode” do
geocode = “52.409645,13.059826”
location = get_geocode(geocode)

assert_equal “Potsdam”, assigns(:location)
end

Beim Ausführen des Tests, erhalte ich die Fehlermeldung:

  1. Error:
    test_should_get_city_from_geocode(HotspotsControllerTest):
    NoMethodError: undefined method `get_geocode’ for
    #HotspotsControllerTest:0x243f5ec

Kann ich in Funktionalen Tests überhaupt private Methoden testen?

Ich sehe 2 Probleme. Zum einen rufst Du die Methode ja gar nicht auf
dem Controller-Objekt auf (das wäre dann eher
@controller.get_geocode()) und zum anderen ist die Methode wie Du
anmerktest private. Das kann man theoretisch umgehen:

@controller.send(:get_geocode, geocode)

Allerdings ist das ein typischer Code-Smell. Grundsätzlich würde ich 2
Dinge dazu anmerken (Wenn Sie erlauben, Sir):

  • private Methoden in funktionalen Tests abtesten zu wollen ist ein
    Code Smell. Funktionale Tests sollten (so sehe ich das) den Controller
    “von aussen” testen. Es sind eben KEINE Unit-Tests. Du müsstest also
    eher die Actions, die diese Methode verwenden auf ihre richtige
    Funktion testen.

  • Das ganze riecht allerdings danach als wäre die Methode
    grundsätzlich im Controller falsch aufgehoben, da es sich vermutlich
    um Domänen-Logik (klingt furchtbar auf deutsch, finde ich) handelt,
    die üblicherweise ins Modell gehört. Wenn ich Deinen Code richtig aus
    Deinen Schnippseln extrapoliere klingt das alles danach als würdest Du
    eigentlich auf Deinem Modell ein virtuelles Attribute “geocode”
    anlegen wollen, was genau das macht, was bei Dir die Methode macht.

Hoffe gehulfen zu haben und

Gruß,

Jan


#3

Jan Krutisch wrote:

  • private Methoden in funktionalen Tests abtesten zu wollen ist ein
    Code Smell. Funktionale Tests sollten (so sehe ich das) den Controller
    “von aussen” testen. Es sind eben KEINE Unit-Tests. Du m�sstest also
    eher die Actions, die diese Methode verwenden auf ihre richtige
    Funktion testen.

Ja, du hast natürlich recht. Ich wollte mit dem Test erst einmal
“kleinteilig” die korrekte Funktion bzw. korrekten Rückgabewert testen.
Da der Kram aber eh ins Model gehört, kann das ja über Unit Tests
erledigt werden.

Wie gesagt, ich beschäftige mich erst frisch mit Test und Rails
überhaupt. Im Moment muss ich auch erst noch herausfinden wie fein das
Testnetz geschrieben werden sollte, damit es a) nicht unnötig viele
werden und b) Sachen ungetestet bleiben und sich so doch Fehler
einschleichen können. So eine richtig gute Abhandlung die die
Testgetriebene Entwicklung in allen Bereichen behandelt (und auch das
Zusammenspiel), habe ich leider noch nicht gefunden.

  • Das ganze riecht allerdings danach als w�re die Methode
    grunds�tzlich im Controller falsch aufgehoben, da es sich vermutlich
    um Dom�nen-Logik (klingt furchtbar auf deutsch, finde ich) handelt,
    die �blicherweise ins Modell geh�rt. Wenn ich Deinen Code richtig aus
    Deinen Schnippseln extrapoliere klingt das alles danach als w�rdest Du
    eigentlich auf Deinem Modell ein virtuelles Attribute “geocode”
    anlegen wollen, was genau das macht, was bei Dir die Methode macht.

Ich dachte mir schon, das die Mehode im Controller nicht wirklich gut
aufgehoben ist. Es geht mir in der Methode grundsätzlich darum, weitere
Parameter zu einer Ortsangabe zu erhalten. In diesem Fall also aus
Geokoordinaten, möchte ich den Ort erhalten, um diesen in einem View
auszugeben.

Einfach die geschriebene Methode

def get_geocode(address)
g = MultiGeocoder.geocode(address)
return {:success => true, :lat => g.lat, :lng => g.lng, :city =>
g.city }
end

in das Model zu packen funktioniert ja (wohl) nicht. Zumindest bekomme
ich es so nicht vom Controller aus angesprochen (Hotspot.get_geocode) ->
NoMethodError: undefined method `get_geocode’ for #Class:0x243b438

Grüße,
Christian


#4

Hallo,

wenn du die Methode “get_geocode” auf der Klasse “Hotspot” rufen
möchtest, solltest du die Methode mit einem vorangeschriebenen “self.”
definieren, damit sie im Klassen-Kontext ausgeführt werden kann. Also
sowas in der Art:

def self.get_geocode(address)
g = MultiGeocoder.geocode(address)
return {:success => true, :lat => g.lat, :lng => g.lng, :city =>
g.city }
end

Schöne Grüße,
Benjamin

Am 01.02.2009 um 15:43 schrieb Christian Beier:


#5

Hallo Christian,

So eine richtig gute Abhandlung die die
Testgetriebene Entwicklung in allen Bereichen behandelt (und auch das
Zusammenspiel), habe ich leider noch nicht gefunden.

unter folgender URL hab ich gestern ein PDF entdeckt, welches dir beim
Einsteig in TDD bestimmt weiterhelfen kann.

http://www.railsprescriptions.com/

Viele
Grüße,Sven


#6

Benjamin Behr | mindmatters wrote:

wenn du die Methode “get_geocode” auf der Klasse “Hotspot” rufen
möchtest, solltest du die Methode mit einem vorangeschriebenen “self.”
definieren, damit sie im Klassen-Kontext ausgeführt werden kann. Also
sowas in der Art:

def self.get_geocode(address)
g = MultiGeocoder.geocode(address)
return {:success => true, :lat => g.lat, :lng => g.lng, :city =>
g.city }
end

Schöne Grüße,
Benjamin

Vielen Dank für die Hilfe. Jetzt habe ich wieder was gelernt :wink:

Sven K. wrote:

Hallo Christian,

So eine richtig gute Abhandlung die die
Testgetriebene Entwicklung in allen Bereichen behandelt (und auch das
Zusammenspiel), habe ich leider noch nicht gefunden.

unter folgender URL hab ich gestern ein PDF entdeckt, welches dir beim
Einsteig in TDD bestimmt weiterhelfen kann.

http://www.railsprescriptions.com/

Viele
Gr��e,Sven

Danke für den Tipp. Ich habe mir gerade das PDF heruntergeladen und
werde es mir mal in Ruhe durchlesen. Es sieht aber schon sehr hilfreich
aus und wird die noch offenen Fragen klären und mir etwas mehr
Sicherheit darüber geben, was in Tests getestet werden sollte.

Viele Grüße,
Christian