
Este artĆculo es parte de una serie en la que documente las ideas, los cambios y el replanteamiento que experimentĆ© al refactorizar la base de código para Pulse , una herramienta de monitoreo de sitios y servidores indolora y asequible diseƱada para desarrolladores.
Hoy, me gustarĆa hablar sobre cómo creĆ© clases falsas para probar la funcionalidad que depende de hacer solicitudes a travĆ©s de Internet. Vamos a profundizar en…
¿Por quĆ© crear clases falsas?
En tĆ©rminos generales, si puede evitar crear una clase falsa, le recomendarĆa absolutamente que lo haga. Es el mismo argumento que existe para ser cauteloso sobre el uso
mocks
y spies
en su código ... realmente no estĆ” probando su código, sino probando la sintaxis / interacción de su código.De acuerdo, si es asĆ, ¿por quĆ© querrĆa usarlos?
La respuesta a eso es simple. Rendimiento . Considere el siguiente ejemplo, escribe una prueba que realiza una solicitud HTTP a un tercero, por ejemplo, acme.com. Recibe la respuesta y su código reacciona en consecuencia.
Bien y elegante ... pero ¿y si la respuesta no fuera la que esperabas? ¿Y si el sitio fuera lento? ¿QuĆ© pasa si el sitio estaba fuera de lĆnea? ¿QuĆ© pasa si su conexión a Internet no funcionaba correctamente?
Incluso si pudo mitigar esos problemas cada vez que ejecutó la prueba, todavĆa hay una cosa que no puede abordar y es la latencia involucrada en el envĆo de la solicitud HTTP. Su prueba tiene que esperar la respuesta.
En el caso de una sola prueba, no es un gran problema, pero imagine si su conjunto de pruebas tenĆa cientos o incluso miles de pruebas que involucraban solicitudes HTTP. No desea estar en una posición en la que se tarde una hora en ejecutar su conjunto de pruebas.
Clases falsas al rescate
La manera fĆ”cil de resolver este problema es envolver la funcionalidad que envĆa una solicitud HTTP dentro de una clase. Luego, dentro de su aplicación, resuelve esta clase fuera del contenedor de servicios de Laravel y llama a sus mĆ©todos.
Para sus pruebas, crea una clase separada que hereda de esta clase principal. Luego anula los mƩtodos para realizar la misma funcionalidad pero sin enviar realmente la solicitud HTTP.
Finalmente, dentro de sus pruebas, instruye al contenedor de servicios de Laravel a
swap
la clase principal con su clase falsa. De esa manera, cuando su aplicación solicita una instancia de la clase principal, obtiene la clase falsa en su lugar.
Si eres nuevo en esto, puede ser un poco abrumador, asĆ que simplifiquemos las cosas mirando un ejemplo de Pulse.
Enviar una solicitud HTTP
Como parte de sus actividades de monitoreo, Pulse realiza una solicitud HTTP al sitio de un usuario y verifica el código de estado HTTP que recibe. Para hacer esto, la aplicación llama al
getStatusCode
mƩtodo en una clase llamada PingSite
.
AquĆ hay un ejemplo simplificado de la clase:
class PingSite { / ** * EnvĆa una solicitud HTTP a una url y recupera su código de estado. * * / public function getStatusCode (string $ url): int { return $ client-> request ($ url) -> statusCode; } }
Luego, dentro de la aplicación, en lugar de simplemente crear una nueva instancia de la
PingSite
clase, sacamos resolve
la clase del contenedor de servicios:// NO $ ping = new PingSite (); // SĆ $ ping = resolve (PingSite :: class);
Aparte de cómo instanciamos la
PingSite
clase, todo sigue igual. TodavĆa devuelve un objeto de tipo PingSite
.Crear la implementación falsa
Para nuestras pruebas, necesitamos crear una clase falsa que anule el
getStatusCode
método y en su lugar simplemente devuelva un número entero. Sin embargo, necesitamos una forma de establecer el número entero que se devuelve para que podamos probar una variedad de escenarios.
Agreguemos una propiedad a nuestra clase falsa y establezcamos su valor en el constructor. Luego podemos modificar el
getStatusCode
método para devolver el valor de la propiedad:la clase PingSiteFake extiende PingSite { código $ protegido; función pública __construct (int $ code) { $ this-> code = $ code; } / ** * Simular una solicitud HTTP a una url y obtener su código de estado. * * / public function getStatusCode (string $ url): int { return $ this-> code; } }
Finalmente, todo lo que tenemos que hacer dentro de nuestras pruebas es instruir a Laravel para que use nuestra clase falsa al resolver
PingSite
desde el contenedor de servicios:/ ** @test * / public function it_can_ping_a_url_and_get_the_http_status_code () { // Usa la implementación falsa $ this-> swap (PingSite :: class, new PingSiteFake (201)); $ this-> get ('/ ping / google.com') -> afirmarJson (['estado' => 201]); }
Y eso es todo lo que hay que hacer. Esta prueba ahora se ejecutarƔ en un par de milisegundos, en lugar de un segundo o mƔs si realmente enviamos una solicitud HTTP genuina.
Advertencias a tener en cuenta
Como se mencionó al principio, el argumento sobre tener cuidado con este enfoque todavĆa se aplica. Como probablemente se dio cuenta, no estamos realmente probando
PingSite
, estamos vez probar el código que interactúa con PingSite
.
TodavĆa es increĆblemente importante escribir pruebas que realmente utilicen
PingSite
y no su implementación falsa, para garantizar que funcione correctamente. Sin embargo, en lugar de escribir docenas, cientos o incluso miles de pruebas que son lentas porque todas se usan PingSite
, solo necesita escribir un puƱado que pruebe especĆficamente la funcionalidad de la PingSite
clase.
Esto asegurarƔ que su conjunto de pruebas se ejecute significativamente mƔs rƔpido.
Terminando
Esperemos que haya visto cómo el uso de clases falsas puede ser significativamente beneficioso para mejorar el rendimiento de su conjunto de pruebas. Tengo mĆ”s artĆculos para compartir, asĆ que si estĆ”s interesado en leerlos, asegĆŗrate de seguirme aquĆ en Medium. TambiĆ©n puedes seguirme en Twitter .
Por Ćŗltimo, si estĆ” buscando una herramienta de monitoreo de sitios y servidores asequible e indolora que no requiera que tenga un tĆtulo de DevOps, tómese un momento para consultar Pulse . ¡Creo que lo encontrarĆ”s como un soplo de aire fresco!
No hay comentarios.:
Publicar un comentario