Привет!
В этой статье поговорим об инструменте Atlassian, который называется dc-app-performance-toolkit. Этот инструмент позволяет Вам проводить нагрузочное тестирование на экземплярах Jira, Confluence или Bitbucket.
У меня есть несколько статей по этому инструменту.
Этот инструмент запускает тесты на Jmeter и Selenium.
В этой статье я бы хотел показать на примере, как понять, что пошло не так в тестах Selenium, и как решить проблему с несекьюрным SSL сертификатом.
Проблема
Я запустил dc-app-performance-toolkit на экземпляр Bitbucket и во время выполнения тестов у меня было много ошибок в тестах Selenium:

Как Вы видите, у меня 100% ошибок с selenium_login. А ошибка – NoSuchEle. Скорее всего, NoSuchElementException
Отлично. Что пошло не так?
Анализируем
Я открыл файл selenium.err и увидел много вот таких сообщений:
Action: test_0_selenium_a_login, Error: bitbucket_webdriver = <selenium.webdriver.chrome.webdriver.WebDriver (session="e369b1efa8c2794638560ae68246409a")>bitbucket_datasets = {'password': 'dcapt-perf-user-hsyjq', 'project_key': 'PRJ-10009', 'projects': [['FORKS-1', '2987'], ['PRJ-1', '5'], ['...RJ-100', '101'], ['PRJ-1000', '1001'], ['PRJ-10000', '11401'], ...], 'pull_request_branch_from': 'perf-branch-24', ...}bitbucket_screen_shots = None def test_0_selenium_a_login(bitbucket_webdriver, bitbucket_datasets, bitbucket_screen_shots):> modules.login(bitbucket_webdriver, bitbucket_datasets)selenium_ui/bitbucket_ui.py:7: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ selenium_ui/bitbucket/modules.py:41: in login measure()_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ @functools.wraps(func) def wrapper(): if LOGIN_ACTION_NAME in interaction: globals.login_failed = False if globals.login_failed: pytest.skip(f"login is failed") start = time.time() error_msg = 'Success' full_exception = '' try: func() success = True except Exception: success = False # https://docs.python.org/2/library/sys.html#sys.exc_info exc_type, full_exception = sys.exc_info()[:2] error_msg = f"Failed measure: {interaction} - {exc_type.__name__}" end = time.time() timing = str(int((end - start) * 1000)) with open(selenium_results_file, "a+") as jtl_file: timestamp = round(time.time() * 1000) jtl_file.write(f"{timestamp},{timing},{interaction},,{error_msg},,{success},0,0,0,0,,0\n") print(f"{timestamp},{timing},{interaction},{error_msg},{success}") if not success: if LOGIN_ACTION_NAME in interaction: globals.login_failed = True> raise Exception(error_msg, full_exception)E Exception: ('Failed measure: selenium_login - Exception', Exception('Failed measure: selenium_login:open_login_page - NoSuchElementException', NoSuchElementException('no such element: Unable to locate element: {"method":"css selector","selector":"[id="product-version"]"}\n (Session info: headless chrome=85.0.4183.102)', None, None)))
Из этих сообщений я понял, что Selenium пытается найти элемент с id=”product-version”, и не может. Но почему?
Так. У нас еще есть папка со скринами и с телом html, на которых произошли ошибки. Может оттуда что-нибудь поймем. Посмотрим.
Я нашел вот такой html код:
<html><head></head><body></body></html>
И вот такой скриншот:

Пустой экран.
Прикольно. Все равно ничего не понятно.
Устанавливаем WEBDRIVER_VISIBLE в True
Нет, не понимаю, что за ошибка. Хорошо бы увидеть, что там реально в браузере происходит во время теста. И такая возможность есть. Нужно установить параметр WEBDRIVER_VISIBLE в True в файле bitbucket.yml (такой же параметр есть и в файлах jira.yml и confluence.yml). По умолчанию он установлен в False, поэтому браузер не видно при запуске тестов Selenium.
Хорошо. Установил параметр. Запустил тест и вот что я увидел:

Ну, теперь другое дело! Selenium ждет, что будет экран входа в Bitbucket, а вместо этого у него экран с ошибкой. Selenium ищет заданный html элемент и, конечно, не находит. В результате падает с ошибкой.
Ладно. Починим.
Чиним ошибку с несекьюрным сертификатом
Webdriver настраивается в файле app/selenium_ui/conftest.py:
def driver_init(): chrome_options = Options() if not app_settings.webdriver_visible: chrome_options.add_argument("--headless") chrome_options.add_argument("--window-size={},{}".format(SCREEN_WIDTH, SCREEN_HEIGHT)) chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--disable-infobars") chrome_options.add_argument('ignore-certificate-errors') driver.app_settings = app_settings return driver
Нам нужно добавить вот такую настройку:
chrome_options.add_argument('ignore-certificate-errors')
Это скажет браузеру Chrome не проверять секьюрность SSL сертификата при его открытии. Ну, и вот так будет выглядеть метод driver_init в конечно варианте:
def driver_init(): chrome_options = Options() if not app_settings.webdriver_visible: chrome_options.add_argument("--headless") chrome_options.add_argument("--window-size={},{}".format(SCREEN_WIDTH, SCREEN_HEIGHT)) chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--disable-infobars") chrome_options.add_argument('ignore-certificate-errors') driver = Chrome(options=chrome_options) driver.app_settings = app_settings return driver
Запускаем. И… Все тесты Selenium заработали!