paint-brush
Python-basierte Leistungstests für QA-Tester: Ein Leitfaden für Einsteiger in Cloud-API-Lasttestsvon@shad0wpuppet
27,041 Lesungen
27,041 Lesungen

Python-basierte Leistungstests für QA-Tester: Ein Leitfaden für Einsteiger in Cloud-API-Lasttests

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

Zu lang; Lesen

Entdecken Sie Python-Skripte für QA-Tester, die Lasttests für Cloud-App-APIs durchführen. Der Artikel behandelt asynchrone und Multiprocessing-Ansätze und bietet Einblicke in die Anpassung, Methodenauswahl und praktische Überwachungstipps. Nutzen Sie die technischen Möglichkeiten von Python für eine umfassende Leistungsanalyse.
featured image - Python-basierte Leistungstests für QA-Tester: Ein Leitfaden für Einsteiger in Cloud-API-Lasttests
Konstantin Sakhchinskiy HackerNoon profile picture
0-item
1-item


Sind Sie ein QA-Tester und möchten in die Leistungstests eintauchen, ohne dass Sie über umfangreiche Programmierkenntnisse verfügen müssen? In diesem Artikel untersuchen wir eine für Nicht-Programmierer zugängliche Möglichkeit, mit Python eine Art Auslastungstest für Cloud-Apps-APIs durchzuführen. Lasttests ohne komplexe Codierung – entdecken Sie, wie selbst normale QA-Tester Python verwenden können, um schwerwiegende Fehler zu finden und potenzielle Leistungsengpässe aufzudecken.


Leistungstests sind ein entscheidender Aspekt, um sicherzustellen, dass Ihre Anwendungen realen Anforderungen gerecht werden. Ich werde versuchen, meinen Ansatz und Python-Skripte zu erläutern, die für den Lasttest eines Cloud-Dienstes zur Verwaltung von Browsern entwickelt wurden.


Lasttest-Szenario Stellen Sie sich einen Cloud-Dienst vor, der für die Verwaltung von Browserprofilen (Browser für Web-Scrapping) verantwortlich ist. Benutzer interagieren über die API mit dem Dienst, um Profile zu erstellen, zu starten, zu stoppen, zu löschen usw. Mein Python-Skript simuliert dieses Szenario und belastet den Cloud-Dienst, indem es diese Aktionen wiederholt ausführt.


 # 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} }

Asynchrone Funktionen: Das Herzstück meiner Lasttests

  • Browserprofile abrufen: Die Funktion get_profiles ruft vorhandene Browserprofile vom Dienst ab und simuliert ein Szenario, in dem Benutzer Informationen anfordern.
 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()


  • Starten von Browsern: Das Skript initiiert Zyklen, die jeweils das asynchrone Starten von Browserprofilen beinhalten. Dies emuliert ein Szenario, in dem ein Benutzer mehrere Browser gleichzeitig erstellt und Browserprofile verwendet.
 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}')


  • Stoppen von Browsern und Löschen von Profilen: Nach dem Starten von Profilen ruft das Skript aktive Profile ab, stoppt sie und löscht anschließend alle Profile. Dieses Lastszenario bewertet die Reaktionsfähigkeit des Cloud-Dienstes auf dynamische Änderungen und seine Effizienz bei der Ressourcenbereinigung.
 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}')


  • Überwachen von Verbindungen: Auswirkungen auf die Last verstehen Das Skript schließt mit der Überprüfung und Meldung aktiver Verbindungen ab. Dieser Schritt ist entscheidend für das Verständnis der Lastauswirkungen und die Identifizierung potenzieller Probleme im Zusammenhang mit der Überwachung.
 for conn in cl._transport._pool.connections: if conn._connection._state.value != 1: continue print(f'Connection in progress: {conn}')

Lasttests in Aktion

Die Hauptfunktion orchestriert die Lasttestzyklen, iteriert durch Profile und führt asynchrone Aufgaben aus. Jeder Zyklus stellt eine simulierte Benutzerinteraktion dar, bei der Browserprofile erstellt, verwendet und gelöscht werden.


 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

Passen Sie Lasttests an Ihre Bedürfnisse an

Dieses Skript zeigt eine Grundlage für QAs, um Lasttestszenarien an ihre Anwendungen anzupassen. Durch Anpassen der Anzahl der Zyklen, Anpassen von Benutzerinteraktionen und Anpassen des Skripts an bestimmte API-Endpunkte können Tester wertvolle Einblicke in die Leistung ihrer Anwendung unter verschiedenen Lasten gewinnen. Hier benötigen Sie wichtige Überwachungstools, um Informationen über den Serverstatus zu erhalten, die Serverlast einzuschätzen und die Ressourcennutzung und Protokolle zu verfolgen. Nutzen Sie Tools wie Grafana, Kibana, Prometheus usw. für eine umfassende Überwachung. Behalten Sie außerdem die Antworten, die Ihr Skript erhält, genau im Auge, um eine gründliche Bewertung der Leistung Ihrer Anwendung sicherzustellen. Dieser Ansatz ist für Ihre effektiven Lasttests und Leistungsanalysen von unschätzbarem Wert.


Für eine realistischere Lastsimulation sollten Sie darüber hinaus in Betracht ziehen, bestimmte Seiten in Ihrem Browser zu öffnen. Während ich persönlich in meinen Browsern eine Startseite verwendet habe, können Sie auch Optionen wie Pyppeteer oder Playwright erkunden, um mehrere Registerkarten zu öffnen und durch verschiedene Seiten zu navigieren. Dieser Ansatz erhöht die Authentizität Ihres Lasttestszenarios und ähnelt stark den Benutzerinteraktionen mit Ihrer Anwendung.


 # 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)}')

Die asynchronen Funktionen von Python in Verbindung mit HTTP-Bibliotheken machen es zu einem vielseitigen Tool für Lasttests cloudbasierter Systeme. Dieses Beispiel dient als Ausgangspunkt für QA-Ingenieure, die die Leistungsfähigkeit von Python bei ihren Lasttestversuchen kennenlernen möchten.


NOTIZ

In meinem Szenario erwies sich das beschriebene Skript als robust und wirkungsvoll. Es diente als nützliches Instrument zur Identifizierung und Lösung zahlreicher Probleme. Der aggressive Charakter des Skripts war in Ordnung, um kritische Probleme zu lokalisieren, ein effektives Debugging zu ermöglichen und den Weg für eine nahtlose und verbesserte Benutzererfahrung zu ebnen, was für eine Qualitätssicherung ziemlich gut ist.



Im Folgenden werde ich kurz auf ein weiteres Skript eingehen, das das Multiprocessing-Modul von Python nutzt. Dieser Ansatz zielt darauf ab, die Lastgenerierung durch die gleichzeitige Ausführung mehrerer Instanzen des Testskripts zu verbessern. Das Hauptziel von Multiprocessing besteht darin, die Ausführung eines Skripts zu parallelisieren und gleichzeitige Interaktionen mit dem Dienst zu ermöglichen. Dieser Ansatz steht im Gegensatz zum zuvor diskutierten asynchronen Ansatz, bei dem Aufgaben nacheinander ausgeführt, aber gleichzeitig verwaltet werden. Dies ähnelt eher Spam/DDoS mit den gleichen Anfragen, könnte aber auch sehr nützlich sein.

Schlüsselkomponenten

  • Funktion zum Abrufen von Profilen: Ähnlich wie beim asynchronen Skript müssen wir weiterhin vorhandene Browserprofile vom Cloud-Dienst abrufen.
 def get_profiles(): response = requests.get(url=f"{api}", params=PARAMS, headers=headers) return response


  • Funktionen: Der Kern des Skripts besteht aus zwei Funktionen: start_profiles und stop_profiles. Diese Funktionen initiieren bzw. beenden Browserprofile.
 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)


  • Multiprocessing-Ausführung: Das Skript nutzt das Multiprocessing-Modul, um den Lasttestzyklus mehrmals parallel auszuführen. Für jeden Zyklus wird ein neuer Prozess erzeugt und gleichzeitig die Funktion run_script ausgeführt.
 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()


So erzeugen Sie Last mit Multiprocessing

  1. Parallele Ausführung: Jeder vom Multiprocessing-Modul erzeugte Prozess arbeitet unabhängig und führt die run_script-Funktion gleichzeitig aus. Durch diese Parallelisierung erhöht sich die Anzahl der gleichzeitig an den Dienst gesendeten Anforderungen erheblich.
  2. Simulieren von Benutzerinteraktionen: Durch die parallele Ausführung mehrerer Instanzen des Skripts simulieren wir eine größere Anzahl von Benutzern, die gleichzeitig mit dem Cloud-Dienst interagieren. Dieser Ansatz ist besonders nützlich für Szenarien, in denen die reale Nutzung eine große Anzahl gleichzeitiger Benutzer umfasst.

Den richtigen Ansatz wählen

Das Multiprocessing bietet eine Strategie für Auslastungstests von Anwendungen. Es ermöglicht QS-Ingenieuren, basierend auf den einzigartigen Eigenschaften ihrer Anwendungen mit verschiedenen Methoden zu experimentieren. Während asynchrone Tests eine Effizienz bei der Verwaltung gleichzeitiger Aufgaben bieten, zeichnet sich Multiprocessing durch die Parallelisierung des gesamten Testprozesses aus. Sie können den Ansatz wählen, der am besten zu Ihren spezifischen Lasttestzielen und Anwendungsanforderungen passt.


Eine kurze Erinnerung:

Diese Demo zielt darauf ab, grundlegende Konzepte in einem anfängerfreundlichen Format vorzustellen und die Einfachheit von Python für QS-Tester hervorzuheben, die sich an Leistungstests wagen.

Wenn Sie Programmierschwierigkeiten haben, zögern Sie nicht, zu googeln und Kollegen zu fragen, ChatGPT oder ähnliche Tools zu verwenden und GitHub Copilot für zusätzliche Unterstützung beim Schreiben Ihrer Lasttestskripte zu verwenden.


Auch hier veröffentlicht.