Best Python code snippet using lisa_python
testsuite.py
Source:testsuite.py
...369 self.name = func.__name__370 self.full_name = func.__qualname__371 self.qualname = func.__qualname__372 self._func = func373 _add_case_metadata(self)374 @wraps(self._func)375 def wrapper(*args: Any, **kwargs: Any) -> None:376 parameters: Dict[str, Any] = {}377 for name in kwargs.keys():378 if name in func.__annotations__:379 parameters[name] = kwargs[name]380 func(*args, **parameters)381 return wrapper382 @property383 def owner(self) -> str:384 if self._owner:385 return self._owner386 return self.suite.owner387class TestCaseRuntimeData:388 def __init__(self, metadata: TestCaseMetadata):389 self.metadata = metadata390 # all runtime setting fields391 self.select_action: str = ""392 self.times: int = 1393 self.retry: int = 0394 self.use_new_environment: bool = metadata.use_new_environment395 self.ignore_failure: bool = False396 self.environment_name: str = ""397 def __getattr__(self, key: str) -> Any:398 # return attributes of metadata for convenient399 assert self.metadata400 return getattr(self.metadata, key)401 def __repr__(self) -> str:402 return (403 f"name: {self.metadata.name}, "404 f"action: {self.select_action}, "405 f"times: {self.times}, retry: {self.retry}, "406 f"new_env: {self.use_new_environment}, "407 f"ignore_failure: {self.ignore_failure}, "408 f"env_name: {self.environment_name}"409 )410 def clone(self) -> TestCaseRuntimeData:411 cloned = TestCaseRuntimeData(self.metadata)412 fields = [413 constants.TESTCASE_SELECT_ACTION,414 constants.TESTCASE_TIMES,415 constants.TESTCASE_RETRY,416 constants.TESTCASE_USE_NEW_ENVIRONMENT,417 constants.TESTCASE_IGNORE_FAILURE,418 constants.ENVIRONMENT,419 ]420 set_filtered_fields(self, cloned, fields)421 return cloned422class TestSuite:423 def __init__(424 self,425 metadata: TestSuiteMetadata,426 ) -> None:427 super().__init__()428 self._metadata = metadata429 self._should_stop = False430 self.__log = get_logger("suite", metadata.name)431 def before_suite(self, log: Logger, **kwargs: Any) -> None:432 ...433 def after_suite(self, log: Logger, **kwargs: Any) -> None:434 ...435 def before_case(self, log: Logger, **kwargs: Any) -> None:436 ...437 def after_case(self, log: Logger, **kwargs: Any) -> None:438 ...439 def start(440 self,441 environment: Environment,442 # test cases to run, must be a test method in this class.443 case_results: List[TestResult],444 # case accessible variables445 case_variables: Dict[str, Any],446 ) -> None:447 suite_error_message = ""448 # set the environment is not new, when it's used by any suite.449 environment.is_new = False450 test_kwargs = {451 "environment": environment,452 "log": self.__log,453 "node": environment.default_node,454 # copy to prevent the data is changed and effect other cases.455 "variables": copy.copy(case_variables),456 }457 # replace to case's logger temporarily458 suite_log = self.__log459 (460 is_suite_continue,461 suite_error_message,462 suite_error_stacktrace,463 ) = self.__suite_method(464 self.before_suite, test_kwargs=test_kwargs, log=suite_log465 )466 for case_result in case_results:467 case_name = case_result.runtime_data.name468 case_result.environment = environment469 case_log = get_logger("case", case_name, parent=self.__log)470 case_log_path = self.__create_case_log_path(case_name)471 case_part_path = self.__get_test_part_path(case_log_path)472 case_working_path = self.__get_case_working_path(case_part_path)473 case_unique_name = case_log_path.name474 case_log_file = case_log_path / f"{case_log_path.name}.log"475 case_log_handler = create_file_handler(case_log_file, case_log)476 add_handler(case_log_handler, environment.log)477 case_kwargs = test_kwargs.copy()478 case_kwargs.update({"case_name": case_unique_name})479 case_kwargs.update({"log": case_log})480 case_kwargs.update({"log_path": case_log_path})481 case_kwargs.update({"working_path": case_working_path})482 case_kwargs.update({"part_path": case_part_path})483 case_kwargs.update({"result": case_result})484 case_log.info(485 f"test case '{case_result.runtime_data.full_name}' is running"486 )487 is_continue: bool = is_suite_continue488 total_timer = create_timer()489 case_result.log_file = case_log_file.relative_to(490 constants.RUN_LOCAL_LOG_PATH491 ).as_posix()492 case_result.set_status(TestStatus.RUNNING, "")493 case_timeout = case_result.runtime_data.metadata.timeout494 if is_continue:495 is_continue = self.__before_case(496 case_result=case_result,497 timeout=case_timeout,498 test_kwargs=case_kwargs,499 log=case_log,500 )501 else:502 case_result.stacktrace = suite_error_stacktrace503 case_result.set_status(TestStatus.SKIPPED, suite_error_message)504 if is_continue:505 self.__run_case(506 case_result=case_result,507 timeout=case_timeout,508 test_kwargs=case_kwargs,509 log=case_log,510 )511 self.__after_case(512 case_result=case_result,513 timeout=case_timeout,514 test_kwargs=case_kwargs,515 log=case_log,516 )517 case_log.info(518 f"result: {case_result.status.name}, " f"elapsed: {total_timer}"519 )520 remove_handler(case_log_handler, case_log)521 remove_handler(case_log_handler, environment.log)522 if case_log_handler:523 case_log_handler.close()524 if self._should_stop:525 suite_log.info("received stop message, stop run")526 break527 self.__suite_method(self.after_suite, test_kwargs=test_kwargs, log=suite_log)528 def stop(self) -> None:529 self._should_stop = True530 def __create_case_log_path(self, case_name: str) -> Path:531 while True:532 path = (533 constants.RUN_LOCAL_LOG_PATH534 / "tests"535 / f"{get_datetime_path()}-{case_name}"536 )537 if not path.exists():538 break539 sleep(0.1)540 # avoid to create folder for UT541 if not is_unittest():542 path.mkdir(parents=True)543 return path544 def __get_test_part_path(self, log_path: Path) -> Path:545 if is_unittest():546 return Path()547 return Path(log_path.parts[-2]) / log_path.parts[-1]548 def __get_case_working_path(self, test_part_path: Path) -> Path:549 if is_unittest():550 return Path()551 # The working path should be the same name as log_path, so it's easy to552 # associated. Unlike the log path, the working path won't be created, because553 # it's not used in most cases. So it doesn't need to be created too. The554 # test case should create it, when it's used.555 working_path = constants.RUN_LOCAL_WORKING_PATH / test_part_path556 return working_path557 def __suite_method(558 self, method: Callable[..., Any], test_kwargs: Dict[str, Any], log: Logger559 ) -> Tuple[bool, str, Optional[str]]:560 result: bool = True561 message: str = ""562 timer = create_timer()563 method_name = method.__name__564 stacktrace: Optional[str] = None565 try:566 self.__call_with_retry_and_timeout(567 method,568 retries=0,569 timeout=3600,570 log=log,571 test_kwargs=test_kwargs,572 )573 except Exception as identifier:574 result = False575 message = f"{method_name}: {identifier}"576 stacktrace = traceback.format_exc()577 log.debug(f"{method_name} end in {timer}")578 return result, message, stacktrace579 def __before_case(580 self,581 case_result: TestResult,582 timeout: int,583 test_kwargs: Dict[str, Any],584 log: Logger,585 ) -> bool:586 result: bool = True587 timer = create_timer()588 try:589 self.__call_with_retry_and_timeout(590 self.before_case,591 retries=case_result.runtime_data.retry,592 timeout=timeout,593 log=log,594 test_kwargs=test_kwargs,595 )596 except Exception as identifier:597 log.error("before_case: ", exc_info=identifier)598 case_result.stacktrace = traceback.format_exc()599 case_result.set_status(TestStatus.SKIPPED, f"before_case: {identifier}")600 result = False601 log.debug(f"before_case end in {timer}")602 return result603 def __after_case(604 self,605 case_result: TestResult,606 timeout: int,607 test_kwargs: Dict[str, Any],608 log: Logger,609 ) -> None:610 timer = create_timer()611 try:612 self.__call_with_retry_and_timeout(613 self.after_case,614 retries=case_result.runtime_data.retry,615 timeout=timeout,616 log=log,617 test_kwargs=test_kwargs,618 )619 except Exception as identifier:620 # after case doesn't impact test case result.621 log.error("after_case failed", exc_info=identifier)622 log.debug(f"after_case end in {timer}")623 def __run_case(624 self,625 case_result: TestResult,626 timeout: int,627 test_kwargs: Dict[str, Any],628 log: Logger,629 ) -> None:630 timer = create_timer()631 case_name = case_result.runtime_data.name632 test_method = getattr(self, case_name)633 try:634 self.__call_with_retry_and_timeout(635 test_method,636 retries=case_result.runtime_data.retry,637 timeout=timeout,638 log=log,639 test_kwargs=test_kwargs,640 )641 case_result.set_status(TestStatus.PASSED, "")642 except Exception as identifier:643 case_result.handle_exception(exception=identifier, log=log)644 log.debug(f"case end in {timer}")645 def __call_with_retry_and_timeout(646 self,647 method: Callable[..., Any],648 retries: int,649 timeout: int,650 log: Logger,651 test_kwargs: Dict[str, Any],652 ) -> None:653 try:654 retry_call(655 func_timeout,656 fkwargs={657 "timeout": timeout,658 "func": method,659 "kwargs": test_kwargs,660 },661 exceptions=Exception,662 tries=retries + 1,663 logger=log,664 )665 except FunctionTimedOut:666 # FunctionTimedOut is a special exception. If it's not captured667 # explicitly, it will make the whole program exit.668 raise TimeoutError(f"time out in {timeout} seconds.")669def get_suites_metadata() -> Dict[str, TestSuiteMetadata]:670 return _all_suites671def get_cases_metadata() -> Dict[str, TestCaseMetadata]:672 return _all_cases673def _add_suite_metadata(metadata: TestSuiteMetadata) -> None:674 key = metadata.test_class.__name__675 exist_metadata = _all_suites.get(key)676 if exist_metadata is None:677 _all_suites[key] = metadata678 else:679 raise LisaException(680 f"duplicate test class name: {key}, "681 f"new: [{metadata}], exists: [{exist_metadata}]"682 )683 class_prefix = f"{key}."684 for test_case in _all_cases.values():685 if test_case.full_name.startswith(class_prefix):686 _add_case_to_suite(metadata, test_case)687 log = get_logger("init", "test")688 log.info(689 f"registered test suite '{key}' "690 f"with test cases: '{', '.join([case.name for case in metadata.cases])}'"691 )692def _add_case_metadata(metadata: TestCaseMetadata) -> None:693 qualname = metadata.qualname694 if _all_cases.get(qualname) is None:695 _all_cases[qualname] = metadata696 else:697 raise LisaException(698 f"found duplicate test class name: {qualname}. "699 "Check there is no duplicate test class name, "700 "and not import by extension twice."701 )702 # this should be None in current observation.703 # the methods are loaded prior to test class704 # in case logic is changed, so keep this logic705 # to make two collection consistent.706 class_name = qualname.split(".")[0]...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!