Frage

Wenn Code in Java zu schreiben, ist es sehr hilfreich zu umarmen Zusammensetzung und Dependency Injection durch spöttische Zusammenarbeit Objekte, die es möglich und einfach zu tun reine Unit-Tests zu machen.

Ich finde, dass das gleiche in Erlang tut, ist weniger einfach und für dreckigen Code macht.

Das ist wahrscheinlich meine Schuld sein, da ich ganz neu in Erlang bin und ziemlich süchtig nach JUnit, EasyMock und Java-Schnittstellen ...

Lassen Sie uns sagen, ich habe diese dumme Funktion:

%% module mymod
handle_announce(Announce) ->
    AnnounceDetails = details_db:fetch_details(Announce),
    AnnounceStats = stats_db:fetch_stats(Announce),
    {AnnounceDetails, AnnounceStats}.

Wenn Unit-Tests mymod, ich nur, dass details_db und stats_db beweisen will, sind mit den richtigen Parametern aufgerufen wird, und dass die Rückgabewerte verwendet werden, korrekt. Die Fähigkeit von details_db und stats_db richtigen Wert zu erzeugen, ist in anderen Orten getestet.

Um das Problem zu lösen, könnte ich meinen Code auf diese Weise Refactoring:

%% module mymod
handle_announce(Announce, [DetailsDb, StatsDb]) ->
    AnnounceDetails = DetailsDb:fetch_details(Announce),
    AnnounceStats = StatsDb:fetch_stats(Announce),
    {AnnounceDetails, AnnounceStats}.

Und testen Sie es auf diese Weise (im Grunde die Anrufe direkt in das Testmodul stubbing):

%% module mymod_test
handle_announce_test() ->
    R = mymod:handle_announce({announce, a_value}, [?MODULE, ?MODULE, ?MODULE]),
    ?assertEqual({details,stats}, R).

fetch_details({announce, a_value}) ->
    details.

fetch_stats({announce, a_value}) ->
    stats.

Es funktioniert, aber der Anwendungscode wird schmutzig, und ich muss immer um diese hässliche Liste der Module tragen.

Ich habe ein paar Mock Bibliotheken versucht ( erlymock und ( dieses andere ), aber ich war nicht zufrieden.

Wie testen Sie Ihr Gerät erlang Code?

Danke!

War es hilfreich?

Lösung

Es gibt zwei Dinge zu beachten, hier ...

Sie müssen Ihren Code alle in 2 trennen verschiedene Arten von Module :

  • reine Funktionsmodule (auch bekannt als nebenwirkungsfreie Module)
  • Module mit Nebenwirkungen

(Sie sollten das lesen und sicher sein, dass Sie den Unterschied zu verstehen - die typischen Nebeneffekt - und die, die in Ihrem Beispielcode ist - in die Datenbank zu schreiben).

Die Module, die zu testen rein funktional geworden trivial sind. Jede exportierte Funktion (per Definition) gibt immer die gleichen Werte, wenn die gleichen Werte in gesetzt werden. Sie können die EUnit / Behaupten Rahmen, Richard Carlsson und Mickael Remond schrieb. Bish-bash-bosh, Job ist ein guter ‚un ...

Das Wichtigste ist, dass etwa 90% des Codes in reiner Funktionsmodule sein sollte - Sie drastisch Ihr Problem schrumpfen. (Man könnte denken, dies ist nicht ‚Lösung‘ Ihr Problem, nur ‚reduzieren‘ es - und Sie würden meist recht sein ...)

Wenn Sie diese Trennung erreicht haben, um Unit-Test den besten Weg, um die Module mit Nebenwirkungen ist das Standard-Test-Framework .

Die Art, wie wir dies tun, ist nicht Mock-Objekte zu verwenden - aber die Datenbank im init_per_suite oder init_per_test Funktionen zu laden und dann die Module selbst läuft ...

Der beste Weg ist direkt über die Systemtests zu bewegen, so bald wie möglich für diese allerdings wie die Unit-Tests ein Schmerz zu pflegen - so genug Unit-Tests Sie zu einem System-Test Round-Trip zu bekommen und nicht mehr ( noch besser auf die db Unit-Tests so schnell wie möglich) löschen.

Andere Tipps

Ich Sekunde, was Guthrie sagt. Sie werden, wie viel von Ihrer Logik überrascht werden kann, hinaus in reine Funktionen gezogen werden.

Eines der Dinge, die ich habe in letzter Zeit mit dem neuen parametrisierte Module wurde zu binden ist paramterized Module für die Dependency Injection zu verwenden. Es vermeidet das Problem mit Parameterlisten und Prozess Wörterbücher. Wenn Sie die aktuellen Versionen von erlang verwenden, die auch eine gute Passform sein könnte.

Gordon ist richtig, dass das Hauptziel ist es, die kleinen Nebeneffekt freien Funktionen zu testen.

Aber ... na ja, es ist möglich, die Integration als auch zu testen, kann so zeigen, wie man das tun kann.

Injektion

Listen Vermeiden Sie die parametrisierte Abhängigkeiten zu tragen. Verwenden Sie einen Datensatz, den Prozess Wörterbuch, parametrisierte Module. Der Code wird weniger hässlich.

Seams

Konzentrieren Sie sich nicht auf variable Module als Abhängigkeit Nähte, lassen Sie Prozesse aus allen Nähten. Hartcodierung ein eingetragener Prozessname ist eine verlorene Chance auf eine Abhängigkeit injiziert wird.

Ich antworte nur die Frage direkt und nicht versuchen, gefragt zu werden, um zu beurteilen, ob der Autor soll dies überhaupt tun.

Mit meck einen Komponententest für Sie beispielsweise schreiben können wie folgt:

handle_announce_test() ->
    %% Given
    meck:new([details_db, stats_db]),
    meck:expect(details_db, fetch_details, ["Announce"], "AnnounceDetails"),
    meck:expect(stats_db, fetch_stats, ["Announce"], "AnnounceStats"),
    %% When
    Result = handle_announce("Announce"),
    %% Then
    ?assertMatch({"AnnounceDetails", "AnnounceStats"}, Result),
    %% Cleanup
    meck:unload().

I-Strings nur Betonung verwenden, dass sie nicht etwas, das in wirklich, sondern eine Fälschung Wert übergeben wird. Dank Syntax Highlight sind sie einfach in den Test-Code zu erkennen.

Um ehrlich zu sein ich bin ein ehemaliger Java-Entwickler tief in der Liebe mit Mockito vor kurzem wechselte zu Erlang, und nun zu dem oben genannten Projekt beitragen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top