paint-brush
Software estable: conozca el poder de las pruebas automatizadaspor@igorluchenkov
1,022 lecturas
1,022 lecturas

Software estable: conozca el poder de las pruebas automatizadas

por Igor Luchenkov6m2024/03/02
Read on Terminal Reader

Demasiado Largo; Para Leer

Las pruebas automatizadas son una forma de probar su software sin perder demasiado tiempo. Hay tres tipos de pruebas: unitarias, de integración y de un extremo a otro. Profundicemos en cada tipo y comprendamos por qué los necesitamos. Las pruebas unitarias son rápidas. El aislamiento les permite ejecutarlos en cualquier momento, localmente y en CI, sin activar los servicios dependientes ni realizar llamadas a API y bases de datos. Las pruebas de integración son más lentas, pero prueban cómo se conectan las partes de su aplicación.
featured image - Software estable: conozca el poder de las pruebas automatizadas
Igor Luchenkov HackerNoon profile picture

Este artículo merece su atención si

  • Les apasiona escribir software de buena calidad y desean mejorar la estabilidad de su aplicación con pruebas.


  • Está cansado de que aparezcan errores inesperados en sus sistemas de producción.


  • Necesita ayuda para comprender qué son las pruebas automatizadas y cómo abordarlas.

¿Por qué necesitamos pruebas automatizadas?

Como ingenieros, queremos crear cosas que funcionen , pero con cada nueva característica que creamos, inevitablemente aumentamos el tamaño y la complejidad de nuestras aplicaciones.


A medida que el producto crece, cada vez lleva más tiempo probar manualmente (por ejemplo, con las manos) cada funcionalidad afectada por los cambios.


La ausencia de pruebas automatizadas nos lleva a perder demasiado tiempo y reducir la velocidad de envío o a gastar muy poco para ahorrar velocidad, lo que genera nuevos errores en el trabajo pendiente junto con las llamadas nocturnas de PagerDuty.


Por el contrario, las computadoras pueden programarse para hacer lo mismo repetidamente . Entonces, ¡deleguemos las pruebas a las computadoras!


Tipos de pruebas

Pirámide de pruebas


La idea de la pirámide de pruebas sugiere tres tipos principales de pruebas: unitarias, de integración y de un extremo a otro . Profundicemos en cada tipo y comprendamos por qué los necesitamos.

Pruebas unitarias

Una unidad es una pequeña pieza de lógica que se prueba de forma aislada (sin depender de otros componentes).

Las pruebas unitarias son rápidas. Terminan en segundos. El aislamiento les permite ejecutarlos en cualquier momento, localmente y en CI, sin activar los servicios dependientes ni realizar llamadas a API y bases de datos.


Ejemplo de prueba unitaria: una función que acepta dos números y los suma. Queremos llamarlo con diferentes argumentos y afirmar que el valor devuelto es correcto.


 // Function "sum" is the unit const sum = (x, y) => x + y test('sums numbers', () => { // Call the function, record the result const result = sum(1, 2); // Assert the result expect(result).toBe(3) }) test('sums numbers', () => { // Call the function, record the result const result = sum(5, 10); // Assert the result expect(result).toBe(15) })


Un ejemplo más interesante es el componente React que muestra algo de texto una vez finalizada la solicitud de API. Necesitamos simular el módulo API para devolver los valores necesarios para nuestras pruebas, representar el componente y afirmar que el HTML renderizado tiene el contenido que necesitamos.


 // "MyComponent" is the unit const MyComponent = () => { const { isLoading } = apiModule.useSomeApiCall(); return isLoading ? <div>Loading...</div> : <div>Hello world</div> } test('renders loading spinner when loading', () => { // Mocking the API module, so that it returns the value we need jest.mock(apiModule).mockReturnValue(() => ({ useSomeApiCall: jest.fn(() => ({ // Return "isLoading: false" for this test case isLoading: false })) })) // Execute the unit (render the component) const result = render(<MyComponent />) // Assert the result result.findByText('Loading...').toBeInTheDocument() }) test('renders text content when not loading', () => { // Mocking the API module jest.mock(apiModule).mockReturnValue(() => ({ useSomeApiCall: jest.fn(() => ({ // Return "isLoading: false" for this test case isLoading: false })) })) // Execute the unit (render the component) const result = render(<MyComponent />) // Assert the result result.findByText('Hello world').toBeInTheDocument() })


Pruebas de integración

Cuando su unidad interactúa con otras unidades (dependencias) , lo llamamos integración . Estas pruebas son más lentas que las pruebas unitarias, pero prueban cómo se conectan las partes de su aplicación.


Ejemplo de prueba de integración: un servicio que crea usuarios en una base de datos. Esto requiere que una instancia de base de datos ( dependencia ) esté disponible cuando se ejecutan las pruebas. Probaremos que el servicio pueda crear y recuperar un usuario de la base de datos.


 import db from 'db' // We will be testing "createUser" and "getUser" const createUser = name => db.createUser(name) // creates a user const getUser = name => db.getUserOrNull(name) // retrieves a user or null test("creates and retrieves users", () => { // Try to get a user that doesn't exist, assert Null is returned const nonExistingUser = getUser("i don't exist") expect(nonExistingUser).toBe(null); // Create a user const userName = "test-user" createUser(userName); // Get the user that was just created, assert it's not Null const user = getUser(userName); expect(user).to.not.be(null) })


Pruebas de un extremo a otro

Es una prueba de un extremo a otro cuando probamos la aplicación completamente implementada , donde todas sus dependencias están disponibles. Esas pruebas simulan mejor el comportamiento real del usuario y le permiten detectar todos los posibles problemas en su aplicación, pero son el tipo de prueba más lento .


Siempre que desee ejecutar pruebas de un extremo a otro, debe aprovisionar toda la infraestructura y asegurarse de que haya proveedores externos disponibles en su entorno.


Sólo querrás tenerlos para las funciones críticas de tu aplicación.


Echemos un vistazo a un ejemplo de prueba de un extremo a otro: flujo de inicio de sesión. Queremos ir a la aplicación, completar los datos de inicio de sesión, enviarla y ver el mensaje de bienvenida.


 test('user can log in', () => { // Visit the login page page.goto('https://example.com/login'); // Fill in the login form page.fill('#username', 'john'); page.fill('#password', 'some-password'); // Click the login button page.click('#login-button'); // Assert the welcome message is visible page.assertTextVisible('Welcome, John!') })

¿Cómo se elige qué tipo de prueba escribir?

Recuerde que las pruebas de un extremo a otro son más lentas que las de integración y las pruebas de integración son más lentas que las pruebas unitarias .


Si la característica en la que está trabajando es de misión crítica, considere escribir al menos una prueba de un extremo a otro (como verificar cómo funciona la funcionalidad de inicio de sesión al desarrollar el flujo de autenticación).


Además de los flujos de misión crítica, queremos probar tantos casos extremos y varios estados de la función como sea posible. Las pruebas de integración nos permiten probar cómo funcionan juntas las partes de la aplicación.


Es una buena idea realizar pruebas de integración para puntos finales y componentes del cliente. Los puntos finales deben realizar las operaciones, producir el resultado esperado y no generar errores inesperados.


Los componentes del cliente deben mostrar el contenido correcto y responder a las interacciones del usuario como usted espera que respondan.


Y finalmente, ¿cuándo deberíamos elegir las pruebas unitarias ? Todas las funciones pequeñas que se pueden probar de forma aislada, como sum que suma los números, Button que representa la etiqueta <button> , son excelentes candidatas para las pruebas unitarias. Las unidades son perfectas si sigues el enfoque de desarrollo basado en pruebas .


¿Que sigue?

¡Escribe algunas pruebas! (pero empieza poco a poco)

  • Instale un marco de prueba que se adapte a su proyecto/idioma. Cada idioma tiene una biblioteca popular para realizar pruebas, como Jest / Vitest para JavaScript, Cypress / Playwright de un extremo a otro (también usa JavaScript), JUnit para Java, etc.


  • Encuentre una pequeña función en su proyecto y escriba una prueba unitaria para ella.


  • Escriba una prueba de integración para alguna interacción componente/servicio-base de datos.


  • Elija un escenario crítico que pueda probarse rápidamente, como un flujo de inicio de sesión simple, y escriba una prueba de un extremo a otro para ello.


Haga lo anterior una vez para comprender cómo funciona. Luego, hágalo nuevamente durante el trabajo de alguna función/error. Luego compártelo con tus colegas para que todos puedan escribir exámenes, ahorrar tiempo y dormir mejor por la noche.


Recursos útiles: