def step_impl(context, link, browser): """ :type context: behave.runner.Context :type link: str :type browser: str """ _logger = context.logger _logger.info('Opening {} in {}'.format(link, browser)) client = getattr(context, browser) client.get(link) time.sleep(Env.vars['wait_time']) attach(client.get_screenshot_as_png(), name="screenshot", attachment_type=AttachmentType.PNG)
def search_for_warnings(self): """dump out instance args, and what could be fishy in my log""" log = str() print(self.arguments) if not self.log_file.exists(): print(str(self.log_file) + " not there. Skipping search") return print(str(self.log_file)) with self.log_file.open(errors="backslashreplace") as log_f: for line in log_f.readline(): if "WARN" in line or "ERROR" in line: print(line.rstrip()) log += line.rstrip() attach(log, "WARN or ERROR lines from starter log")
def attach_http_request_to_report(method: str, url: str, headers: dict, body: str): request = f""" <html> <p><b>Method: </b>${method.upper()}</p> <p><b>URL: </b>${url}</p> <p><b>Headers: </b></p> <p> """ for key in headers: request += f"<b>{key}: </b>{headers[key]}<br>" request += f"</p>" request += f"<p><b>Body:<br></b>{body}</p>" request +="</html>" attach(request, "HTTP request", AttachmentType.HTML)
def upgrade_server_package(self, old_installer): if not (self.cfg.package_dir / self.server_package).exists(): raise Exception("Package not found: " + str(self.server_package)) self._verify_signature(self.server_package) self.backup_dirs_number_before_upgrade = self.count_backup_dirs() self.stop_service() self._verify_signature(self.server_package) cmd = [ str(self.cfg.package_dir / self.server_package), "/INSTDIR=" + str(PureWindowsPath(self.cfg.install_prefix)), "/DATABASEDIR=" + str(PureWindowsPath(self.cfg.dbdir)), "/APPDIR=" + str(PureWindowsPath(self.cfg.appdir)), "/PATH=0", "/UPGRADE=1", "/BACKUP_ON_UPGRADE=1", "/S", "/INSTALL_SCOPE_ALL=1", ] logging.info("running windows package installer:") logging.info(str(cmd)) install = psutil.Popen(cmd) try: install.wait(600) except psutil.TimeoutExpired as exc: print("upgrading timed out, taking screenshot, re-raising!") filename = "windows_upgrade_screenshot.png" with mss() as sct: sct.shot(output=filename) attach( filename, name="Screenshot ({fn})".format(fn=filename), attachment_type=AttachmentType.PNG, ) install.kill() raise Exception("Upgrade install failed to complete on time") from exc self.service = psutil.win_service_get("ArangoDB") while not self.check_service_up(): logging.info("starting...") time.sleep(1) self.enable_logging() self.stop_service() # the smaller the wintendo, the longer we shal let it rest, # since it needs to look at all these files we # just unloaded into it to make sure no harm originates from them. time.sleep(60 / multiprocessing.cpu_count()) self.set_system_instance() self.start_service() logging.info("Installation successfull")
def step_impl(context, item_name, cart): """ :type context: behave.runner.Context :type item_name: str :type cart: str """ element = context.browser.find_elements(By.CSS_SELECTOR, cart) assert element, 'Element not found' attach(context.browser.get_screenshot_as_png(), name="screenshot", attachment_type=AttachmentType.PNG) assert len(element) == 1, f'{item_name} not added to cart' print( f'Successfully verified the availability of the {item_name} in the {cart}' )
def check_installed(self, version, enterprise, check_stripped, check_symlink, check_notarized): """check all attributes of this file in reality""" if check_notarized: self._validate_notarization(enterprise) attach(str(self), "file info") if semver.compare(self.version_min, version) == 1: self.check_path(enterprise, False) return self.check_path(enterprise) if not enterprise and self.enterprise: # checks do not need to continue in this case return if check_stripped: self.check_stripped() if check_symlink: self.check_symlink()
def __init__(self, web_driver): self.driver = web_driver self.diprella_header = WebDriverWait(self.driver, 10).until( EC.visibility_of_element_located( (By.CSS_SELECTOR, ".main__wrapper"))) self.diprella_logo = WebDriverWait(self.driver, 15).until( EC.visibility_of_element_located( (By.CSS_SELECTOR, ".header__logo"))) self.course_search = self.driver.find_element_by_xpath( "//input[@id='search' and @type='text']") self.recommendations = self.driver.find_element_by_xpath( "//section[@class='recomendations'][1]") self.popular = self.driver.find_element_by_xpath( "//section[@class='recomendations'][2]") self.lector_menu = 0 self.user_menu = 0 attach(self.driver.get_screenshot_as_png(), name="User workspace page screenshot", attachment_type=attachment_type.PNG)
def create_arangod_dump(installer, starter_dir: str, dump_file_dir: str): """create arangod memory dump file""" starter = StarterManager( basecfg=installer.cfg, install_prefix=Path(starter_dir), instance_prefix="single", expect_instances=[InstanceType.SINGLE], mode="single", jwt_str="single", ) dump_filename = None try: with step("Start a single server deployment"): starter.run_starter() starter.detect_instances() starter.detect_instance_pids() starter.set_passvoid("") pid = starter.all_instances[0].pid with step("Create a dump of arangod process"): cmd = ["procdump", "-ma", str(pid), dump_file_dir] lh.log_cmd(cmd) with psutil.Popen(cmd, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc: (procdump_out, procdump_err) = proc.communicate() procdump_str = str(procdump_out, "UTF-8") attach(procdump_str, "procdump sdtout") attach(str(procdump_err), "procdump stderr") success_string = "Dump 1 complete" filename_regex = re.compile( r"^(\[\d{2}:\d{2}:\d{2}\] Dump 1 initiated: )(?P<filename>.*)$", re.MULTILINE) match = re.search(filename_regex, procdump_str) if procdump_str.find(success_string) < 0 or not match: raise Exception( "procdump wasn't able to create a dump file: " + procdump_str) dump_filename = match.group("filename") finally: starter.terminate_instance() kill_all_processes() return dump_filename
def attach_table(table, title="HTML table"): """attach a BeautifulTable to allure report""" template_str = """ <html> <style> table { white-space: pre-line; border-collapse: collapse; font-family: Helvetica,Arial,sans-serif; font-size: 14px; margin: 8px 0; padding: 0; } table tr { border-top: 1px solid #cccccc; background-color: white; margin: 0; padding: 0; } table tr:nth-child(2n) { background-color: #f8f8f8; } table tr th { font-weight: bold; border: 1px solid #cccccc; text-align: left; margin: 0; padding: 3px 5px; } table tr td { border: 1px solid #cccccc; text-align: left; margin: 0; padding: 3px 5px; } table tr th :first-child, table tr td :first-child { margin-top: 0; } table tr th :last-child, table tr td :last-child { margin-bottom: 0; } </style> $html_table </html> """ # pylint: disable=no-member template = Template(template_str) html_table = tabulate(table, headers=table.columns.header, tablefmt="html") attach(template.substitute(html_table=html_table), title, AttachmentType.HTML)
def take_screenshot(self): """*snap*""" # pylint: disable=broad-except filename = datetime.now().strftime("%d-%m-%Y_%H:%M:%S.%f") + ".png" self.progress("Taking screenshot from: %s " % self.webdriver.current_url) try: if self.is_headless: self.progress("taking full screenshot") elmnt = self.webdriver.find_element_by_tag_name("body") screenshot = elmnt.screenshot_as_png() else: self.progress("taking screenshot") screenshot = self.webdriver.get_screenshot_as_png() except InvalidSessionIdException: self.progress("Fatal: webdriver not connected!") except Exception as ex: self.progress("falling back to taking partial screenshot " + str(ex)) screenshot = self.webdriver.get_screenshot_as_png() self.progress("Saving screenshot to file: %s" % filename) attach(screenshot, name="Screenshot ({fn})".format(fn=filename), attachment_type=AttachmentType.PNG)
def step_impl(context, message, element, browser): """ :type context: behave.runner.Context :type message: str :type element: str :type browser: str """ client = getattr(context, browser) WebDriverWait(client, Env.vars['driver_wait']).until( EC.text_to_be_present_in_element((By.XPATH, element), '{}'.format(message))) element = client.find_element(By.XPATH, element) attach(client.get_screenshot_as_png(), name="screenshot", attachment_type=AttachmentType.PNG) actual_message = element.text assert actual_message == message, \ "Message is '{}' but expected should be '{}' ".format(actual_message, message) print("Message '{}' successfully verified".format(actual_message)) time.sleep(Env.vars['wait_time'])
def test_debug_symbols_attach_to_process_windows(self): """Debug arangod executable by attaching debugger to a running process (Windows)""" starter = StarterManager( basecfg=self.installer.cfg, install_prefix=Path(DebuggerTestSuite.STARTER_DIR), instance_prefix="single", expect_instances=[InstanceType.SINGLE], mode="single", jwt_str="single", ) try: with step("Start a single server deployment"): starter.run_starter() starter.detect_instances() starter.detect_instance_pids() starter.set_passvoid("") pid = starter.all_instances[0].pid pdb_dir = str(self.installer.cfg.debug_install_prefix) with step( "Check that stack trace with function names and line numbers can be acquired from cdb" ): cmd = " ".join([ "cdb", "-pv", "-p", str(pid), "-y", pdb_dir, "-lines", "-n" ]) attach(cmd, "CDB command", attachment_type=AttachmentType.TEXT) cdb = wexpect.spawn(cmd) cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=300) cdb.sendline("k") cdb.expect(DebuggerTestSuite.CDB_PROMPT, timeout=300) stack = cdb.before cdb.sendline("q") attach(stack, "Stacktrace from cdb output", attachment_type=AttachmentType.TEXT) assert "arangod!main" in stack, "Stack must contain real function names." assert "arangod.cpp" in stack, "Stack must contain real source file names." finally: starter.terminate_instance() kill_all_processes()
def kill_all_processes(kill_selenium=True): """killall arangod arangodb arangosync""" processlist = get_all_processes(kill_selenium) print(processlist) attach(str(processlist), "List of processes") for process in processlist: if process.is_running(): cmdline = str(process) try: cmdline = process.cmdline() except psutil.AccessDenied: pass except psutil.NoSuchProcess: pass logging.info("cleanup killing ${proc}".format(proc=cmdline)) if process.is_running(): try: process.terminate() except Exception as ex: logging.info( "seems as if process %s is already dead?", str(process) + " - " + str(ex), ) continue if process.is_running(): try: process.wait(timeout=2) except psutil.NoSuchProcess: pass except psutil.TimeoutExpired: logging.info( "timeout while waiting for %s to exit, try once more", str(process), ) try: process.kill() except psutil.NoSuchProcess: pass
def _attach_response(response: RequestsResponse): response_json = None try: response_json = response.json() except ValueError: pass with step(f"{response.request.method}: {response.request.url}"): attach(_dump_headers(response.request.headers), 'request.headers', AttachmentType.TEXT) with step(f"response → {response.status_code}"): if response_json: attach(_dump(response_json), 'response.json', AttachmentType.JSON) if response.text: attach(response.text, 'response.text', AttachmentType.TEXT) attach(_dump_headers(response.headers), 'response.headers', AttachmentType.JSON)
def un_install_client_package_impl(self): """Uninstall client package""" uninstaller = "Uninstall.exe" tmp_uninstaller = Path("c:/tmp") / uninstaller uninstaller = self.cfg.install_prefix / uninstaller if uninstaller.exists(): # copy out the uninstaller as the windows facility would do: shutil.copyfile(uninstaller, tmp_uninstaller) cmd = [ tmp_uninstaller, "/S", "_?=" + str(PureWindowsPath(self.cfg.install_prefix)), ] logging.info("running windows package uninstaller") logging.info(str(cmd)) uninstall = psutil.Popen(cmd) try: uninstall.wait(600) except psutil.TimeoutExpired as exc: print("uninstall timed out, taking screenshot, re-raising!") filename = "windows_uninstall_client_package_screenshot.png" with mss() as sct: sct.shot(output=filename) attach( filename, name="Screenshot ({fn})".format(fn=filename), attachment_type=AttachmentType.PNG, ) uninstall.kill() raise Exception("uninstall failed to complete on time") from exc if self.cfg.log_dir.exists(): shutil.rmtree(self.cfg.log_dir) if tmp_uninstaller.exists(): tmp_uninstaller.unlink()
def __init__(self, web_driver): self.driver = web_driver self.diprella_logo = WebDriverWait(self.driver, 15).until( EC.visibility_of_element_located((By.CSS_SELECTOR, ".page-logo"))) self.signup_link = WebDriverWait(self.driver, 15).until( EC.visibility_of_element_located( (By.CSS_SELECTOR, ".image-container-btn"))) self.facebook_login = self.driver.find_element_by_xpath( "//a[@class='social__icons-box-link facebook']") self.google_login = self.driver.find_element_by_xpath( "//a[@class='social__icons-box-link google']") self.linkedin_login = self.driver.find_element_by_xpath( "//a[@class='social__icons-box-link linkedin']") self.email_field = self.driver.find_element_by_xpath( "//input[@formcontrolname='email' and @type='text']") self.password_field = self.driver.find_element_by_xpath( "//input[@formcontrolname='password' and @type='password']") self.signin_button = self.driver.find_element_by_xpath( "//button[@type='submit']") self.incorrect_email_message = 0 self.incorrect_pass_message = 0 attach(self.driver.get_screenshot_as_png(), name="Signin page screenshot", attachment_type=attachment_type.PNG)
def un_install_server_package_for_upgrade(self): """hook to uninstall old package for upgrade""" # once we modify it, the uninstaller will leave it there... if self.get_arangod_conf().exists(): self.get_arangod_conf().unlink() uninstaller = "Uninstall.exe" tmp_uninstaller = Path("c:/tmp") / uninstaller uninstaller = self.cfg.install_prefix / uninstaller if uninstaller.exists(): # copy out the uninstaller as the windows facility would do: shutil.copyfile(uninstaller, tmp_uninstaller) cmd = [ tmp_uninstaller, "/PURGE_DB=0", "/S", "_?=" + str(PureWindowsPath(self.cfg.install_prefix)), ] logging.info("running windows package uninstaller") logging.info(str(cmd)) uninstall = psutil.Popen(cmd) try: uninstall.wait(600) except psutil.TimeoutExpired as exc: print("upgrade uninstall timed out, taking screenshot, re-raising!") filename = "windows_upgrade_screenshot.png" with mss() as sct: sct.shot(output=filename) attach( filename, name="Screenshot ({fn})".format(fn=filename), attachment_type=AttachmentType.PNG, ) uninstall.kill() raise Exception("upgrade uninstall failed to complete on time") from exc
def _log_response(response): is_json_response = json_response(response) headers = json.dumps(dict(response.headers), indent=4, sort_keys=True) response_body = response.json() if is_json_response else response.text with step('Received response'): logger.info('Received response:') logger.info('Headers:\n%s\n' 'Code: %s\n' 'Response body:\n%s' % (headers, response.status_code, json.dumps(response_body, indent=4))) attach(headers, 'Response headers', attachment_type=AttachmentType.TEXT) if is_json_response: attach(json.dumps(response_body, indent=4, sort_keys=True), 'Response body', attachment_type=AttachmentType.JSON) else: attach(response_body, 'Response body', attachment_type=AttachmentType.HTML) _log_add_separator()
def capture_screenshot(self): attach(self.driver.get_screenshot_as_png(), name=datetime.datetime.now().timestamp(), attachment_type=AttachmentType.PNG)
def run_monitored(self, executeable, args, timeout=60, result_line=dummy_line_result, verbose=False, expect_to_fail=False): """ run a script in background tracing with a dynamic timeout that its got output (is still alive...) """ run_cmd = [executeable] + args lh.log_cmd(run_cmd, verbose) with Popen( run_cmd, stdout=PIPE, stderr=PIPE, close_fds=ON_POSIX, cwd=self.cfg.test_data_dir.resolve(), ) as process: queue = Queue() thread1 = Thread( name="readIO", target=enqueue_stdout, args=(process.stdout, queue, self.connect_instance), ) thread2 = Thread( name="readErrIO", target=enqueue_stderr, args=(process.stderr, queue, self.connect_instance), ) thread1.start() thread2.start() try: print("me PID:%d launched PID:%d with LWPID:%d and LWPID:%d" % (os.getpid(), process.pid, thread1.native_id, thread2.native_id)) except AttributeError: print( "me PID:%d launched PID:%d with LWPID:N/A and LWPID:N/A" % (os.getpid(), process.pid)) # ... do other things here # out = logfile.open('wb') # read line without blocking have_timeout = False line_filter = False tcount = 0 close_count = 0 result = [] while not have_timeout: if not verbose: progress("sj" + str(tcount)) line = "" try: line = queue.get(timeout=1) line_filter = line_filter or result_line(line) except Empty: tcount += 1 if verbose: progress("T " + str(tcount)) have_timeout = tcount >= timeout else: tcount = 0 if isinstance(line, tuple): if verbose: print("e: " + str(line[0])) if not str(line[0]).startswith("#"): result.append(line) else: close_count += 1 if close_count == 2: print(" done!") break timeout_str = "" if have_timeout: timeout_str = "TIMEOUT OCCURED!" print(timeout_str) timeout_str += "\n" process.kill() rc_exit = process.wait() thread1.join() thread2.join() attach(str(rc_exit), f"Exit code: {str(rc_exit)}") if have_timeout or rc_exit != 0: res = (False, timeout_str + convert_result(result), rc_exit, line_filter) if expect_to_fail: return res raise CliExecutionException("Execution failed.", res, have_timeout) if not expect_to_fail: if len(result) == 0: res = (True, "", 0, line_filter) else: res = (True, convert_result(result), 0, line_filter) return res if len(result) == 0: res = (True, "", 0, line_filter) else: res = (True, convert_result(result), 0, line_filter) raise CliExecutionException( "Execution was expected to fail, but exited successfully.", res, have_timeout)
def save_page_source(self): """save current page""" html = self.webdriver.page_source filename = datetime.now().strftime("%d-%m-%Y_%H:%M:%S.%f") + ".html" self.progress("Saving pagedump to file: %s" % filename) attach(html, name="Pagedump of ({fn})".format(fn=filename), attachment_type=AttachmentType.HTML)
def screenshot(screenshot_as_png, name='Screenshot'): attach( screenshot_as_png, name=name, attachment_type=AttachmentType.PNG )
def message(msg, name='Message'): attach( msg, name=name, attachment_type=AttachmentType.TEXT )
def after_step(context, step): if step.status == "failed": attach(context.driver.get_screenshot_as_png(), name=datetime.datetime.now().timestamp(), attachment_type=AttachmentType.PNG)
def attach_and_clear_buffer(): attach(buffer_stream.getvalue(), 'Full log', attachment_type=AttachmentType.TEXT) buffer_stream.truncate(0) buffer_stream.seek(0)
def after_step(context, step): if step.status == 'failed': # Save session ID and quote ID zebra_cookie = context.driver.get_cookies() for item in zebra_cookie: if item.get('name') == 'sessionid': session_id = item.get('value') quote_id = return_quote_id(session_id, context) session_id_and_quote_id = 'Session ID: ' + session_id + '\n\n' + 'Quote ID: ' + quote_id attach(session_id_and_quote_id, name='Session ID and Quote ID', attachment_type='text/plain') # Save console logs string_of_logs = 'CONSOLE lOG' + '\n\n' for entry in context.driver.get_log('browser'): human_readable_time_stamp = datetime.datetime.fromtimestamp( entry['timestamp'] / 1000.0).strftime('%Y-%m-%d %H:%M:%S') timestamp = 'Timestamp: ' + str(human_readable_time_stamp) error_message = 'Error Message: ' + entry['message'] string_of_logs = string_of_logs + timestamp + '\n' + error_message + '\n\n' attach(str(string_of_logs), name='Console Log', attachment_type='text/plain') # Save screenshot attach(context.driver.get_screenshot_as_png(), name='{}'.format(step.name.encode('utf-8').strip()), attachment_type=AttachmentType.PNG) # attach(name='{}: {}'.format(context.scenario.name, step.name.encode('utf-8').strip(), context.session_id)) # def step_status(context, step): # context.test_name = context.scenario.name # step_name = re.sub('[^A-Za-z0-9]+', '_', step.name) # # if step.status == 'failed': # report_dir = Logger.create_test_folder(context.scenario.name) # _screenshot = os.path.join(report_dir, '{}__Fail.png'.format(step_name)) # try: # save_report_screenshot(context=context, step_name=step_name, screenshot=_screenshot) # time.sleep(5) # # attach_report_screenshot(context=context, step=step, screenshot=_screenshot) # except Exception as e: # print ('Failed to save or attach report: {}', e) # finally: # # context.allure.stop_step(Status.FAILED) # context.last_traceback = step.error_message # try: # context.last_error_message = step.error_message.split('ERROR:')[1] # except IndexError: # context.last_error_message = step.error_message # def save_report_screenshot(context, step_name, screenshot): # try: # context.driver.save_screenshot(screenshot) # except Exception as e: # print ('Failed to take screenshot to: {}. \n{}'.format(conf.config['logs'], e)) # print ('Screenshot name: {}'.format(step_name)) # def attach_report_screenshot(context, step, screenshot): # try: # with open(screenshot, 'rb') as _file: # allure.attach(_file.read(), name='{}_{}'.format(context.test_name, step.name.encode('utf-8').strip()), attachment_type=allure.attachment_type.PNG) # # context.allure.attach('{}_{}'.format(context.test_name, step.name.encode('utf-8').strip()), _file.read(), attachment_type=allure.attachment_type.PNG) # # except Exception as e: # print ('Failed to attach to report screenshot: {}. \nError: {}\n'.format(screenshot, e))
def __init__(self, web_driver: WebDriver): super().__init__(web_driver) attach(self.web_driver.get_screenshot_as_png(), name="Login Page screenshot", attachment_type=attachment_type.PNG)
def detect_instances(self): """see which arangods where spawned and inspect their logfiles""" lh.subsection("Instance Detection for {0.name}".format(self)) self.all_instances = [] logging.debug("waiting for frontend") logfiles = set() # logfiles that can be used for debugging # the more instances we expect to spawn the more patient: tries = 10 * self.expect_instance_count # Wait for forntend to become alive. all_instances_up = False while not all_instances_up and tries: self.all_instances = [] detected_instances = [] sys.stdout.write(".") sys.stdout.flush() for root, dirs, files in os.walk(self.basedir): for onefile in files: # logging.debug("f: " + root + os.path.sep + onefile) if onefile.endswith("log"): logfiles.add(str(Path(root) / onefile)) for name in dirs: # logging.debug("d: " + root + os.path.sep + name) match = None instance_class = None if name.startswith("sync"): match = re.match(r"(syncmaster|syncworker)(\d*)", name) instance_class = SyncInstance else: match = re.match( r"(agent|coordinator|dbserver|resilientsingle|single)(\d*)", name, ) instance_class = ArangodInstance # directory = self.basedir / name if match and len(match.group(2)) > 0: # we may see a `local-slave-*` directory inbetween, # hence we need to choose the current directory not # the starter toplevel dir for this: instance = instance_class( match.group(1), match.group(2), self.cfg.localhost, self.cfg.publicip, Path(root) / name, self.passvoid, self.cfg.ssl, ) instance.wait_for_logfile(tries) instance.detect_pid( ppid=self.instance.pid, full_binary_path=self.cfg.real_sbin_dir, offset=0, ) detected_instances.append(instance.instance_type) self.all_instances.append(instance) print(self.expect_instances) detected_instances.sort() print(detected_instances) attach(str(self.expect_instances), "Expected instances") attach(str(detected_instances), "Detected instances") if (self.expect_instances != detected_instances) or (not self.get_frontends()): tries -= 1 time.sleep(5) else: all_instances_up = True if not self.get_frontends(): print() logging.error("STARTER FAILED TO SPAWN ARANGOD") self.show_all_instances() logging.error("can not continue without frontend instance") logging.error("please check logs in" + str(self.basedir)) for logf in logfiles: logging.debug(logf) message = "if that does not help try to delete: " + str(self.basedir) logging.error(message) raise Exception(message) self.show_all_instances()
def pytest_exception_interact(node, call, report): if report.failed: attach(node.instance.initialized_webdriver.get_screenshot_as_png(), name="Screenshot of Diprella tests for test fails", attachment_type=attachment_type.PNG)
def get_rclone_config_file(self): """create a config file and return its full name""" filename = self.save_config("rclone_config.json") attach(self.get_config_json_sanitized(), "rclone_config.json", "application/json", "rclone_config.json") return filename