hardpy 0.5.1__py3-none-any.whl → 0.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hardpy/__init__.py +10 -0
- hardpy/cli/__init__.py +0 -0
- hardpy/cli/cli.py +145 -0
- hardpy/cli/template.py +220 -0
- hardpy/common/__init__.py +0 -0
- hardpy/common/config.py +159 -0
- hardpy/hardpy_panel/api.py +49 -6
- hardpy/hardpy_panel/frontend/dist/asset-manifest.json +3 -3
- hardpy/hardpy_panel/frontend/dist/index.html +1 -1
- hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js +3 -0
- hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js.map +1 -0
- hardpy/pytest_hardpy/db/base_connector.py +7 -1
- hardpy/pytest_hardpy/db/base_server.py +4 -4
- hardpy/pytest_hardpy/db/base_store.py +13 -3
- hardpy/pytest_hardpy/db/const.py +3 -0
- hardpy/pytest_hardpy/db/schema.py +47 -11
- hardpy/pytest_hardpy/db/statestore.py +11 -0
- hardpy/pytest_hardpy/plugin.py +93 -33
- hardpy/pytest_hardpy/pytest_call.py +65 -5
- hardpy/pytest_hardpy/pytest_wrapper.py +62 -60
- hardpy/pytest_hardpy/reporter/base.py +1 -1
- hardpy/pytest_hardpy/reporter/hook_reporter.py +7 -3
- hardpy/pytest_hardpy/result/report_loader/couchdb_loader.py +3 -2
- hardpy/pytest_hardpy/result/report_reader/couchdb_reader.py +2 -2
- hardpy/pytest_hardpy/utils/__init__.py +7 -4
- hardpy/pytest_hardpy/utils/connection_data.py +17 -0
- hardpy/pytest_hardpy/utils/const.py +4 -14
- hardpy/pytest_hardpy/utils/dialog_box.py +1 -1
- hardpy/pytest_hardpy/utils/exception.py +14 -0
- hardpy/pytest_hardpy/utils/node_info.py +1 -1
- hardpy/pytest_hardpy/utils/progress_calculator.py +1 -1
- hardpy/pytest_hardpy/utils/singleton.py +1 -1
- {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/METADATA +25 -57
- {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/RECORD +38 -34
- {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/entry_points.txt +1 -1
- hardpy/hardpy_panel/frontend/dist/static/js/main.da686f40.js +0 -3
- hardpy/hardpy_panel/frontend/dist/static/js/main.da686f40.js.map +0 -1
- hardpy/hardpy_panel/runner.py +0 -54
- hardpy/pytest_hardpy/utils/config_data.py +0 -35
- /hardpy/hardpy_panel/frontend/dist/static/js/{main.da686f40.js.LICENSE.txt → main.7c954faf.js.LICENSE.txt} +0 -0
- {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/WHEEL +0 -0
- {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Copyright (c) 2024 Everypin
|
|
2
2
|
# GNU General Public License v3.0 (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
3
|
|
|
4
|
-
import sys
|
|
5
4
|
import signal
|
|
6
|
-
import subprocess
|
|
7
|
-
|
|
5
|
+
import subprocess # noqa: S404
|
|
6
|
+
import sys
|
|
8
7
|
from platform import system
|
|
8
|
+
from socket import socket
|
|
9
9
|
|
|
10
|
-
from hardpy.
|
|
10
|
+
from hardpy.common.config import ConfigManager
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class PyTestWrapper
|
|
13
|
+
class PyTestWrapper:
|
|
14
14
|
"""Wrapper for pytest subprocess."""
|
|
15
15
|
|
|
16
16
|
def __init__(self):
|
|
@@ -19,13 +19,14 @@ class PyTestWrapper(object):
|
|
|
19
19
|
|
|
20
20
|
# Make sure test structure is stored in DB
|
|
21
21
|
# before clients come in
|
|
22
|
-
self.config =
|
|
23
|
-
self.collect()
|
|
22
|
+
self.config = ConfigManager().get_config()
|
|
23
|
+
self.collect(is_clear_database=True)
|
|
24
24
|
|
|
25
|
-
def start(self):
|
|
25
|
+
def start(self) -> bool:
|
|
26
26
|
"""Start pytest subprocess.
|
|
27
27
|
|
|
28
|
-
Returns
|
|
28
|
+
Returns:
|
|
29
|
+
bool: True if pytest was started
|
|
29
30
|
"""
|
|
30
31
|
if self.python_executable is None:
|
|
31
32
|
return False
|
|
@@ -39,21 +40,15 @@ class PyTestWrapper(object):
|
|
|
39
40
|
self.python_executable,
|
|
40
41
|
"-m",
|
|
41
42
|
"pytest",
|
|
42
|
-
"--hardpy-
|
|
43
|
-
|
|
44
|
-
"--hardpy-dbh",
|
|
45
|
-
self.config.db_host,
|
|
46
|
-
"--hardpy-dbu",
|
|
47
|
-
self.config.db_user,
|
|
48
|
-
"--hardpy-dbpw",
|
|
49
|
-
self.config.db_pswd,
|
|
43
|
+
"--hardpy-db-url",
|
|
44
|
+
self.config.database.connection_url(),
|
|
50
45
|
"--hardpy-sp",
|
|
51
|
-
str(self.config.
|
|
52
|
-
"--hardpy-
|
|
53
|
-
self.config.
|
|
46
|
+
str(self.config.socket.port),
|
|
47
|
+
"--hardpy-sh",
|
|
48
|
+
self.config.socket.host,
|
|
54
49
|
"--hardpy-pt",
|
|
55
50
|
],
|
|
56
|
-
cwd=
|
|
51
|
+
cwd=ConfigManager().get_tests_path(),
|
|
57
52
|
)
|
|
58
53
|
elif system() == "Windows":
|
|
59
54
|
self._proc = subprocess.Popen( # noqa: S603
|
|
@@ -61,21 +56,15 @@ class PyTestWrapper(object):
|
|
|
61
56
|
self.python_executable,
|
|
62
57
|
"-m",
|
|
63
58
|
"pytest",
|
|
64
|
-
"--hardpy-
|
|
65
|
-
|
|
66
|
-
"--hardpy-dbh",
|
|
67
|
-
self.config.db_host,
|
|
68
|
-
"--hardpy-dbu",
|
|
69
|
-
self.config.db_user,
|
|
70
|
-
"--hardpy-dbpw",
|
|
71
|
-
self.config.db_pswd,
|
|
59
|
+
"--hardpy-db-url",
|
|
60
|
+
self.config.database.connection_url(),
|
|
72
61
|
"--hardpy-sp",
|
|
73
|
-
str(self.config.
|
|
74
|
-
"--hardpy-
|
|
75
|
-
self.config.
|
|
62
|
+
str(self.config.socket.port),
|
|
63
|
+
"--hardpy-sh",
|
|
64
|
+
self.config.socket.host,
|
|
76
65
|
"--hardpy-pt",
|
|
77
66
|
],
|
|
78
|
-
cwd=
|
|
67
|
+
cwd=ConfigManager().get_tests_path(),
|
|
79
68
|
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
|
|
80
69
|
)
|
|
81
70
|
|
|
@@ -84,7 +73,8 @@ class PyTestWrapper(object):
|
|
|
84
73
|
def stop(self) -> bool:
|
|
85
74
|
"""Stop pytest subprocess.
|
|
86
75
|
|
|
87
|
-
Returns
|
|
76
|
+
Returns:
|
|
77
|
+
bool: True if pytest was running and stopped
|
|
88
78
|
"""
|
|
89
79
|
if self.is_running() and self._proc:
|
|
90
80
|
if system() == "Linux":
|
|
@@ -94,10 +84,15 @@ class PyTestWrapper(object):
|
|
|
94
84
|
return True
|
|
95
85
|
return False
|
|
96
86
|
|
|
97
|
-
def collect(self) -> bool:
|
|
87
|
+
def collect(self, is_clear_database: bool = False) -> bool:
|
|
98
88
|
"""Perform pytest collection.
|
|
99
89
|
|
|
100
|
-
|
|
90
|
+
Args:
|
|
91
|
+
is_clear_database (bool): indicates whether database
|
|
92
|
+
should be cleared. Defaults to False.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
bool: True if collection was started
|
|
101
96
|
"""
|
|
102
97
|
if self.python_executable is None:
|
|
103
98
|
return False
|
|
@@ -105,45 +100,52 @@ class PyTestWrapper(object):
|
|
|
105
100
|
if self.is_running():
|
|
106
101
|
return False
|
|
107
102
|
|
|
103
|
+
args = [
|
|
104
|
+
"-m",
|
|
105
|
+
"pytest",
|
|
106
|
+
"--collect-only",
|
|
107
|
+
"--hardpy-db-url",
|
|
108
|
+
self.config.database.connection_url(),
|
|
109
|
+
"--hardpy-sp",
|
|
110
|
+
str(self.config.socket.port),
|
|
111
|
+
"--hardpy-sh",
|
|
112
|
+
self.config.socket.host,
|
|
113
|
+
"--hardpy-pt",
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
if is_clear_database:
|
|
117
|
+
args.append("--hardpy-clear-database")
|
|
118
|
+
args.append(str(is_clear_database))
|
|
119
|
+
|
|
108
120
|
subprocess.Popen( # noqa: S603
|
|
109
|
-
[
|
|
110
|
-
|
|
111
|
-
"-m" "pytest",
|
|
112
|
-
"--collect-only",
|
|
113
|
-
"--hardpy-dbp",
|
|
114
|
-
str(self.config.db_port),
|
|
115
|
-
"--hardpy-dbh",
|
|
116
|
-
self.config.db_host,
|
|
117
|
-
"--hardpy-dbu",
|
|
118
|
-
self.config.db_user,
|
|
119
|
-
"--hardpy-dbpw",
|
|
120
|
-
self.config.db_pswd,
|
|
121
|
-
"--hardpy-pt",
|
|
122
|
-
],
|
|
123
|
-
cwd=self.config.tests_dir.absolute(),
|
|
121
|
+
[self.python_executable, *args],
|
|
122
|
+
cwd=ConfigManager().get_tests_path(),
|
|
124
123
|
)
|
|
125
124
|
return True
|
|
126
125
|
|
|
127
|
-
def
|
|
128
|
-
"""
|
|
126
|
+
def send_data(self, data: str):
|
|
127
|
+
"""Send data to pytest subprocess.
|
|
129
128
|
|
|
130
129
|
Args:
|
|
131
|
-
|
|
130
|
+
data (str): Data to be sent. Can be dialog
|
|
131
|
+
box output or operator message visibility.
|
|
132
132
|
|
|
133
133
|
Returns:
|
|
134
|
-
bool: True if dialog box was confirmed, else False
|
|
134
|
+
bool: True if dialog box was confirmed/closed, else False
|
|
135
135
|
"""
|
|
136
|
-
config_data = ConfigData()
|
|
137
|
-
|
|
138
136
|
try:
|
|
139
137
|
client = socket()
|
|
140
|
-
client.connect((
|
|
141
|
-
client.sendall(
|
|
138
|
+
client.connect((self.config.socket.host, self.config.socket.port))
|
|
139
|
+
client.sendall(data.encode("utf-8"))
|
|
142
140
|
client.close()
|
|
143
141
|
except Exception:
|
|
144
142
|
return False
|
|
145
143
|
return True
|
|
146
144
|
|
|
147
145
|
def is_running(self) -> bool | None:
|
|
148
|
-
"""Check if pytest is running.
|
|
146
|
+
"""Check if pytest is running.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
bool | None: True if self._proc is not None
|
|
150
|
+
"""
|
|
149
151
|
return self._proc and self._proc.poll() is None
|
|
@@ -9,14 +9,16 @@ from natsort import natsorted
|
|
|
9
9
|
|
|
10
10
|
from hardpy.pytest_hardpy.db import DatabaseField as DF
|
|
11
11
|
from hardpy.pytest_hardpy.reporter.base import BaseReporter
|
|
12
|
-
from hardpy.pytest_hardpy.utils import TestStatus,
|
|
12
|
+
from hardpy.pytest_hardpy.utils import TestStatus, NodeInfo
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class HookReporter(BaseReporter):
|
|
16
16
|
"""Reporter for using in the hook HardPy plugin's hooks."""
|
|
17
17
|
|
|
18
|
-
def __init__(self): # noqa: WPS612
|
|
18
|
+
def __init__(self, is_clear_database: bool = False): # noqa: WPS612
|
|
19
19
|
super().__init__()
|
|
20
|
+
if is_clear_database:
|
|
21
|
+
self._statestore.clear()
|
|
20
22
|
self._log = getLogger(__name__)
|
|
21
23
|
|
|
22
24
|
def init_doc(self, doc_name: str):
|
|
@@ -33,6 +35,7 @@ class HookReporter(BaseReporter):
|
|
|
33
35
|
self.set_doc_value(DF.PROGRESS, 0)
|
|
34
36
|
self.set_doc_value(DF.DRIVERS, {})
|
|
35
37
|
self.set_doc_value(DF.ARTIFACT, {}, runstore_only=True)
|
|
38
|
+
self.set_doc_value(DF.OPERATOR_MSG, {}, statestore_only=True)
|
|
36
39
|
|
|
37
40
|
def start(self):
|
|
38
41
|
"""Start test."""
|
|
@@ -43,7 +46,7 @@ class HookReporter(BaseReporter):
|
|
|
43
46
|
self.set_doc_value(DF.TIMEZONE, tzname) # noqa: WPS432
|
|
44
47
|
self.set_doc_value(DF.PROGRESS, 0)
|
|
45
48
|
|
|
46
|
-
def finish(self, status:
|
|
49
|
+
def finish(self, status: TestStatus):
|
|
47
50
|
"""Finish test.
|
|
48
51
|
|
|
49
52
|
This method must be called at the end of test run.
|
|
@@ -196,6 +199,7 @@ class HookReporter(BaseReporter):
|
|
|
196
199
|
DF.STOP_TIME: None,
|
|
197
200
|
DF.ASSERTION_MSG: None,
|
|
198
201
|
DF.MSG: None,
|
|
202
|
+
DF.ATTEMPT: 0,
|
|
199
203
|
}
|
|
200
204
|
|
|
201
205
|
if item.get(node_info.module_id) is None: # noqa: WPS204
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
# GNU General Public License v3.0 (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
3
|
|
|
4
4
|
from logging import getLogger
|
|
5
|
+
from uuid import uuid4
|
|
5
6
|
|
|
6
7
|
from pycouchdb import Server as DbServer
|
|
7
8
|
from pycouchdb.exceptions import Conflict
|
|
@@ -11,7 +12,7 @@ from hardpy.pytest_hardpy.db.schema import ResultRunStore
|
|
|
11
12
|
from hardpy.pytest_hardpy.result.couchdb_config import CouchdbConfig
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
class CouchdbLoader
|
|
15
|
+
class CouchdbLoader:
|
|
15
16
|
"""CouchDB report generator."""
|
|
16
17
|
|
|
17
18
|
def __init__(self, config: CouchdbConfig):
|
|
@@ -51,7 +52,7 @@ class CouchdbLoader(object):
|
|
|
51
52
|
device_serial_number = report.dut.serial_number
|
|
52
53
|
if not device_serial_number:
|
|
53
54
|
self._log.warning("Device serial number is not provided in the report.")
|
|
54
|
-
return f"report_{timestamp}"
|
|
55
|
+
return f"report_{timestamp}_no_serial_{str(uuid4())[:6]}"
|
|
55
56
|
return f"report_{timestamp}_{device_serial_number}"
|
|
56
57
|
|
|
57
58
|
def _schema_to_dict(self, report: ResultRunStore, report_id: str) -> dict:
|
|
@@ -15,7 +15,7 @@ from hardpy.pytest_hardpy.result.couchdb_config import CouchdbConfig
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
@dataclass
|
|
18
|
-
class ReportInfo
|
|
18
|
+
class ReportInfo:
|
|
19
19
|
"""CouchDB report info."""
|
|
20
20
|
|
|
21
21
|
name: str
|
|
@@ -26,7 +26,7 @@ class ReportInfo(object):
|
|
|
26
26
|
first_failed_test_id: Optional[str]
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
class CouchdbReader
|
|
29
|
+
class CouchdbReader:
|
|
30
30
|
"""CouchDB report info reader."""
|
|
31
31
|
|
|
32
32
|
def __init__(self, config: CouchdbConfig):
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
from hardpy.pytest_hardpy.utils.node_info import NodeInfo
|
|
5
5
|
from hardpy.pytest_hardpy.utils.progress_calculator import ProgressCalculator
|
|
6
|
-
from hardpy.pytest_hardpy.utils.const import TestStatus
|
|
6
|
+
from hardpy.pytest_hardpy.utils.const import TestStatus
|
|
7
7
|
from hardpy.pytest_hardpy.utils.singleton import Singleton
|
|
8
|
-
from hardpy.pytest_hardpy.utils.
|
|
8
|
+
from hardpy.pytest_hardpy.utils.connection_data import ConnectionData
|
|
9
9
|
from hardpy.pytest_hardpy.utils.exception import (
|
|
10
10
|
DuplicateSerialNumberError,
|
|
11
|
+
DuplicatePartNumberError,
|
|
12
|
+
DuplicateTestStandNameError,
|
|
11
13
|
DuplicateDialogBoxError,
|
|
12
14
|
WidgetInfoError,
|
|
13
15
|
)
|
|
@@ -27,10 +29,11 @@ __all__ = [
|
|
|
27
29
|
"NodeInfo",
|
|
28
30
|
"ProgressCalculator",
|
|
29
31
|
"TestStatus",
|
|
30
|
-
"RunStatus",
|
|
31
32
|
"Singleton",
|
|
32
|
-
"
|
|
33
|
+
"ConnectionData",
|
|
33
34
|
"DuplicateSerialNumberError",
|
|
35
|
+
"DuplicatePartNumberError",
|
|
36
|
+
"DuplicateTestStandNameError",
|
|
34
37
|
"DuplicateDialogBoxError",
|
|
35
38
|
"WidgetInfoError",
|
|
36
39
|
"DialogBox",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Copyright (c) 2024 Everypin
|
|
2
|
+
# GNU General Public License v3.0 (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
|
+
|
|
4
|
+
from socket import gethostname
|
|
5
|
+
|
|
6
|
+
from hardpy.pytest_hardpy.utils.singleton import Singleton
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ConnectionData(Singleton):
|
|
10
|
+
"""Connection data storage."""
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
if not self._initialized:
|
|
14
|
+
self.database_url: str = "http://dev:dev@localhost:5984/"
|
|
15
|
+
self.socket_host: str = gethostname()
|
|
16
|
+
self.socket_port: int = 6525
|
|
17
|
+
self._initialized = True
|
|
@@ -5,7 +5,10 @@ from enum import Enum
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class TestStatus(str, Enum): # noqa: WPS600
|
|
8
|
-
"""Pytest test status.
|
|
8
|
+
"""Pytest test status.
|
|
9
|
+
|
|
10
|
+
Statuses, that can be returned by Pytest.
|
|
11
|
+
"""
|
|
9
12
|
|
|
10
13
|
PASSED = "passed"
|
|
11
14
|
FAILED = "failed"
|
|
@@ -14,16 +17,3 @@ class TestStatus(str, Enum): # noqa: WPS600
|
|
|
14
17
|
RUN = "run"
|
|
15
18
|
READY = "ready"
|
|
16
19
|
STOPPED = "stopped"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class RunStatus(str, Enum): # noqa: WPS600
|
|
20
|
-
"""Pytest run status."""
|
|
21
|
-
|
|
22
|
-
PASSED = "passed"
|
|
23
|
-
FAILED = "failed"
|
|
24
|
-
STOPPED = "stopped"
|
|
25
|
-
STARTED = "started"
|
|
26
|
-
COLLECTED = "collected"
|
|
27
|
-
BUSY = "busy"
|
|
28
|
-
READY = "ready"
|
|
29
|
-
ERROR = "error"
|
|
@@ -147,7 +147,7 @@ class CheckboxWidget(IWidget):
|
|
|
147
147
|
"""
|
|
148
148
|
super().__init__(WidgetType.CHECKBOX)
|
|
149
149
|
if not fields:
|
|
150
|
-
raise ValueError("
|
|
150
|
+
raise ValueError("Checkbox must have at least one field")
|
|
151
151
|
self.info["fields"] = fields
|
|
152
152
|
|
|
153
153
|
def convert_data(self, input_data: str) -> list[str] | None:
|
|
@@ -16,6 +16,20 @@ class DuplicateSerialNumberError(HardpyError):
|
|
|
16
16
|
super().__init__(self.__doc__) # type: ignore
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
class DuplicatePartNumberError(HardpyError):
|
|
20
|
+
"""The part number has already been determined."""
|
|
21
|
+
|
|
22
|
+
def __init__(self):
|
|
23
|
+
super().__init__(self.__doc__) # type: ignore
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class DuplicateTestStandNameError(HardpyError):
|
|
27
|
+
"""The test stand name has already been determined."""
|
|
28
|
+
|
|
29
|
+
def __init__(self):
|
|
30
|
+
super().__init__(self.__doc__) # type: ignore
|
|
31
|
+
|
|
32
|
+
|
|
19
33
|
class DuplicateDialogBoxError(HardpyError):
|
|
20
34
|
"""The dialog box has already been determined."""
|
|
21
35
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hardpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.1
|
|
4
4
|
Summary: HardPy library for device testing
|
|
5
5
|
Project-URL: Homepage, https://github.com/everypinio/hardpy/
|
|
6
6
|
Project-URL: Documentation, https://everypinio.github.io/hardpy/
|
|
@@ -28,7 +28,9 @@ Requires-Dist: glom>=23.3.0
|
|
|
28
28
|
Requires-Dist: natsort>=8.4.0
|
|
29
29
|
Requires-Dist: pycouchdb>=1.14.2
|
|
30
30
|
Requires-Dist: pydantic>=2.4.0
|
|
31
|
-
Requires-Dist: pytest<9
|
|
31
|
+
Requires-Dist: pytest<9,>=7
|
|
32
|
+
Requires-Dist: rtoml~=0.11.0
|
|
33
|
+
Requires-Dist: typer<1.0,>=0.12
|
|
32
34
|
Requires-Dist: uvicorn>=0.23.2
|
|
33
35
|
Provides-Extra: build
|
|
34
36
|
Requires-Dist: build==1.0.3; extra == 'build'
|
|
@@ -74,71 +76,37 @@ HardPy allows you to:
|
|
|
74
76
|
pip install hardpy
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
## Examples
|
|
78
|
-
|
|
79
|
-
Find examples of using the **HardPy** in the `examples` folder.
|
|
80
|
-
|
|
81
79
|
## Getting Started
|
|
82
80
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
For Windows, follow the instructions from the
|
|
87
|
-
[documentation](https://everypinio.github.io/hardpy/documentation/database/#couchdb-instance).
|
|
88
|
-
|
|
89
|
-
Launch CouchDB with Docker.
|
|
90
|
-
The Docker version must be 24.0.0 or higher.
|
|
91
|
-
Create `couchdb.ini` file:
|
|
92
|
-
|
|
93
|
-
```ini
|
|
94
|
-
[chttpd]
|
|
95
|
-
enable_cors=true
|
|
96
|
-
|
|
97
|
-
[cors]
|
|
98
|
-
origins = *
|
|
99
|
-
methods = GET, PUT, POST, HEAD, DELETE
|
|
100
|
-
credentials = true
|
|
101
|
-
headers = accept, authorization, content-type, origin, referer, x-csrf-token
|
|
81
|
+
1. Create your first test bench.
|
|
82
|
+
```bash
|
|
83
|
+
hardpy init
|
|
102
84
|
```
|
|
103
|
-
|
|
104
|
-
Run the Docker container from folder with couchdb.ini file:
|
|
105
|
-
|
|
85
|
+
2. Launch [CouchDB](https://couchdb.apache.org/) database via [docker compose](https://docs.docker.com/compose/) in the background.
|
|
106
86
|
```bash
|
|
107
|
-
|
|
87
|
+
cd tests
|
|
88
|
+
docker compose up -d
|
|
108
89
|
```
|
|
109
|
-
|
|
110
|
-
Command for Windows:
|
|
111
|
-
|
|
90
|
+
3. Launch HardPy operator panel.
|
|
112
91
|
```bash
|
|
113
|
-
|
|
92
|
+
hardpy run
|
|
114
93
|
```
|
|
94
|
+
4. View operator panel in browser: http://localhost:8000/
|
|
115
95
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
```python
|
|
121
|
-
# test_1.py
|
|
122
|
-
import pytest
|
|
123
|
-
|
|
124
|
-
def test_one():
|
|
125
|
-
assert True
|
|
126
|
-
```
|
|
127
|
-
#### Operator panel
|
|
96
|
+
<h1 align="center">
|
|
97
|
+
<img src="https://everypinio.github.io/hardpy/img/hardpy_operator_panel_hello_hardpy.png"
|
|
98
|
+
alt="hardpy operator panel" style="width:600px;">
|
|
99
|
+
</h1>
|
|
128
100
|
|
|
129
|
-
|
|
101
|
+
5. View the latest test report: http://localhost:5984/_utils
|
|
130
102
|
|
|
131
|
-
|
|
132
|
-
<img src="https://everypinio.github.io/hardpy/img/hardpy_operator_panel_hello_hardpy.png"
|
|
133
|
-
alt="hardpy operator panel" style="width:600px;">
|
|
134
|
-
</h1>
|
|
103
|
+
Login and password: **dev**, database - **runstore**, document - **current**.
|
|
135
104
|
|
|
136
|
-
|
|
105
|
+
<h1 align="center">
|
|
106
|
+
<img src="https://everypinio.github.io/hardpy/img/runstore_hello_hardpy.png"
|
|
107
|
+
alt="hardpy runstore" style="width:500px;">
|
|
108
|
+
</h1>
|
|
137
109
|
|
|
138
|
-
|
|
139
|
-
You can view the CouchDB instance through Fauxton web interface: http://localhost:5984/_utils
|
|
110
|
+
## Examples
|
|
140
111
|
|
|
141
|
-
|
|
142
|
-
<img src="https://everypinio.github.io/hardpy/img/runstore_hello_hardpy.png"
|
|
143
|
-
alt="hardpy runstore" style="width:600px;">
|
|
144
|
-
</h1>
|
|
112
|
+
Find more examples of using the **HardPy** in the [examples](https://github.com/everypinio/hardpy/tree/main/examples) folder.
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
hardpy/__init__.py,sha256=
|
|
1
|
+
hardpy/__init__.py,sha256=1GtlRzkpmNVjZ6LcNYFVmEtgFCR3T6gLSLBLrZA9Nog,1692
|
|
2
|
+
hardpy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
hardpy/cli/cli.py,sha256=Z0KGzZplCaHfyttKjMIqnE5upaca-H1XyiaZ2fUCHvM,4504
|
|
4
|
+
hardpy/cli/template.py,sha256=IgroGdzkKUn5BExDYtzw9djr1Ryvj39wRUF-VlKCToE,6461
|
|
5
|
+
hardpy/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
hardpy/common/config.py,sha256=rkvbFXFxoqBkYsEbCcnWX5d6G9hzS9Mr4mgQoSMbY6U,4497
|
|
2
7
|
hardpy/hardpy_panel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
hardpy/hardpy_panel/api.py,sha256=
|
|
4
|
-
hardpy/hardpy_panel/
|
|
5
|
-
hardpy/hardpy_panel/frontend/dist/asset-manifest.json,sha256=WKgjuP2ksuEcMXfMu-965znPimRRRa9gNuzhU16L4kg,2824
|
|
8
|
+
hardpy/hardpy_panel/api.py,sha256=ew_3cTMW5XzS_EtHkH41z8ckOcJ_a5_zi3-AE8OKtEI,2969
|
|
9
|
+
hardpy/hardpy_panel/frontend/dist/asset-manifest.json,sha256=BnMkNkch6nsMmxLzKmOB3ne_jq-d5ksz2AS_M25r-jA,2824
|
|
6
10
|
hardpy/hardpy_panel/frontend/dist/favicon.ico,sha256=sgIk5PKUKEKBDpkSrc8dJgjpObp0iF82Mec0GpfKId4,15406
|
|
7
|
-
hardpy/hardpy_panel/frontend/dist/index.html,sha256=
|
|
11
|
+
hardpy/hardpy_panel/frontend/dist/index.html,sha256=6Ea-Fn6tO3DbWeeYbMp4HYix1SILrdny4OKnk2odti8,656
|
|
8
12
|
hardpy/hardpy_panel/frontend/dist/logo512.png,sha256=-fIMbqX7PYUpheK4kX1C1erRTe_hHZwFQYDLrAbhFRU,34188
|
|
9
13
|
hardpy/hardpy_panel/frontend/dist/manifest.json,sha256=PfmJlN2JMJtHS6OnhU4b4X5wPQC_yRBdjesjoirObSA,502
|
|
10
14
|
hardpy/hardpy_panel/frontend/dist/static/css/main.e8a862f1.css,sha256=gNl6kGMBhtswNrUU6X2S6uosRU7xhxqI_p9gsEtBUqE,318244
|
|
@@ -21,9 +25,9 @@ hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-all-paths.f63155c9.c
|
|
|
21
25
|
hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-all-paths.f63155c9.chunk.js.map,sha256=p1xKHRK4AZutkZsQHiWSNU61tYp7I3iUuyLLm3eqkHQ,2833
|
|
22
26
|
hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-split-paths-by-size-loader.52a072d3.chunk.js,sha256=Jl5xm_jQ9IXKhCagHHvnIhwYXb379Q5FFBiqPoKdUIE,605
|
|
23
27
|
hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-split-paths-by-size-loader.52a072d3.chunk.js.map,sha256=amJiG2QaJMRR9Y2M0C2soOqd75xdQHhsVKjwrDSIIT0,2224
|
|
24
|
-
hardpy/hardpy_panel/frontend/dist/static/js/main.
|
|
25
|
-
hardpy/hardpy_panel/frontend/dist/static/js/main.
|
|
26
|
-
hardpy/hardpy_panel/frontend/dist/static/js/main.
|
|
28
|
+
hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js,sha256=e6kjJZEVUdfYrF2TE7_jXWmRkxv555N6ARVR5OSNquA,1062573
|
|
29
|
+
hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js.LICENSE.txt,sha256=ForPNukClWMEP3pF9LMYoU-ve-LsyCH-rYU8eLki_FY,2315
|
|
30
|
+
hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js.map,sha256=VpaF9MC2wZxpMZf-a7PgfXikuXzwK4nL3qKmknf-yn4,5306007
|
|
27
31
|
hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-16.520846c6beb41df528c8.eot,sha256=PTCTrQYNHX2hIPUaYWtOKrI30-iQGXt_EGxq6JCXie0,117628
|
|
28
32
|
hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-16.5c52b39c697f2323ce8b.svg,sha256=lDCQy06aS-9bmhwuFOUs-EdcR8MP2wqwAwky5oamtkQ,509417
|
|
29
33
|
hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-16.84db1772f4bfb529f64f.woff,sha256=edyqQN0nw4dNBs1pgr7pQB7nJhhR6T_YfklFcG_fHj0,53344
|
|
@@ -36,37 +40,37 @@ hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-20.afbadb627d43b7
|
|
|
36
40
|
hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-20.e857f5a5132b8bfa71a1.woff,sha256=mQZTxE1PyyAL16VWuASOvXlZFwuI4aCPvbrhfgpdIdU,55356
|
|
37
41
|
hardpy/hardpy_panel/frontend/dist/static/media/logo_smol.5b16f92447a4a9e80331.png,sha256=E4K7drvhJCg9HcTpRihOXZhVJVBZ7-W97Se-3tDb46o,14485
|
|
38
42
|
hardpy/pytest_hardpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
hardpy/pytest_hardpy/plugin.py,sha256=
|
|
40
|
-
hardpy/pytest_hardpy/pytest_call.py,sha256=
|
|
41
|
-
hardpy/pytest_hardpy/pytest_wrapper.py,sha256=
|
|
43
|
+
hardpy/pytest_hardpy/plugin.py,sha256=5DF29vbTPQ-nohiDDYay6Ml6GUHFnxZZDZHtKSFAOZE,14044
|
|
44
|
+
hardpy/pytest_hardpy/pytest_call.py,sha256=yXhp40ccOyeN0AJygenjQQ6fQKS2B85eW4-wZP2OgIQ,10184
|
|
45
|
+
hardpy/pytest_hardpy/pytest_wrapper.py,sha256=p11L4d1VIDmgeG8ltRQrmBRXqK1HRqBCQo63Qia_0SQ,4495
|
|
42
46
|
hardpy/pytest_hardpy/db/__init__.py,sha256=MxDufncz0zgRAxrndvPXXW4NrU7rRP7MzIrR7S5Cwwo,558
|
|
43
|
-
hardpy/pytest_hardpy/db/base_connector.py,sha256=
|
|
44
|
-
hardpy/pytest_hardpy/db/base_server.py,sha256=
|
|
45
|
-
hardpy/pytest_hardpy/db/base_store.py,sha256=
|
|
46
|
-
hardpy/pytest_hardpy/db/const.py,sha256=
|
|
47
|
+
hardpy/pytest_hardpy/db/base_connector.py,sha256=cmNV4Y6jFij8Fpp_74W0nqdBFa3J9c9in7MDeNJ4ZL0,1046
|
|
48
|
+
hardpy/pytest_hardpy/db/base_server.py,sha256=zZbek5jNjtXRVxOhFLWvmKrtOZsbQwrsW0pcql2gpUg,396
|
|
49
|
+
hardpy/pytest_hardpy/db/base_store.py,sha256=WkgBvvY4pEYp83jP3HxxSfmLztoMzAXh199J_mOQcX8,2900
|
|
50
|
+
hardpy/pytest_hardpy/db/const.py,sha256=7jmJOZA-V-Jjf8vyFqTuyqrKueiPDUO60jNj2z5jKsQ,738
|
|
47
51
|
hardpy/pytest_hardpy/db/runstore.py,sha256=50amoTIO7OTqd5Ks1_7uTzqjCldLpTapkxbIQOgj1sQ,1023
|
|
48
|
-
hardpy/pytest_hardpy/db/schema.py,sha256=
|
|
49
|
-
hardpy/pytest_hardpy/db/statestore.py,sha256=
|
|
52
|
+
hardpy/pytest_hardpy/db/schema.py,sha256=dDwVlXT1Jt_A-ZtjjbZG_QR6AeqTdHT79eLEIjkZIxU,8262
|
|
53
|
+
hardpy/pytest_hardpy/db/statestore.py,sha256=IBgPXQ0aAtaAOVW2Q-U9Pv0GqYY8o340K30EvDRdsAI,1025
|
|
50
54
|
hardpy/pytest_hardpy/reporter/__init__.py,sha256=RONapygH3c_FyXokAlyCVJXGV2cV_jCYDxLymvvA1uE,322
|
|
51
|
-
hardpy/pytest_hardpy/reporter/base.py,sha256=
|
|
52
|
-
hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=
|
|
55
|
+
hardpy/pytest_hardpy/reporter/base.py,sha256=mnu_1exZ7IHj5SvhsAeRdZoZPe9uZFQoTt-Bg0wsO5s,1933
|
|
56
|
+
hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=WE7Z5KP-9VapexIev6Igd-H9Vxp_bjWxyug6fgbpJgA,10255
|
|
53
57
|
hardpy/pytest_hardpy/reporter/runner_reporter.py,sha256=NXkBIoERqmLI-GYtHavmOWC5t6NIpcAE-NECrUKIAJs,827
|
|
54
58
|
hardpy/pytest_hardpy/result/__init__.py,sha256=NMeCGx3yh8ds9VpaUpuNFDxbwgYFq3e-o7W6rYIv8uI,346
|
|
55
59
|
hardpy/pytest_hardpy/result/couchdb_config.py,sha256=kttsrWzv9D99R3ms-hFbzVbrZ78B2me6rrJgncfs5jk,3129
|
|
56
60
|
hardpy/pytest_hardpy/result/report_loader/__init__.py,sha256=FuHuD6IFZyaKj0yu5urhf6nkxGbiPONJ-WHnJ2jHwyc,251
|
|
57
|
-
hardpy/pytest_hardpy/result/report_loader/couchdb_loader.py,sha256=
|
|
61
|
+
hardpy/pytest_hardpy/result/report_loader/couchdb_loader.py,sha256=Wwo_JBoPpwh72iHFaq5ZqHZw-_tWsXyalqje1jzYlfY,2247
|
|
58
62
|
hardpy/pytest_hardpy/result/report_reader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
|
-
hardpy/pytest_hardpy/result/report_reader/couchdb_reader.py,sha256=
|
|
60
|
-
hardpy/pytest_hardpy/utils/__init__.py,sha256=
|
|
61
|
-
hardpy/pytest_hardpy/utils/
|
|
62
|
-
hardpy/pytest_hardpy/utils/const.py,sha256=
|
|
63
|
-
hardpy/pytest_hardpy/utils/dialog_box.py,sha256=
|
|
64
|
-
hardpy/pytest_hardpy/utils/exception.py,sha256=
|
|
65
|
-
hardpy/pytest_hardpy/utils/node_info.py,sha256=
|
|
66
|
-
hardpy/pytest_hardpy/utils/progress_calculator.py,sha256=
|
|
67
|
-
hardpy/pytest_hardpy/utils/singleton.py,sha256=
|
|
68
|
-
hardpy-0.
|
|
69
|
-
hardpy-0.
|
|
70
|
-
hardpy-0.
|
|
71
|
-
hardpy-0.
|
|
72
|
-
hardpy-0.
|
|
63
|
+
hardpy/pytest_hardpy/result/report_reader/couchdb_reader.py,sha256=Ns82mzerDa4HipX6Xea1uGkXmhf8UotX6KsiChD1ViM,5618
|
|
64
|
+
hardpy/pytest_hardpy/utils/__init__.py,sha256=R2a5la6zEQdEeeL-W-OWpAFFzXHswu8a_nAw3C53y38,1295
|
|
65
|
+
hardpy/pytest_hardpy/utils/connection_data.py,sha256=GTKXzl9MXt1XkwEPi6NxdWUghRmZOWBV8nfgnbRh50s,541
|
|
66
|
+
hardpy/pytest_hardpy/utils/const.py,sha256=SsqRisrq9OlCb9cK5sEjFW_bZ9V2Qw61P9iYObIj5Fg,423
|
|
67
|
+
hardpy/pytest_hardpy/utils/dialog_box.py,sha256=lY_q_SGRdWtza4paHrsMfKTCsSkN_V8WIH7V7r_PNdo,8187
|
|
68
|
+
hardpy/pytest_hardpy/utils/exception.py,sha256=BlkVea4wwHJeXcU1rpUqH9IbMBFQYHghOXhHWSvDz8Q,1156
|
|
69
|
+
hardpy/pytest_hardpy/utils/node_info.py,sha256=qBzNCv-0YwIcLxES3kIvOLSblaJ3ICrtKl-tdF2Ndnk,3149
|
|
70
|
+
hardpy/pytest_hardpy/utils/progress_calculator.py,sha256=L6jJgkO1uxx5U2KKmQfTsGwgX5Atrqka5KV7uiMcou8,1033
|
|
71
|
+
hardpy/pytest_hardpy/utils/singleton.py,sha256=vP1BMzLkQF0j7t7crijPj6uyAowfviihJeXDJvhTDxU,606
|
|
72
|
+
hardpy-0.6.1.dist-info/METADATA,sha256=HtkFMKxgEnDfNOSz8C-CQcyGYAyF_kmF2fAJM7MfcVI,3586
|
|
73
|
+
hardpy-0.6.1.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
|
|
74
|
+
hardpy-0.6.1.dist-info/entry_points.txt,sha256=nL2sMkKMScNaOE0IPkYnu9Yr-BUswZvGSrwY-SxHY3E,102
|
|
75
|
+
hardpy-0.6.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
76
|
+
hardpy-0.6.1.dist-info/RECORD,,
|