Probleme beim Zeitvergleich mit RSpec
Ich bin mit Ruby, Ruby on Rails 4 und der rspec-rails gem 2.14. Für mein Objekt würde ich gerne vergleichen der aktuellen Zeit mit der updated_at
Objekt-Attribut nach einer action ausgeführt wird, aber ich bin in Schwierigkeiten, da die spec nicht passieren. Das ist, da die folgenden ist der spec-code:
it "updates updated_at attribute" do
Timecop.freeze
patch :update
@article.reload
expect(@article.updated_at).to eq(Time.now)
end
Wenn ich die oben genannten Skillung bekomme ich die folgende Fehlermeldung:
Failure/Error: expect(@article.updated_at).to eq(Time.now)
expected: 2013-12-05 14:42:20 UTC
got: Thu, 05 Dec 2013 08:42:20 CST -06:00
(compared using ==)
Wie kann ich die Skillung zu bestehen?
Hinweis: ich habe versucht, auch die folgenden (beachten Sie die utc
Ergänzung):
it "updates updated_at attribute" do
Timecop.freeze
patch :update
@article.reload
expect(@article.updated_at.utc).to eq(Time.now)
end
aber die Skillung noch nicht bestanden hat (man beachte die "got" - Wert Differenz):
Failure/Error: expect(@article.updated_at.utc).to eq(Time.now)
expected: 2013-12-05 14:42:20 UTC
got: 2013-12-05 14:42:20 UTC
(compared using ==)
InformationsquelleAutor der Frage Backo | 2013-12-05
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ruby-Zeit-Objekt verwaltet eine größere Präzision als die Datenbank hat. Wenn der Wert wieder zu Lesen aus der Datenbank, es wird nur beibehalten, um Mikrosekunden-Genauigkeit, während die in-memory-Darstellung ist präzise bis Nanosekunden.
Wenn Sie kümmern sich nicht um Millisekunden-Unterschied, könnte man einen to_s/to_i auf beiden Seiten Ihrer Erwartung
oder
Finden diese für weitere Informationen, warum die Zeiten unterschiedlich sind
InformationsquelleAutor der Antwort usha
Finde ich mit der
be_within
Standard-rspec-matcher elegant:InformationsquelleAutor der Antwort Oin
Alte post, aber ich hoffe, es hilft wer tritt hier für eine Lösung. Ich denke, es ist einfacher und zuverlässiger zu erstellen die das Datum manuell ein:
Dies gewährleistet das gespeicherte Datum ist das richtige, ohne dabei
to_x
oder sich Gedanken über Dezimalzahlen.InformationsquelleAutor der Antwort jBilbo
Können Sie konvertieren Sie das Datum/datetime/time-Objekt in eine Zeichenfolge, wie es in der Datenbank gespeichert ist mit
to_s(:db)
.InformationsquelleAutor der Antwort Thomas Klemm
yep als
Oin
suggeriertbe_within
matcher ist die beste Praxis...und es hat etwas mehr uscases -> http://www.eq8.eu/blogs/27-rspec-be_within-matcher
Aber noch eine weitere Art und Weise, wie damit umzugehen ist die Verwendung von Schienen gebaut
midday
undmiddnight
Attribute.Nun, dies ist nur zur demonstration !
Ich würde nicht verwenden Sie diese in einem controller, wie Sie sind stubbing alle Zeit.die neuen Aufrufe => alle Attribute haben gleichen Zeit => kann nicht beweisen Konzept, das Sie versuchen zu erreichen. Normalerweise verwende ich es in der komponierten Ruby-Objekte ähnlich wie diese:
Aber ehrlich gesagt, ich empfehlen, kleben mit
be_within
matcher auch beim Vergleich der Zeit.nun.Mittag !Also ja pls stick mit
be_within
matcher 😉update 2017-02
Frage im Kommentar:
können Sie weitergeben, RSpec-matcher, um die
match
matcher(also z.B. man kann sogar API-Test mit reinem RSpec)
Als für "post-db-mal" - ich denke mal du meinst string, der generiert wird, nachdem speichern in der DB. Ich würde vorschlagen, entkoppeln diesem Fall um 2 Erwartungen (sicherstellen, dass die hash-Struktur, die zweite Prüfung der Zeit) So etwas wie:
Aber wenn dieser Fall auch oft in der test-suite würde ich vorschlagen, schreiben Sie Ihre eigene RSpec-matcher (z.B.
be_near_time_now_db_string
) Umwandlung von db-string, Zeit, Zeit, Objekt und verwenden Sie dies als Teil desmatch(hash)
:InformationsquelleAutor der Antwort equivalent8
Die einfachste Möglichkeit, die ich gefunden, um dieses problem zu schaffen, ist eine
current_time
test-helper-Methode wie folgt:Nun die Zeit wird immer gerundet auf die nächste Millisekunde auf-Vergleiche sind einfach:
InformationsquelleAutor der Antwort Sam Davies