Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@
* **log:** shows test execution on .log file, with the same name as the project_name, errors are shown in stderr
* **portalio:** ReportPortalIO Web REST DB and reporter:
* **slack:** tests results are sent to Slack channel
* **web:** tests results can be seen in realtime on a browser
* **web:** tests results can be seen in realtime on a browser. use **-r-web-port PORT** to specify other than 9204
* **xml:** test results will be saved on report.xml file


# 2.3. Run:
- ### options:
* **-rid** RunID (ex: -rid 17, if not passed than current hour and minute will be used ex: 2359)
* **-rid** RunID (ex: -rid 17, if not passed then current hour and minute will be used ex: 2359)
* **-pn** ProjectName (ex: -pn jules)
* **-env** EnvironmentName to test (ex: -env dev)
* **-rf** ResultsFolder (ex: -rf "/qa/test_results/"), where the tests results will be stored
Expand Down
4 changes: 1 addition & 3 deletions testipy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#!/usr/bin/env python3

import logging


__version__ = "0.10.1"
__version__ = "0.10.2"
__app__ = "TestiPy"
__app_full__ = "Python Test Tool"
__author__ = "Pedro Nunes"
Expand Down
6 changes: 3 additions & 3 deletions testipy/configs/default_config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os

from testipy.configs import enums_data
from testipy.configs.enums_data import STATE_PASSED, STATE_FAILED

# run.py
default_project_name = "local"
Expand All @@ -24,8 +24,8 @@
separator_and_join_tags = "&"

# execute_tests.py
if_no_test_started_mark_as = enums_data.STATE_PASSED
count_as_failed_states = [enums_data.STATE_FAILED]
if_no_test_started_mark_as = STATE_PASSED
count_as_failed_states = [STATE_FAILED]
suite_threads = 1

# report_base.py
Expand Down
11 changes: 7 additions & 4 deletions testipy/engine/execute_tests.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
from __future__ import annotations
import os
import traceback
import concurrent.futures

from typing import List
from typing import List, TYPE_CHECKING

from testipy import get_exec_logger
from testipy.configs import enums_data, default_config
from testipy.engine.models import PackageAttr, SuiteAttr, TestMethodAttr
from testipy.lib_modules import common_methods as cm
from testipy.lib_modules.common_methods import synchronized
from testipy.lib_modules.state_counter import StateCounter
from testipy.lib_modules.textdecor import color_state
from testipy.lib_modules.start_arguments import StartArguments
from testipy.helpers.prettify import format_duration
from testipy.helpers.handle_assertions import ExpectedError
from testipy.reporter.report_manager import ReportManager
from testipy.reporter import SuiteDetails, TestDetails

if TYPE_CHECKING:
from testipy.models import PackageAttr, SuiteAttr, TestMethodAttr, SuiteDetails, TestDetails
from testipy.reporter.report_manager import ReportManager


_exec_logger = get_exec_logger()

Expand Down
6 changes: 4 additions & 2 deletions testipy/engine/read_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
from testipy.lib_modules import py_inspector, common_methods as cm
from testipy.lib_modules.args_parser import ArgsParser
from testipy.helpers import load_config
from testipy.engine.models import (
PackageAttr, SuiteAttr, TestMethodAttr,
from testipy.models.attr import (
PackageAttr,
SuiteAttr,
TestMethodAttr,
get_package_by_name,
mark_packages_suites_methods_ids,
show_test_structure,
Expand Down
9 changes: 5 additions & 4 deletions testipy/helpers/data_driven_testing.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
from __future__ import annotations

from abc import abstractmethod, ABC
from collections import OrderedDict
from enum import Enum
from typing import Union, Dict, List, Tuple
from typing import Union, Dict, List, Tuple, TYPE_CHECKING

from testipy.configs import enums_data
from testipy.reporter.package_manager import SuiteDetails, TestDetails
from testipy.reporter.report_manager import ReportManager
from testipy.helpers import get_traceback_tabulate, load_config, left_update_dict, prettify
from testipy.helpers.handle_assertions import ExpectedError, SkipTestError

if TYPE_CHECKING:
from testipy.models import SuiteDetails, TestDetails
from testipy.reporter import ReportManager


class RunMode(Enum):
SCENARIOS_AS_TESTS__USECASES_AS_TESTSTEPS = 1
Expand Down
7 changes: 5 additions & 2 deletions testipy/helpers/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,15 @@ def get_traceback_list(exc_value: BaseException) -> List[Dict]:
tbe = traceback.TracebackException.from_exception(exc_value)

# get stacktrace (cascade methods calls)
error_lines = [{
error_lines = [
{
"filename": frame_summary.filename,
"method" : frame_summary.name,
"lineno" : frame_summary.lineno,
"code" : frame_summary.line
} for frame_summary in tbe.stack]
}
for frame_summary in tbe.stack
]

# append error, by order of execution
result.append({
Expand Down
8 changes: 4 additions & 4 deletions testipy/helpers/handle_assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ def assert_equal_complex_object(


def assert_equal_dicts(
expected: Any,
received: Any,
expected: Dict,
received: Dict,
expected_name: str = "expected",
received_name: str = "received",
) -> None:
Expand All @@ -103,8 +103,8 @@ def assert_equal_dicts(


def assert_equal_lists(
expected: Any,
received: Any,
expected: List,
received: List,
expected_name: str = "expected",
received_name: str = "received",
same_len: bool = True,
Expand Down
1 change: 0 additions & 1 deletion testipy/lib_modules/args_parser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
from __future__ import annotations

import sys
Expand Down
1 change: 0 additions & 1 deletion testipy/lib_modules/browser_manager/playwright.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
import base64

from time import sleep
Expand Down
1 change: 0 additions & 1 deletion testipy/lib_modules/common_methods.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/usr/bin/env python3
from __future__ import annotations

import os
Expand Down
2 changes: 0 additions & 2 deletions testipy/lib_modules/py_inspector.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

import os
import importlib.util
import inspect
Expand Down
2 changes: 0 additions & 2 deletions testipy/lib_modules/webhook_http_listener.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/usr/bin/env python3

import sys
import threading
import json
Expand Down
2 changes: 2 additions & 0 deletions testipy/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from testipy.models.attr import PackageAttr, SuiteAttr, TestMethodAttr
from testipy.models.package_manager import PackageManager, PackageDetails, SuiteDetails, TestDetails
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from __future__ import annotations

from typing import Dict, List, Set, NamedTuple, Any, Union
from typing import Dict, List, Set, NamedTuple, Any, Union, TYPE_CHECKING
from tabulate import tabulate

from testipy.configs import enums_data, default_config
from testipy.engine.models import PackageAttr, SuiteAttr, TestMethodAttr
from testipy.lib_modules.common_methods import get_datetime_now
from testipy.lib_modules.state_counter import StateCounter

if TYPE_CHECKING:
from testipy.models import PackageAttr, SuiteAttr, TestMethodAttr
from testipy.reporter.report_manager import ReportManager


class TestInfo(NamedTuple):
timestamp: int
Expand Down Expand Up @@ -50,7 +52,7 @@ class PackageDetails(CommonDetails):
def __init__(self, parent: PackageManager, package_attr: PackageAttr, package_name: str = ""):
super(PackageDetails, self).__init__(package_name or package_attr.package_name)

self.parent = parent
self.parent: PackageManager = parent
self.package_attr: PackageAttr = package_attr
self.suite_manager: SuiteManager = SuiteManager(self)

Expand All @@ -69,12 +71,12 @@ class SuiteDetails(CommonDetails):
def __init__(self, parent: PackageDetails, suite_attr: SuiteAttr, suite_name: str = ""):
super(SuiteDetails, self).__init__(suite_name or suite_attr.name)

self.package = parent
self.package: PackageDetails = parent
self.suite_attr: SuiteAttr = suite_attr
self.current_test_method_attr: TestMethodAttr = None
self.test_state_by_prio: Dict[int, Set] = dict() # {2: {"PASS", "SKIP"}, 10: ...
self.rb_test_result_rows: List = []
self.test_manager = TestManager(self)
self.test_manager: TestManager = TestManager(self)

def set_current_test_method_attr(self, test_method_attr: Union[TestMethodAttr, None]) -> SuiteDetails:
self.current_test_method_attr = test_method_attr
Expand Down Expand Up @@ -119,19 +121,27 @@ class TestDetails(CommonDetails):
def __init__(self, parent: SuiteDetails, test_method_attr: TestMethodAttr, test_name: str = ""):
super(TestDetails, self).__init__(test_name or test_method_attr.name)

self.suite = parent
self.suite: SuiteDetails = parent
self.test_method_attr: TestMethodAttr = test_method_attr
self.rm: ReportManager = None

self.test_id: int = 0
self.test_usecase: str = ""
self.test_comment: str = test_method_attr.comment
self.test_state: str = ""
self.test_reason_of_state: str = ""

self._info = list()
self._test_step = StateCounter()
self._info: List[TestInfo] = list()
self._test_step: StateCounter = StateCounter()

def get_rm(self) -> ReportManager:
return self.rm

def endTest(self, state: str, reason_of_state: str, exc_value: BaseException = None):
self.end_time = get_datetime_now()
self.state_counter.inc_state(state, reason_of_state=reason_of_state, description="end test", exc_value=exc_value)
self.test_state = state
self.test_reason_of_state = reason_of_state

self.suite.update_package_suite_counters(self.get_prio(), state, reason_of_state)
self.suite.test_manager.remove_test_running(self)
Expand Down Expand Up @@ -216,7 +226,7 @@ def set_next_step_starting_from_now(self):
return self

def get_state(self):
return self.state_counter.get_last_state() or self._test_step.get_last_state()
return self.test_state or self._test_step.get_last_state()

def is_passed(self):
return self.get_state() == enums_data.STATE_PASSED
Expand All @@ -227,6 +237,9 @@ def is_failed(self):
def is_skipped(self):
return self.get_state() == enums_data.STATE_SKIPPED

def get_reason_of_state(self) -> str:
return self.test_reason_of_state or self._test_step.get_last_reason_of_state()

def __str__(self):
res = f"meid={self.get_method_id()} | teid={self.get_test_id()} | prio={self.get_prio()} | {self.get_name()}"
if usecase := self.get_usecase():
Expand Down
1 change: 0 additions & 1 deletion testipy/reporter/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
from testipy.reporter.report_interfaces import ReportInterface
from testipy.reporter.report_manager import ReportManager
from testipy.reporter.package_manager import PackageManager, PackageDetails, SuiteDetails, TestDetails
20 changes: 13 additions & 7 deletions testipy/reporter/report_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
from mimetypes import guess_type

from testipy.configs import enums_data, default_config
from testipy.engine.models import PackageAttr, SuiteAttr, TestMethodAttr
from testipy.models import PackageAttr, SuiteAttr, TestMethodAttr, PackageManager, PackageDetails, SuiteDetails, TestDetails
from testipy.reporter.report_interfaces import ReportInterface
from testipy.lib_modules.common_methods import get_current_date_time_ns, get_timestamp
from testipy.reporter.package_manager import PackageManager, PackageDetails, SuiteDetails, TestDetails


class ReportBase(ReportInterface):
Expand Down Expand Up @@ -95,11 +94,18 @@ def end_suite(self, sd: SuiteDetails):

# update DataFrame with all ended tests for this suite
df_size = self._df.shape[0]
new_rows = pd.DataFrame(sd.rb_test_result_rows,
columns=self._df_columns,
index=range(df_size, df_size + len(sd.rb_test_result_rows)))
self._df = new_rows if df_size == 0 else pd.concat(
[self._df, new_rows], axis=0, join="outer", ignore_index=True, verify_integrity=False, copy=False)
new_rows = pd.DataFrame(
sd.rb_test_result_rows,
columns=self._df_columns,
index=range(df_size, df_size + len(sd.rb_test_result_rows))
)

if df_size == 0:
self._df = new_rows
else:
df1 = self._df.dropna(axis=1, how="all")
df2 = new_rows.dropna(axis=1, how="all")
self._df = pd.concat([df1, df2], axis=0, join="outer", ignore_index=True, copy=False)

# clear list since they were added to DataFrame
sd.rb_test_result_rows.clear()
Expand Down
8 changes: 5 additions & 3 deletions testipy/reporter/report_interfaces.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
from __future__ import annotations
from typing import Union, List, Dict, TYPE_CHECKING
import os

from typing import Union, List, Dict
from abc import abstractmethod, ABC

from testipy import get_exec_logger
from testipy.configs import default_config
from testipy.engine.models import PackageAttr
from testipy.lib_modules.args_parser import ArgsParser
from testipy.lib_modules.start_arguments import StartArguments
from testipy.lib_modules.browser_manager import BrowserManager
from testipy.lib_modules import webhook_http_listener as HL
from testipy.reporter.package_manager import PackageDetails, SuiteDetails, TestDetails
from testipy.models import PackageDetails, SuiteDetails, TestDetails

if TYPE_CHECKING:
from testipy.models import PackageAttr


_exec_logger = get_exec_logger()
Expand Down
Loading