paint-brush
Тестирование производительности на базе Python для тестировщиков QA: руководство для начинающих по нагрузочному тестированию облачных APIк@shad0wpuppet
27,036 чтения
27,036 чтения

Тестирование производительности на базе Python для тестировщиков QA: руководство для начинающих по нагрузочному тестированию облачных API

Слишком долго; Читать

Изучите сценарии Python для тестировщиков контроля качества, проводящих нагрузочное тестирование API облачных приложений. В статье рассматриваются асинхронные и многопроцессорные подходы, даются сведения о настройке, выборе методологии и практические советы по мониторингу. Используйте технические возможности Python для комплексного анализа производительности.
featured image - Тестирование производительности на базе Python для тестировщиков QA: руководство для начинающих по нагрузочному тестированию облачных API
Konstantin Sakhchinskiy HackerNoon profile picture
0-item
1-item


Вы тестировщик QA и хотите погрузиться в тестирование производительности без необходимости обширных знаний в области программирования? В этой статье мы рассмотрим доступный для непрограммистов способ проведения своего рода нагрузочного тестирования API облачных приложений с использованием Python . Нагрузочное тестирование без необходимости сложного кодирования — узнайте, как даже обычные тестировщики QA могут использовать Python для поиска серьезных ошибок и выявления потенциальных узких мест в производительности.


Тестирование производительности — важнейший аспект обеспечения способности ваших приложений соответствовать реальным требованиям. Я попытаюсь объяснить свой подход и сценарии Python, предназначенные для нагрузочного тестирования облачного сервиса, управляющего браузерами.


Сценарий нагрузочного тестирования Представьте себе облачный сервис, отвечающий за управление профилями браузеров (браузеры для очистки веб-страниц). Пользователи взаимодействуют через API с сервисом для создания, запуска, остановки, удаления и т. д. профилей. Мой сценарий Python имитирует этот сценарий, загружая облачный сервис путем многократного выполнения этих действий.


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

Асинхронные функции: суть моих нагрузочных тестов

  • Получение профилей браузера. Функция get_profiles извлекает существующие профили браузера из службы, имитируя сценарий, в котором пользователи запрашивают информацию.
 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()


  • Запуск браузеров: сценарий инициирует циклы, каждый из которых включает асинхронный запуск профилей браузера. Это эмулирует сценарий, в котором пользователь одновременно создает несколько браузеров и использует профили браузеров.
 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}')


  • Остановка браузеров и удаление профилей. После запуска профилей сценарий извлекает активные профили и останавливает их, а затем удаляет все профили. Этот сценарий нагрузки оценивает реакцию облачной службы на динамические изменения и ее эффективность при очистке ресурсов.
 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}')


  • Мониторинг соединений: понимание влияния нагрузки. Сценарий завершается проверкой и составлением отчета об активных соединениях. Этот шаг имеет решающее значение для понимания влияния нагрузки и выявления потенциальных проблем, связанных с мониторингом.
 for conn in cl._transport._pool.connections: if conn._connection._state.value != 1: continue print(f'Connection in progress: {conn}')

Нагрузочное тестирование в действии

Функция main управляет циклами нагрузочного тестирования, проходя по профилям и выполняя асинхронные задачи. Каждый цикл представляет собой моделируемое взаимодействие пользователя, создание, использование и удаление профилей браузера.


 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

Адаптация нагрузочных тестов под ваши нужды

Этот сценарий показывает, как специалисты по обеспечению качества могут адаптировать сценарии нагрузочного тестирования к своим приложениям. Настраивая количество циклов, корректируя взаимодействие с пользователем и изменяя сценарий для соответствия конкретным конечным точкам API, тестировщики могут получить ценную информацию о производительности своего приложения при различных нагрузках. Здесь вам понадобятся необходимые инструменты мониторинга, чтобы получить информацию о состоянии сервера, оценить нагрузку на сервер и отслеживать использование ресурсов и журналы. Используйте такие инструменты, как Grafana, Kibana, Prometheus и т. д., для комплексного мониторинга. Кроме того, внимательно следите за ответами, которые получает ваш сценарий, чтобы обеспечить тщательную оценку производительности вашего приложения. Этот подход неоценим для эффективного нагрузочного тестирования и анализа производительности.


Кроме того, для более реалистичной симуляции загрузки рассмотрите возможность открытия определенных страниц в браузере. Хотя я лично использовал стартовую страницу в своих браузерах, вы также можете использовать такие параметры, как Pyppeteer или Playwright, чтобы открывать несколько вкладок и перемещаться по различным страницам. Такой подход повышает достоверность сценария нагрузочного тестирования, очень напоминающего взаимодействие пользователя с вашим приложением.


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

Асинхронные возможности Python в сочетании с библиотеками HTTP делают его универсальным инструментом для нагрузочного тестирования облачных систем. Этот пример служит отправной точкой для инженеров по контролю качества, желающих изучить возможности Python в своих попытках нагрузочного тестирования.


ПРИМЕЧАНИЕ

В моем сценарии описанный сценарий оказался надежным и эффективным. Он послужил полезным инструментом в выявлении и решении многочисленных проблем. Агрессивный характер сценария позволил выявить критические проблемы, облегчить эффективную отладку и проложить путь к беспрепятственному и улучшенному пользовательскому интерфейсу, что очень хорошо для QA.



В продолжении я кратко расскажу о другом сценарии, использующем многопроцессорный модуль Python. Этот подход направлен на улучшение генерации нагрузки за счет одновременного выполнения нескольких экземпляров сценария тестирования. Основная цель многопроцессорной обработки — распараллелить выполнение сценария, обеспечивая одновременное взаимодействие со службой. Этот подход контрастирует с обсуждавшимся ранее асинхронным подходом, в котором задачи выполняются последовательно, но управляются одновременно. Это больше похоже на спам/ддосы с теми же запросами, но тоже может быть очень полезно.

Ключевые компоненты

  • Функция получения профилей: как и в асинхронном сценарии, нам все равно необходимо получить существующие профили браузера из облачной службы.
 def get_profiles(): response = requests.get(url=f"{api}", params=PARAMS, headers=headers) return response


  • Функции. В основе сценария лежат две функции: start_profiles и stop_profiles. Эти функции запускают и завершают профили браузера соответственно.
 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)


  • Многопроцессорное выполнение: сценарий использует модуль многопроцессорности для параллельного выполнения цикла нагрузочного тестирования несколько раз. Для каждого цикла создается новый процесс, и функция run_script выполняется одновременно.
 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()


Как генерировать нагрузку с помощью многопроцессорности

  1. Параллельное выполнение: каждый процесс, порожденный многопроцессорным модулем, работает независимо, одновременно выполняя функцию run_script. Такое распараллеливание существенно увеличивает количество запросов, отправляемых в сервис одновременно.
  2. Моделирование взаимодействия с пользователем. Запуская несколько экземпляров сценария параллельно, мы имитируем большее количество пользователей, одновременно взаимодействующих с облачным сервисом. Этот подход особенно полезен для сценариев, в которых в реальном использовании участвует большое количество одновременных пользователей.

Выбор правильного подхода

Многопроцессорность обеспечивает стратегию нагрузочного тестирования приложений. Это позволяет инженерам по обеспечению качества экспериментировать с различными методологиями, основанными на уникальных характеристиках их приложений. В то время как асинхронное тестирование обеспечивает эффективность управления параллельными задачами, многопроцессорность превосходно распараллеливает весь процесс тестирования. Вы можете выбрать подход, который лучше всего соответствует конкретным целям нагрузочного тестирования и требованиям приложений.


Краткое напоминание:

Целью этой демонстрации является представление основных понятий в формате, удобном для новичков, и подчеркивание простоты Python для тестировщиков QA, решающихся заняться тестированием производительности.

Если у вас есть проблемы с программированием, не стесняйтесь обращаться к Google и спрашивать коллег, используйте ChatGPT или аналогичные инструменты, а также используйте GitHub Copilot для получения дополнительной помощи в написании сценариев нагрузочного тестирования.


Также опубликовано здесь .