¿Cuál es la mejor manera de establecer Time.now
con el fin de probar métodos sensibles al tiempo en una prueba unitaria?Cómo falsificar Time.now?
Respuesta
Haga lo time-warp
tiempo de cápsula es una biblioteca que hace lo que quiere. Te da un método que toma un tiempo y un bloque y todo lo que sucede en el bloque usa el tiempo falso.
pretend_now_is(2000,"jan",1,0) do
Time.now
end
Personalmente prefiero hacer el inyectable de reloj, así:
def hello(clock=Time)
puts "the time is now: #{clock.now}"
end
O:
class MyClass
attr_writer :clock
def initialize
@clock = Time
end
def hello
puts "the time is now: #{@clock.now}"
end
end
Sin embargo, muchos prefieren usar una biblioteca/stubbing burla. En RSpec/flexmock puede utilizar:
Time.stub!(:now).and_return(Time.mktime(1970,1,1))
O en Mocha:
Time.stubs(:now).returns(Time.mktime(1970,1,1))
La parte de prueba es exactamente el tipo de respuesta que iba a proporcionar. – nitecoder
Esto es totalmente lo que habría hecho también. Si escribe su código de una manera que lo haga fácil de probar, no tiene que hacer cosas arcanas para hacerlo comprobable. –
Si bien estoy de acuerdo con la idea general de escribir cosas de una manera más comprobable, hay ocasiones en que simplemente no es práctico. Y Time.now es uno de esos ejemplos. se puede usar en muchas partes del sistema y pasarlo todo el tiempo será demasiado alto. –
me gusta mucho la biblioteca Timecop. Usted puede hacer el tiempo deforma en forma de bloques (como tiempo de cápsula):
Timecop.travel(6.days.ago) do
@model = TimeSensitiveMode.new
end
assert @model.times_up!
(Sí, puede anidar viaje en el tiempo en forma de bloque.)
También se puede hacer viajes en el tiempo declarativa:
class MyTest < Test::Unit::TestCase
def setup
Timecop.travel(...)
end
def teardown
Timecop.return
end
end
Tengo algunos ayudantes cucumber para Timecop here. Ellos le permiten hacer cosas como:
Given it is currently January 24, 2008
And I go to the new post page
And I fill in "title" with "An old post"
And I fill in "body" with "..."
And I press "Submit"
And we jump in our Delorean and return to the present
When I go to the home page
I should not see "An old post"
¿Debería haber una comilla al final de la última prueba? –
Estos ayudantes se han puesto en una gema: https://github.com/zedtux/cucumber-timecop – approxiblue
Este tipo de obras y permite la anidación:
class Time
class << self
attr_accessor :stack, :depth
end
def self.warp(time)
Time.stack ||= []
Time.depth ||= -1
Time.depth += 1
Time.stack.push time
if Time.depth == 0
class << self
alias_method :real_now, :now
alias_method :real_new, :new
define_method :now do
stack[depth]
end
define_method :new do
now
end
end
end
yield
Time.depth -= 1
Time.stack.pop
class << self
if Time.depth < 0
alias_method :new, :real_new
alias_method :now, :real_now
remove_method :real_new
remove_method :real_now
end
end
end
end
Podría ser ligeramente mejorada por undefing los descriptores de acceso de pila y profundidad al final
Uso :
time1 = 2.days.ago
time2 = 5.months.ago
Time.warp(time1) do
Time.real_now.should_not == Time.now
Time.now.should == time1
Time.warp(time2) do
Time.now.should == time2
end
Time.now.should == time1
end
Time.now.should_not == time1
Time.now.should_not be_nil
Dependiendo de lo que compare Time.now
, a veces yo Puedes cambiar tus accesorios para lograr el mismo objetivo o probar la misma función. Por ejemplo, tuve una situación en la que necesitaba que sucediera algo si alguna fecha estaba en el futuro y otra que sucedería si era en el pasado. Lo que pude hacer fue incluir en mis accesorios de algunos de rubí incrustado (erb):
future:
comparing_date: <%= Time.now + 10.years %>
...
past:
comparing_date: <%= Time.now - 10.years %>
...
Luego, en sus pruebas y luego a elegir cuál usar para probar las diferentes funciones o acciones basadas en el tiempo en relación con Time.now
.
También vea this question donde pongo este comentario también.
Según lo que esté comparando Time.now
, a veces puede cambiar sus dispositivos para lograr el mismo objetivo o probar la misma función.Por ejemplo, tuve una situación en la que necesitaba que sucediera algo si alguna fecha estaba en el futuro y otra que sucedería si era en el pasado. Lo que pude hacer fue incluir en mis accesorios de algunos de rubí incrustado (erb):
future:
comparing_date: <%= Time.now + 10.years %>
...
past:
comparing_date: <%= Time.now - 10.years %>
...
Luego, en sus pruebas y luego a elegir cuál usar para probar las diferentes funciones o acciones basadas en el tiempo en relación con Time.now
.
Gracias, encontré esto mucho más elegante que falsificar Time.now. Sus pruebas también asegurarán que no haya ninguna fecha de codificación fija en ninguna parte y su código aún funciona como se espera el día que lo ejecute – Benoit
Estoy usando RSpec y lo hice: Time.stub! (: Ahora) .and_return (2.days.ago) antes de que llame a Time.now. De ese modo soy capaz de controlar el tiempo que he usado para este caso prueba en particular
¿No cambiarían sus pruebas con el tiempo? ¿Tienes algún ejemplo? – Trip
por ej. si tengo un sistema de alquiler, quiero probar si el sistema cobra una multa si el día en que se devuelve el artículo es tarde, tendré que manipular Time.now para que cuando se devuelva el artículo, sea tarde. .. no estoy seguro de si me entiendes – Staelen
acabo de esto en mi archivo de prueba:
def time_right_now
current_time = Time.parse("07/09/10 14:20")
current_time = convert_time_to_utc(current_date)
return current_time
end
y en mi archivo Time_helper.rb tengo un
def time_right_now
current_time= Time.new
return current_time
end
así que cuando se prueba el time_right_now se sobrescribe para usar la hora que desee.
Siempre extraigo Time.now
en un método separado que me convierto en attr_accessor
en el simulacro.
No olvide que Time
es simplemente una constante que hace referencia a un objeto de clase. Si usted está dispuesto a causar una advertencia, siempre se puede hacer
real_time_class = Time
Time = FakeTimeClass
# run test
Time = real_time_class
El recientemente lanzado Test::Redef
hace que este y otra falsedad fácil, incluso sin tener que reestructurar el código en un estilo de dependencia de la inyección (especialmente útil si usted está utilizando el código de otras personas.)
fake_time = Time.at(12345) # ~3:30pm UTC Jan 1 1970
Test::Redef.rd 'Time.now' => proc { fake_time } do
assert_equal 12345, Time.now.to_i
end
sin embargo, tenga cuidado de otras formas de obtener el tiempo de que esto no fuera falsa (Date.new
, una extensión compilado que hace su propia llamada al sistema, interfaces con cosas como servidores de bases de datos externas que conocen el tiempo actual ps, etc.) Parece que la biblioteca de Timecop anterior podría superar estas limitaciones.
Otros grandes usos incluyen probar cosas como "¿qué sucede cuando trato de usar este amigable cliente HTTP pero decide plantear esta excepción en lugar de devolverme una cadena?" sin configurar realmente las condiciones de la red que conducen a esa excepción (que puede ser complicado). También le permite verificar los argumentos para redefinir las funciones.
tenían el mismo problema, que tenía en cuando falsa para una especificación para un día y hora específicos acaba de hacer lo siguiente:
Time.stub!(:now).and_return(Time.mktime(2014,10,22,5,35,28))
esto le dará:
2014-10-22 05:35:28 -0700
¿qué es el signo de exclamación? esto es usando la gema de moka? –
, de hecho, creo que 'stub!' Está privado y puedes simplemente usar 'stub' ahora –
Usando Rspec 3.2, la única manera sencilla si se determina que el valor de retorno es falsa Time.now:
now = Time.parse("1969-07-20 20:17:40")
allow(Time).to receive(:now) { now }
Ahora Time.now siempre devolverá la fecha de Apol Lo 11 aterrizando en la luna.
Si ha incluido ActiveSupport, podría utilizar http://api.rubyonrails.org/classes/ActiveSupport/Testing/TimeHelpers.html
- 1. DateTime.now o Time.now?
- 2. Cómo falsificar http referer
- 3. Cómo falsificar ip en java
- 4. ¿Cómo hago esto? Model.where ("created_at> = # {Time.now - 5.days}")
- 5. ¿puedes falsificar * nix uptime?
- 6. Cómo falsificar el tipo con Python
- 7. Cómo falsificar/proxy una clase en Python
- 8. Lienzo HTML5: Cómo falsificar globalCompositeOperation = "more-more"
- 9. ¿Se puede falsificar una sesión?
- 10. ¿Se puede falsificar $ _SERVER ['SERVER_NAME']?
- 11. Time.now y Created_at son diferentes? Ruby on Rails
- 12. C# Cómo falsificar la dirección IP para WebRequest
- 13. ¿Cómo puedo "falsificar" los atributos de estilo C# en Ruby?
- 14. ¿Cómo puedo falsificar la dirección IP del remitente utilizando curl?
- 15. ¿Cómo falsificar Azure Table Storage en .NET para pruebas unitarias?
- 16. Cómo falsificar llamadas de retorno desde el geolocalizador en jazmín
- 17. cómo falsificar mediante programación un evento táctil a un UIButton?
- 18. ¿Cómo falsificar la entrada al operador de diamantes de perl?
- 19. Configurar un archivo de host - Falsificar URL
- 20. Falsificar un modelo de registro activo sin db
- 21. ¿Es posible falsificar la consola de Windows api?
- 22. ¿es posible simular/falsificar un método de extensión?
- 23. ¿Hay alguna forma de FALSIFICAR herencia en C#/VB.NET?
- 24. ¿Es posible falsificar un átomo de moov (mp4)?
- 25. ¿Puede falsificar Array.isArray() con un objeto definido por el usuario?
- 26. ¿Es posible "falsificar" el atributo src de un iframe?
- 27. ¿Cómo puedo simular/falsificar la existencia de un archivo usando rspec?
- 28. ¿Cómo puedo simular/falsificar/archivar OracleException sellado sin un constructor público?
- 29. ¿Cómo falsificar una búsqueda de subdominio en las pruebas de Rails?
- 30. ¿Cómo falsificar los cambios de tipo de conexión de red en el simulador de iOS?
¿Hay una joya timelord rubí? : P – Rob
¡Cerrar! Hay Timecop. (Consulte mi respuesta a continuación.) –