• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

testit-tms / adapters-python / 24745776944

21 Apr 2026 08:51PM UTC coverage: 24.109% (+0.08%) from 24.029%
24745776944

Pull #261

github

web-flow
Merge d32910c72 into 611a25726
Pull Request #261: fix: pytest run without testit flag - no actions

3 of 8 new or added lines in 1 file covered. (37.5%)

1 existing line in 1 file now uncovered.

399 of 1655 relevant lines covered (24.11%)

0.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.55
/testit-adapter-pytest/src/testit_adapter_pytest/plugin.py
1
import re
×
2
import json
×
3
from urllib.parse import urlparse
×
4
import pytest
×
5

6
from testit_adapter_pytest.listener import TmsListener
×
7
from testit_python_commons.services import TmsPluginManager
×
8

9

10
def _adapter_mode_type(value):
×
11
    if value is None:
2✔
12
        raise ValueError("Adapter mode cannot be None! Valid modes: 0, 1, 2")
2✔
13
    valid_modes = ['0', '1', '2']
2✔
14
    if value not in valid_modes:
2✔
15
        raise ValueError(f"Unknown adapter mode '{value}'! Valid modes: {', '.join(valid_modes)}")
2✔
16
    return value
2✔
17

18

19
def _boolean_type(value):
×
20
    if value is None:
2✔
21
        raise ValueError("Boolean value cannot be None! Must be 'true' or 'false'")
2✔
22
    valid_values = ['true', 'false']
2✔
23
    if value.lower() not in valid_values:
2✔
24
        raise ValueError(f"Invalid value '{value}'! Must be 'true' or 'false'")
2✔
25
    return value.lower()
2✔
26

27

28
def _uuid_type(value):
×
29
    if value is None:
2✔
30
        raise ValueError("UUID cannot be None!")
2✔
31
    uuid_pattern = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', re.I)
2✔
32
    if not uuid_pattern.match(value):
2✔
33
        raise ValueError(f"Invalid UUID format: '{value}'!")
2✔
34
    return value
2✔
35

36

37
def _url_type(value):
×
38
    if value is None:
2✔
39
        raise ValueError("URL cannot be None!")
2✔
40
    if not value.startswith(('http://', 'https://')):
2✔
41
        raise ValueError(f"Invalid URL format: '{value}'!")
2✔
42
    url = urlparse(value)
2✔
43
    if not all([url.scheme, url.netloc]):
2✔
44
        raise ValueError(f"Invalid URL format: '{value}'!")
2✔
45
    return value
2✔
46

47

48
def _proxy_type(value):
×
49
    if value is None:
2✔
50
        raise ValueError("Proxy cannot be None!")
2✔
51
    try:
2✔
52
        proxy_dict = json.loads(value)
2✔
53
        if not isinstance(proxy_dict, dict):
2✔
54
            raise ValueError(f"Proxy must be a JSON object, got {type(proxy_dict).__name__}")
2✔
55
        
56
        valid_keys = {'http', 'https'}
2✔
57
        for key in proxy_dict.keys():
2✔
58
            if key not in valid_keys:
2✔
59
                raise ValueError(f"Invalid proxy key '{key}'! Must be 'http' or 'https'")
2✔
60
        
61
        for key, url in proxy_dict.items():
2✔
62
            if not isinstance(url, str):
2✔
63
                raise ValueError(f"Proxy URL for '{key}' must be string, got {type(url).__name__}")
2✔
64
            if not url.startswith(('http://', 'https://')):
2✔
65
                raise ValueError(f"Invalid {key} proxy URL: '{url}'! Must start with http:// or https://")
2✔
66
            parsed = urlparse(url)
2✔
67
            if not parsed.netloc:
2✔
68
                raise ValueError(f"Invalid {key} proxy URL: '{url}'! Missing hostname")
2✔
69
        
70
        return value
2✔
71
    except json.JSONDecodeError:
2✔
72
        raise ValueError(f"Invalid JSON format for proxy: '{value}'!")
2✔
73
    except ValueError as e:
2✔
74
        raise ValueError(str(e))
2✔
75

76
def pytest_addoption(parser):
×
77
    parser.getgroup('testit').addoption(
2✔
78
        '--testit',
79
        action='store_true',
80
        dest="tms_report",
81
        help='Pytest plugin for Test IT'
82
    )
83
    parser.getgroup('testit').addoption(
2✔
84
        '--tmsUrl',
85
        action="store",
86
        dest="set_url",
87
        type=_url_type,
88
        metavar="https://demo.testit.software",
89
        help='Set location of the TMS instance'
90
    )
91
    parser.getgroup('testit').addoption(
2✔
92
        '--tmsPrivateToken',
93
        action="store",
94
        dest="set_private_token",
95
        metavar="T2lKd2pLZGI4WHRhaVZUejNl",
96
        help='Set API secret key'
97
    )
98
    parser.getgroup('testit').addoption(
2✔
99
        '--tmsProjectId',
100
        action="store",
101
        dest="set_project_id",
102
        type=_uuid_type,
103
        metavar="15dbb164-c1aa-4cbf-830c-8c01ae14f4fb",
104
        help='Set project ID'
105
    )
106
    parser.getgroup('testit').addoption(
2✔
107
        '--tmsConfigurationId',
108
        action="store",
109
        dest="set_configuration_id",
110
        type=_uuid_type,
111
        metavar="d354bdac-75dc-4e3d-84d4-71186c0dddfc",
112
        help='Set configuration ID'
113
    )
114
    parser.getgroup('testit').addoption(
2✔
115
        '--tmsTestRunId',
116
        action="store",
117
        dest="set_test_run_id",
118
        type=_uuid_type,
119
        metavar="5236eb3f-7c05-46f9-a609-dc0278896464",
120
        help='Set test run ID (optional)'
121
    )
122
    parser.getgroup('debug').addoption(
2✔
123
        '--tmsProxy',
124
        action="store",
125
        dest="set_tms_proxy",
126
        type=_proxy_type,
127
        metavar='{"http":"http://localhost:8888","https":"http://localhost:8888"}',
128
        help='Set proxy for sending requests (optional)'
129
    )
130
    parser.getgroup('testit').addoption(
2✔
131
        '--tmsTestRunName',
132
        action="store",
133
        dest="set_test_run_name",
134
        metavar="Custom name of test run",
135
        help='Set custom name of test run (optional)'
136
    )
137
    parser.getgroup('testit').addoption(
2✔
138
        '--tmsAdapterMode',
139
        action="store",
140
        type=_adapter_mode_type,
141
        dest="set_adapter_mode",
142
        metavar="1",
143
        help="""
144
        Set adapter mode with test run (optional):
145
        0 - with filtering autotests by launch\'s suite in TMS (Default)
146
        1 - without filtering autotests by launch\'s suite in TMS
147
        2 - create new test run in TMS
148
        """
149
    )
150
    parser.getgroup('testit').addoption(
2✔
151
        '--tmsConfigFile',
152
        action="store",
153
        dest="set_config_file",
154
        metavar="tmsConfigFile",
155
        help='Set custom name of configuration file'
156
    )
157
    parser.getgroup('testit').addoption(
2✔
158
        '--tmsCertValidation',
159
        action="store",
160
        dest="set_cert_validation",
161
        type=_boolean_type,
162
        metavar="false",
163
        help='Set certificate validation (true/false)'
164
    )
165
    parser.getgroup('testit').addoption(
2✔
166
        '--tmsAutomaticCreationTestCases',
167
        action="store",
168
        dest="set_automatic_creation_test_cases",
169
        type=_boolean_type,
170
        metavar="false",
171
        help="""
172
        Set mode of automatic creation test cases (optional):
173
        true - create a test case linked to the created autotest (not to the updated autotest)
174
        false - not create a test case (Default)
175
        """
176
    )
177
    parser.getgroup('testit').addoption(
2✔
178
        '--tmsAutomaticUpdationLinksToTestCases',
179
        action="store",
180
        dest="set_automatic_updation_links_to_test_cases",
181
        type=_boolean_type,
182
        metavar="false",
183
        help="""
184
        Set mode of automatic updation links to test cases (optional):
185
        true - update links to test cases
186
        false - not update links to test cases (Default)
187
        """
188
    )
189
    parser.getgroup('testit').addoption(
2✔
190
        '--tmsImportRealtime',
191
        action="store",
192
        dest="set_import_realtime",
193
        type=_boolean_type,
194
        metavar="false",
195
        help="""
196
        Set mode of import type selection when launching autotests (optional):
197
        true - the adapter will create/update each autotest in real time (Default)
198
        false - the adapter will create/update multiple autotests
199
        """
200
    )
201

202

NEW
203
@pytest.hookimpl(tryfirst=True)
×
NEW
204
def pytest_load_initial_conftests(early_config, parser, args):
×
205
    ns = getattr(early_config, "known_args_namespace", None)
2✔
206
    if ns is not None and hasattr(ns, "tms_report"):
2✔
207
        TmsPluginManager.set_pytest_tms_report(ns.tms_report)
2✔
208

209

NEW
210
def pytest_unconfigure(config):
×
NEW
211
    TmsPluginManager.set_pytest_tms_report(None)
×
212

213

NEW
214
@pytest.hookimpl(tryfirst=True)
×
UNCOV
215
def pytest_cmdline_main(config):
×
216
    if config.option.tms_report:
2✔
217
        listener = TmsListener(
2✔
218
            TmsPluginManager.get_adapter_manager(config.option),
219
            TmsPluginManager.get_step_manager(),
220
            TmsPluginManager.get_fixture_manager())
221

222
        config.pluginmanager.register(listener)
2✔
223
        TmsPluginManager.get_plugin_manager().register(listener)
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc