Was sind die Best Practices zum Testen von Modulen in rspec? Ich habe einige Module, die in wenigen Modellen enthalten sind, und im Moment habe ich einfach doppelte Tests für jedes Modell (mit wenigen Unterschieden). Gibt es eine Möglichkeit, es auszutrocknen?
ruby
unit-testing
rspec
Andrius
quelle
quelle
let(:dummy_class) { Class.new { include ModuleToBeTested } }
let(:class_instance) { (Class.new { include Super::Duper::Module }).new }
diese Weise erhalte ich die Instanzvariable, die am häufigsten zum Testen verwendet wird.include
funktioniert nicht für mich, aberextend
funktioniertlet(:dummy_class) { Class.new { extend ModuleToBeTested } }
subject(:instance) { Class.new.include(described_class).new }
Was Mike gesagt hat. Hier ist ein triviales Beispiel:
Modulcode ...
Spezifikationsfragment ...
quelle
include Say
Gibt es einen Grund, warum Sie nicht in der DummyClass-Deklaration waren, anstatt anzurufenextend
?extend
in die Instanz der Klasse ein, dh nachdemnew
er gerufen wurde. Wenn Sie dies getan haben, bevornew
aufgerufen wird, dann haben Sie Recht, Sie würden verwendeninclude
DummyClass
Konstante definieren ? Warum nicht einfach@dummy_class = Class.new
? Jetzt verschmutzen Sie Ihre Testumgebung mit einer unnötigen Klassendefinition. Diese DummyClass ist für jede einzelne Ihrer Spezifikationen definiert. In der nächsten Spezifikation, in der Sie denselben Ansatz verwenden und die DummyClass-Definition erneut öffnen, enthält sie möglicherweise bereits etwas (obwohl in diesem trivialen Beispiel die Definition im wirklichen Leben streng leer ist Anwendungsfälle Es ist wahrscheinlich, dass irgendwann etwas hinzugefügt wird und dieser Ansatz dann gefährlich wird.)Für Module, die isoliert oder durch Verspotten der Klasse getestet werden können, gefällt mir Folgendes:
Modul:
spec:
Es mag falsch erscheinen, verschachtelte Beispielgruppen zu entführen, aber ich mag die Knappheit. Irgendwelche Gedanken?
quelle
let
von @metakungfu beschriebene Methode ist besser.Ich habe eine bessere Lösung auf der rspec-Homepage gefunden. Anscheinend unterstützt es gemeinsame Beispielgruppen. Von https://www.relishapp.com/rspec/rspec-core/v/2-13/docs/example-groups/shared-examples !
quelle
Könnten Sie auf den ersten Blick eine Dummy-Klasse in Ihrem Testskript erstellen und das Modul in dieses aufnehmen? Testen Sie dann, ob die Dummy-Klasse das erwartete Verhalten aufweist.
BEARBEITEN: Wenn das Modul, wie in den Kommentaren erwähnt, erwartet, dass einige Verhaltensweisen in der Klasse vorhanden sind, in die es gemischt ist, würde ich versuchen, Dummies dieser Verhaltensweisen zu implementieren. Gerade genug, um das Modul glücklich zu machen, seine Aufgaben zu erfüllen.
Trotzdem wäre ich etwas nervös wegen meines Designs, wenn ein Modul eine ganze Menge von seiner Host-Klasse erwartet (sagen wir "Host"?) - Wenn ich nicht bereits von einer Basisklasse erbe oder nicht injizieren kann Die neue Funktionalität in den Vererbungsbaum, dann würde ich versuchen, solche Erwartungen, die ein Modul haben könnte, zu minimieren. Ich befürchte, dass mein Design einige Bereiche unangenehmer Inflexibilität entwickeln könnte.
quelle
Die akzeptierte Antwort ist meiner Meinung nach die richtige Antwort. Ich wollte jedoch ein Beispiel für die Verwendung von rpsecs
shared_examples_for
undit_behaves_like
Methoden hinzufügen . Ich erwähne einige Tricks im Code-Snippet, aber für weitere Informationen siehe diese relishapp-rspec-Anleitung .Damit können Sie Ihr Modul in jeder der Klassen testen, die es enthalten. Sie testen also wirklich, was Sie in Ihrer Anwendung verwenden.
Sehen wir uns ein Beispiel an:
Jetzt erstellen wir eine Spezifikation für unser Modul:
movable_spec.rb
quelle
Wie wäre es mit:
quelle
Ich würde vorschlagen, dass man sich für größere und häufig verwendete Module für die "Shared Example Groups" entscheiden sollte, wie von @Andrius hier vorgeschlagen . Für einfache Dinge, für die Sie nicht die Mühe haben möchten, mehrere Dateien usw. zu haben, erfahren Sie hier, wie Sie die maximale Kontrolle über die Sichtbarkeit Ihrer Dummy-Sachen gewährleisten (getestet mit rspec 2.14.6, kopieren Sie einfach den Code und fügen Sie ihn in ein ein Spezifikationsdatei und führen Sie es aus):
quelle
subject { dummy_class.new }
funktioniert nur. Der Fall mitsubject { dummy_class }
funktioniert bei mir nicht.meine jüngste Arbeit mit so wenig Kabel wie möglich
Ich wünsche
hat funktioniert, aber nicht (wie bei Ruby MRI 2.2.3 und RSpec :: Core 3.3.0)
Offensichtlich ist die beschriebene Klasse in diesem Bereich nicht sichtbar.
quelle
Verwenden Sie zum Testen Ihres Moduls:
Um einige Dinge, die Sie in mehreren Spezifikationen verwenden, auszutrocknen, können Sie einen gemeinsamen Kontext verwenden:
Ressourcen:
quelle
Sie können auch den Hilfstyp verwenden
Hier ist die Dokumentation: https://www.relishapp.com/rspec/rspec-rails/v/3-3/docs/helper-specs/helper-spec
quelle
Sie müssen Ihr Modul einfach in Ihre Spezifikationsdatei
mudule Test module MyModule def test 'test' end end end
in Ihre Spezifikationsdatei aufnehmenRSpec.describe Test::MyModule do include Test::MyModule #you can call directly the method *test* it 'returns test' do expect(test).to eql('test') end end
quelle
Eine mögliche Lösung zum Testen von Modulmethoden, die unabhängig von der Klasse sind, in der sie enthalten sind
Und spezifizieren Sie dafür
Und wenn Sie sie DRY testen möchten, ist shared_examples ein guter Ansatz
quelle
subject(:module_to_test_instance) { Class.new.include(described_class) }
. Ansonsten sehe ich mit Ihrer Antwort nichts falsches.Dies ist ein wiederkehrendes Muster, da Sie mehr als ein Modul testen müssen. Aus diesem Grund ist es mehr als wünschenswert, einen Helfer dafür zu erstellen.
Ich habe diesen Beitrag gefunden , in dem erklärt wird, wie es geht, aber ich komme hier zurecht, da die Site möglicherweise irgendwann heruntergefahren wird.
Um zu vermeiden, dass die Objektinstanzen die Instanzmethode nicht implementieren :: welcher Fehler auch immer auftritt, wenn Sie versuchen,
allow
Methoden für diedummy
Klasse zu verwenden.Code:
Im
spec/support/helpers/dummy_class_helpers.rb
Im
spec/spec_helper.rb
In Ihren Spezifikationen:
quelle