Ist es idiomatisch, Ruby eine assert () -Methode zu Rubys Kernel-Klasse hinzuzufügen?

74

Ich erweitere mein Ruby-Verständnis, indem ich ein Äquivalent von Kent Becks xUnit in Ruby codiere. Python (in das Kent schreibt) hat eine assert () -Methode in der Sprache, die häufig verwendet wird. Ruby nicht. Ich denke, es sollte einfach sein, dies hinzuzufügen, aber ist Kernel der richtige Ort, um es zu platzieren?

Übrigens, ich kenne die Existenz der verschiedenen Unit-Frameworks in Ruby - dies ist eine Übung, um die Ruby-Redewendungen zu lernen, anstatt "etwas zu erledigen".

Andrew Harmel-Law
quelle
5
Ich mag Probleme, die beides bewirken: Sie unterrichten und etwas erledigen. :)
Ian Terrell

Antworten:

106

Nein, es ist keine bewährte Methode. Die beste Analogie zu assert () in Ruby ist nur das Erhöhen

 raise "This is wrong" unless expr

und Sie können Ihre eigenen Ausnahmen implementieren, wenn Sie eine spezifischere Ausnahmebehandlung bereitstellen möchten

Julik
quelle
28
fail if [expr]Wenn Sie möchten, können Sie auch einen Laufzeitfehler verwenden.
Xiong Chiamiov
6
failist ein Alias ​​für raise, nicht wahr? Sie geben beide RuntimeError. (Vielleicht ist einer idiomatischer?)
Benjamin Oakes
5
Es ist gut, wenn Ihre Software in der Produktion hart und schnell ausfällt. Ich halte stillgelegte Ausnahmen für eine schreckliche Kopie der Problemumgehung "Alle Ausnahmen abfangen". Es ist normalerweise das erste schreckliche Pflaster, das auf schrecklichen Code angewendet wird, wenn Dinge kaputt gehen.
Julik
2
Behauptungen und Ausnahmen sind verschiedene Dinge.
Jack Casey
6
@nus Behauptungen dienen nicht der Warnung, sondern der Sicherstellung, dass an diesem Ort immer etwas wahr ist. Wenn Ihre Behauptung in der Produktion fehlschlägt, möchten Sie auf jeden Fall abbrechen.
Yarin
30

Ich denke, es ist absolut gültig, Asserts in Ruby zu verwenden. Aber Sie erwähnen zwei verschiedene Dinge:

  • xUnit-Frameworks verwenden assertMethoden zur Überprüfung Ihrer Testerwartungen. Sie sollen in Ihrem Testcode verwendet werden, nicht in Ihrem Anwendungscode.
  • Einige Sprachen wie C, Java oder Python enthalten eine assertKonstruktion, die im Code Ihrer Programme verwendet werden soll, um die von Ihnen getroffenen Annahmen über deren Integrität zu überprüfen. Diese Überprüfungen werden im Code selbst erstellt. Sie sind kein Dienstprogramm zur Testzeit, sondern ein Dienstprogramm zur Entwicklungszeit.

Ich habe kürzlich solid_assert geschrieben: eine kleine Ruby-Bibliothek, die ein Ruby-Assertion-Dienstprogramm implementiert, sowie einen Beitrag in meinem Blog, in dem die Motivation erläutert wird .

assert some_string != "some value"
assert clients.empty?, "Isn't the clients list empty?"

invariant "Lists with different sizes?" do
    one_variable = calculate_some_value
    other_variable = calculate_some_other_value
    one_variable > other_variable
end    

Und sie können so deaktiviert assertund invariantals leere Anweisungen ausgewertet werden. Auf diese Weise können Sie Leistungsprobleme in der Produktion vermeiden. Beachten Sie jedoch, dass die Pragmatischen Programmierer davon abraten, sie zu deaktivieren. Sie sollten sie nur deaktivieren, wenn sie sich wirklich auf die Leistung auswirken.

In Bezug auf die Antwort, dass der idiomatische Ruby-Weg eine normale raiseAussage verwendet, denke ich, dass es an Ausdruckskraft mangelt. Eine der goldenen Regeln der durchsetzungsfähigen Programmierung besteht darin, keine Zusicherungen für die normale Ausnahmebehandlung zu verwenden. Das sind zwei völlig verschiedene Dinge. Wenn Sie für beide dieselbe Syntax verwenden, wird Ihr Code meiner Meinung nach dunkler. Und natürlich verlieren Sie die Fähigkeit, sie zu deaktivieren.

Sie können davon überzeugt sein, dass die Verwendung von Behauptungen eine gute Sache ist, da zwei klassische Bücher wie The Pragmatic Programmer From Journeyman to Master und Code Complete ihnen ganze Abschnitte widmen und ihre Verwendung empfehlen. Es gibt auch einen schönen Artikel mit dem Titel Programmieren mit Behauptungen , die sehr gut veranschaulichen, worum es bei durchsetzungsfähiger Programmierung geht und wann sie verwendet werden soll (sie basiert auf Java, aber Konzepte gelten für jede Sprache).

jmanrubia
quelle
Ich würde auch "Writing Solid Code" von Steve Maguire vorschlagen, das extrem C-orientiert ist, aber über Behauptungen, Teststrategien und Ideen zur Konstruktion von Funktionen spricht, die auch für die Methodenkonstruktion gelten.
Paul Kroll
14

Was ist Ihr Grund, die Assert-Methode zum Kernel-Modul hinzuzufügen? Warum nicht einfach ein anderes Modul namens Assertionsoder so verwenden?

So was:

module Assertions
  def assert(param)
    # do something with param
  end

  # define more assertions here
end

Wenn Sie wirklich möchten, dass Ihre Behauptungen überall verfügbar sind, gehen Sie wie folgt vor:

class Object
  include Assertions
end

Haftungsausschluss: Ich habe den Code nicht getestet, aber im Prinzip würde ich es so machen.

Christoph Schiessl
quelle
1
Flickt dieser Affe nicht? Sie ändern die ObjectKlasse.
Tsikov
Ja, das ist klassisches Affen-Patching. Das ist der Weg, wenn Sie die assertMethode wirklich global verfügbar machen müssen. Ich würde jedoch niemandem raten, solche Affen-Patches in Nicht-Spielzeug-Projekten zu verwenden.
Christoph Schiessl
7

Es ist nicht besonders idiomatisch, aber ich denke, es ist eine gute Idee. Besonders wenn es so gemacht wird:

def assert(msg=nil)
    if DEBUG
        raise msg || "Assertion failed!" unless yield
    end
end

Auf diese Weise hat dies keine Auswirkungen, wenn Sie sich entscheiden, nicht mit DEBUG (oder einem anderen praktischen Schalter, den ich in der Vergangenheit mit Kernel.do_assert verwendet habe) zu arbeiten.

regelmäßig
quelle
5

Meines Wissens nach schreiben Sie Ihre eigene Testsuite, um sich mit Ruby vertraut zu machen. Während Test :: Unit als Leitfaden nützlich sein kann, ist es wahrscheinlich nicht das, wonach Sie suchen (weil es die Arbeit bereits erledigt hat).

Das heißt, Pythons Behauptung ist (zumindest für mich) analoger zu Cs Behauptung (3) . Es wurde nicht speziell für Unit-Tests entwickelt, sondern um Fälle zu erfassen, in denen "dies niemals passieren sollte".

Rubys integrierte Komponententests sehen das Problem in der Regel so, dass jede einzelne Testfallklasse eine Unterklasse von TestCase ist und eine "assert" -Anweisung enthält , die die Gültigkeit der übergebenen Tests überprüft und aufzeichnet Berichterstattung.

Atiaxi
quelle