paint-brush
Pruebas de rendimiento basadas en Python para probadores de control de calidad: una guía para principiantes sobre pruebas de carga de API en la nubepor@shad0wpuppet
27,075 lecturas
27,075 lecturas

Pruebas de rendimiento basadas en Python para probadores de control de calidad: una guía para principiantes sobre pruebas de carga de API en la nube

por Konstantin Sakhchinskiy8m2024/01/19
Read on Terminal Reader
Read this story w/o Javascript

Demasiado Largo; Para Leer

Explore los scripts de Python para los evaluadores de control de calidad que realizan pruebas de carga en las API de aplicaciones en la nube. El artículo cubre enfoques asincrónicos y de multiprocesamiento y ofrece información sobre personalización, selección de metodología y consejos prácticos de monitoreo. Aproveche las capacidades técnicas de Python para un análisis integral del rendimiento.
featured image - Pruebas de rendimiento basadas en Python para probadores de control de calidad: una guía para principiantes sobre pruebas de carga de API en la nube
Konstantin Sakhchinskiy HackerNoon profile picture
0-item
1-item


¿Es usted un evaluador de control de calidad y está ansioso por sumergirse en las pruebas de rendimiento sin la necesidad de tener una amplia experiencia en programación? En este artículo, exploraremos una forma accesible para que los no programadores realicen algún tipo de prueba de carga en las API de aplicaciones en la nube usando Python . Pruebas de carga sin necesidad de codificación compleja: descubra cómo incluso los evaluadores de control de calidad habituales pueden utilizar Python para encontrar errores graves y descubrir posibles cuellos de botella en el rendimiento.


Las pruebas de rendimiento son un aspecto crítico para garantizar que sus aplicaciones puedan manejar las demandas del mundo real. Intentaré explicar mi enfoque y los scripts de Python diseñados para probar la carga de un servicio en la nube que administra navegadores.


Escenario de prueba de carga Imagine un servicio en la nube responsable de administrar los perfiles del navegador (navegadores para desguace web). Los usuarios interactúan vía API con el servicio para crear, iniciar, detener, eliminar, etc. perfiles. Mi secuencia de comandos Python simula este escenario, aplicando carga al servicio en la nube realizando estas acciones repetidamente.


 # Dependencies import asyncio import httpx # Configuration API_HOST = 'https://cloud.io' API_KEY = 'qatest' API_HEADERS = { "x-cloud-api-token": API_KEY, "Content-Type": "application/json" } CYCLES_COUNT = 3 # Browser profile configuration data_start = { "proxy": "http://127.0.0.1:8080", "browser_settings": {"inactive_kill_timeout": 120} }

Funciones asincrónicas: el corazón de mis pruebas de carga

  • Obtención de perfiles de navegador: la función get_profiles recupera perfiles de navegador existentes del servicio, simulando un escenario en el que los usuarios solicitan información.
 async def get_profiles(cl: httpx.AsyncClient): resp = await cl.get(f'{API_HOST}/profiles', params={'page_len': 10, 'page': 0}, headers=API_HEADERS) return resp.json()


  • Inicio de navegadores: el script inicia ciclos, cada uno de los cuales implica iniciar perfiles de navegador de forma asincrónica. Esto emula un escenario en el que un usuario crea varios navegadores simultáneamente y utiliza perfiles de navegador.
 async def start_profile(cl: httpx.AsyncClient, uuid): resp = await cl.post(f'{API_HOST}/profiles/{id}/start', json=data_start, headers=API_HEADERS) if error := resp.json().get('error'): print(f'Profile {id} not started with error {error}')


  • Detener navegadores y eliminar perfiles: después de iniciar los perfiles, el script recupera los perfiles activos y los detiene, seguido de la eliminación de todos los perfiles. Este escenario de carga evalúa la capacidad de respuesta del servicio en la nube a los cambios dinámicos y su eficiencia en la limpieza de recursos.
 async def stop_profile(cl: httpx.AsyncClient, uuid): resp = await cl.post(f'{API_HOST}/profiles/{id}/stop', headers=API_HEADERS) if error := resp.json().get('error'): print(f'Profile {id} not stopped with error {error}') async def delete_profile(cl: httpx.AsyncClient, uuid): resp = await cl.delete(f'{API_HOST}/profiles/{id}', headers=API_HEADERS) if error := resp.json().get('error'): print(f'Profile {id} not stopped with error {error}')


  • Monitoreo de conexiones: comprensión del impacto de la carga El script concluye verificando e informando sobre las conexiones activas. Este paso es crucial para comprender el impacto de la carga e identificar posibles problemas relacionados con el monitoreo.
 for conn in cl._transport._pool.connections: if conn._connection._state.value != 1: continue print(f'Connection in progress: {conn}')

Pruebas de carga en acción

La función principal organiza los ciclos de prueba de carga, iterando a través de perfiles y ejecutando tareas asincrónicas. Cada ciclo representa una interacción de usuario simulada, creación, uso y eliminación de perfiles de navegador.


 async def main(): async with httpx.AsyncClient(timeout=httpx.Timeout(timeout=300)) as cl: for _ in range(CYCLES_COUNT): profiles = await get_profiles(cl) start_tasks = [asyncio.create_task(start_profile(cl, profile['id'])) for profile in profiles] await asyncio.gather(*start_tasks) active_browsers = await get_active_profiles(cl) stop_tasks = [asyncio.create_task(stop_profile(cl, active_browser['id'])) for active_browser in active_browsers['data']] await asyncio.gather(*stop_tasks) profiles = await get_profiles(cl) del_tasks = [asyncio.create_task(delete_profile(cl, profile['id'])) for profile in profiles] await asyncio.gather(*del_tasks) # Monitor active connections for insights into load impact

Adaptación de las pruebas de carga a sus necesidades

Este script muestra una base para que los controles de calidad adapten escenarios de pruebas de carga a sus aplicaciones. Al personalizar la cantidad de ciclos, ajustar las interacciones del usuario y modificar el script para que se ajuste a puntos finales de API específicos, los evaluadores pueden obtener información valiosa sobre el rendimiento de su aplicación bajo diferentes cargas. Aquí, necesitará herramientas de monitoreo esenciales para obtener información sobre los estados del servidor, evaluar la carga del servidor y realizar un seguimiento de la utilización de recursos y los registros. Utilice herramientas como Grafana, Kibana, Prometheus, etc., para un seguimiento integral. Además, esté atento a las respuestas que recibe su script, lo que garantiza una evaluación exhaustiva del rendimiento de su aplicación. Este enfoque es invaluable en sus pruebas de carga y análisis de rendimiento efectivos.


Además, para una simulación de carga más realista, considere abrir páginas específicas en su navegador. Si bien yo personalmente utilicé una página de inicio en mis navegadores, también puedes explorar opciones como Pyppeteer o Playwright para abrir varias pestañas y navegar por varias páginas. Este enfoque mejora la autenticidad de su escenario de prueba de carga, asemejándose mucho a las interacciones del usuario con su aplicación.


 # Attempt to connect to the browser using the provided profile URL try: browser = await connect({'browserWSEndpoint': browser_url, 'defaultViewport': None}) except Exception as e: # Handle connection errors and print a message print(f'Error occurred when connecting to the browser: {str(e)}') return # Create a new page in the connected browser page = await browser.newPage() # Introduce a brief delay to ensure the page is ready await asyncio.sleep(2) # Set the viewport dimensions for the page width, height = 1920, 1080 await page.setViewport({'width': width, 'height': height}) # Try to navigate to a specific URL try: await page.goto('https://{your_website}') # Wait for 10 seconds to simulate user interaction await page.waitFor(10000) # Introduce another delay for additional stability await asyncio.sleep(5) except pyppeteer.errors.PageError as e: # Handle page navigation errors and print a message print(f'Error occurred during page navigation: {str(e)}') # Attempt to take a screenshot of the page try: await page.screenshot(path='screen.png', fullPage=True) # Print a success message if the screenshot is captured successfully print('Screenshot taken successfully.') except Exception as e: # Handle screenshot capture errors and print a message print(f'Error occurred during taking a screenshot: {str(e)}')

Las capacidades asincrónicas de Python, junto con las bibliotecas HTTP, lo convierten en una herramienta versátil para probar la carga de sistemas basados en la nube. Este ejemplo sirve como punto de partida para los ingenieros de control de calidad que buscan conocer el poder de Python en sus intentos de pruebas de carga.


NOTA

En mi escenario, el guión descrito resultó ser sólido e impactante. Sirvió como herramienta útil para identificar y abordar numerosas cuestiones. La naturaleza agresiva del script estuvo bien al identificar problemas críticos, facilitar una depuración efectiva y abrir el camino para una experiencia de usuario mejorada y sin problemas, lo cual es bastante bueno para un control de calidad.



A continuación, analizaré brevemente otro script que utiliza el módulo de multiprocesamiento de Python. Este enfoque tiene como objetivo mejorar la generación de carga mediante la ejecución simultánea de múltiples instancias del script de prueba. El objetivo principal del multiprocesamiento es paralelizar la ejecución de un script, permitiendo interacciones simultáneas con el servicio. Este enfoque contrasta con el enfoque asincrónico analizado anteriormente, donde las tareas se ejecutan de forma secuencial pero se administran al mismo tiempo. Esto se parece más a spam/ddos con las mismas solicitudes, pero también puede ser muy útil.

Componentes clave

  • Función para recuperar perfiles: similar al script asincrónico, aún necesitamos recuperar los perfiles de navegador existentes del servicio en la nube.
 def get_profiles(): response = requests.get(url=f"{api}", params=PARAMS, headers=headers) return response


  • Funciones: El núcleo del script gira en torno a dos funciones: start_profiles y stop_profiles. Estas funciones inician y finalizan perfiles de navegador, respectivamente.
 def start_profiles(list_of_profiles_uuids): for uuid in list_of_profiles_uuids: # ... (API request to start profile) def stop_profiles(internal_uuids): for uuid in internal_uuids: # ... (API request to stop profile) def run_script(): start_profiles(get_profile_ids()) stop_profiles(list_of_ids)


  • Ejecución de multiprocesamiento: el script utiliza el módulo de multiprocesamiento para ejecutar el ciclo de prueba de carga varias veces en paralelo. Para cada ciclo, se genera un nuevo proceso y la función run_script se ejecuta simultáneamente.
 if __name__ == "__main__": for runs in range(0, 5): processes = [] for i in range(20): p = multiprocessing.Process(target=run_script) processes.append(p) p.start() for p in processes: p.join()


Cómo generar carga con multiprocesamiento

  1. Ejecución paralela: cada proceso generado por el módulo de multiprocesamiento opera de forma independiente y ejecuta la función run_script simultáneamente. Esta paralelización aumenta significativamente la cantidad de solicitudes enviadas al servicio simultáneamente.
  2. Simulación de interacciones de usuarios: al ejecutar varias instancias del script en paralelo, simulamos un mayor volumen de usuarios que interactúan con el servicio en la nube al mismo tiempo. Este enfoque es particularmente útil para escenarios donde el uso en el mundo real involucra una gran cantidad de usuarios simultáneos.

Elegir el enfoque correcto

El multiprocesamiento proporciona una estrategia para aplicaciones de prueba de carga. Permite a los ingenieros de control de calidad experimentar con diferentes metodologías basadas en las características únicas de sus aplicaciones. Si bien las pruebas asincrónicas ofrecen eficiencia en la gestión de tareas simultáneas, el multiprocesamiento sobresale al paralelizar todo el proceso de prueba. Puede elegir el enfoque que mejor se alinee con sus objetivos específicos de pruebas de carga y requisitos de aplicación.


Un recordatorio rápido:

Esta demostración tiene como objetivo presentar conceptos básicos en un formato apto para principiantes, destacando la simplicidad de Python para los evaluadores de control de calidad que se aventuran en las pruebas de rendimiento.

Si tiene desafíos de programación, no dude en buscar en Google y preguntar a sus colegas, usar ChatGPT o herramientas similares y usar GitHub Copilot para obtener ayuda adicional al escribir sus scripts de prueba de carga.


También publicado aquí .