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

testit-tms / adapters-python / 22071855248

16 Feb 2026 05:15PM UTC coverage: 0.0% (-41.2%) from 41.236%
22071855248

Pull #234

github

web-flow
Merge a88493a08 into 44a4e9f3f
Pull Request #234: feat: TMS-37545: replace labels with tags when collecting autotest me…

0 of 7 new or added lines in 1 file covered. (0.0%)

0 of 350 relevant lines covered (0.0%)

0.0 hits per line

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

0.0
/testit-adapter-robotframework/src/testit_adapter_robotframework/models.py
1
import ast
×
2
import re
×
3

4
from attr import Factory, asdict, attrib, s
×
5

6
from robot.api import logger
×
7
from testit_python_commons.models.link import Link
×
8

9
from .utils import get_hash
×
10

11

12
LinkTypes = ['Related', 'BlockedBy', 'Defect', 'Issue', 'Requirement', 'Repository']
×
13

14

15
def link_type_check(self, attribute, value):
×
16
    if value.title() not in LinkTypes:
×
17
        raise ValueError(f"Incorrect Link type: {value}")
×
18

19

20
def url_check(self, attribute, value):
×
21
    if not bool(re.match(
×
22
            r"(https?|ftp)://"
23
            r"(\w+(-\w+)*\.)?"
24
            r"((\w+(-\w+)*)\.(\w+))"
25
            r"(\.\w+)*"
26
            r"([\w\-._~/]*)*(?<!\.)",
27
            value)):
28
        raise ValueError(f"Incorrect URL: {value}")
×
29

30

31
class Default:
×
32

33
    def order(self):
×
34
        return asdict(self)
×
35

36

37
@s
×
38
class StepResult(Default):
×
39
    title = attrib(default='')
×
40
    description = attrib(default='')
×
41
    started_on = attrib(default=None)
×
42
    completed_on = attrib(default=None)
×
43
    duration = attrib(default=None)
×
44
    outcome = attrib(default=None)
×
45
    step_results = attrib(default=Factory(list))
×
46
    attachments = attrib(default=Factory(list))
×
47
    parameters = attrib(default=Factory(dict))
×
48

49

50
@s
×
51
class Step(Default):
×
52
    title = attrib()
×
53
    description = attrib()
×
54
    steps = attrib(default=Factory(list))
×
55

56

57
@s
×
58
class Label:
×
59
    name = attrib()
×
60

61

62
@s(kw_only=True)
×
63
class Autotest(Default):
×
64
    externalID = attrib(default=None)  # noqa: N815
×
65
    autoTestName = attrib()  # noqa: N815
×
66
    steps = attrib(default=Factory(list))
×
67
    stepResults = attrib(default=Factory(list))  # noqa: N815
×
68
    setUp = attrib(default=Factory(list))  # noqa: N815
×
69
    setUpResults = attrib(default=Factory(list))  # noqa: N815
×
70
    tearDown = attrib(default=Factory(list))  # noqa: N815
×
71
    tearDownResults = attrib(default=Factory(list))  # noqa: N815
×
72
    resultLinks = attrib(default=Factory(list))  # noqa: N815
×
73
    duration = attrib(default=None)
×
74
    failureReasonNames = attrib(default=Factory(list))  # noqa: N815
×
75
    traces = attrib(default=None)
×
76
    outcome = attrib(default=None)
×
77
    namespace = attrib(default=None)
×
78
    attachments = attrib(default=Factory(list))
×
79
    parameters = attrib(default=Factory(dict))
×
80
    properties = attrib(default=Factory(dict))
×
81
    classname = attrib(default=None)
×
82
    title = attrib(default=None)
×
83
    description = attrib(default=None)
×
84
    links = attrib(default=Factory(list))
×
85
    labels = attrib(default=Factory(list))
×
NEW
86
    tags = attrib(default=Factory(list))
×
87
    workItemsID = attrib(default=Factory(list))  # noqa: N815
×
88
    message = attrib(default="")
×
89
    started_on = attrib(default=None)
×
90
    completed_on = attrib(default=None)
×
91
    externalKey = attrib(default=None)
×
92

93
    step_depth = attrib(default=Factory(list))
×
94
    result_depth = attrib(default=Factory(list))
×
95

96
    def add_attributes(self, attrs):
×
97
        self.title = attrs['originalname']
×
98
        self.autoTestName = attrs['originalname']
×
99
        self.externalKey = attrs['originalname']
×
100
        self.description = attrs['doc']
×
101
        self.template = attrs['template']
×
102
        self.classname = attrs['longname'].split('.')[-2]
×
103
        for tag in attrs['tags']:
×
104
            if tag.lower().startswith('testit.'):
×
105
                attr = re.findall(r'(?<=\.).*?(?=:)', tag)[0].strip().lower()
×
106
                value = tag.split(':', 1)[-1].strip()
×
107
                if attr == 'externalid':
×
108
                    self.externalID = str(value).replace("'", "").replace('"', '')
×
109
                elif attr == 'displayname':
×
110
                    self.autoTestName = str(value).replace("'", "").replace('"', '')
×
111
                elif attr == 'title':
×
112
                    self.title = str(value).replace("'", "").replace('"', '')
×
113
                elif attr == 'description':
×
114
                    self.description = str(value).replace("'", "").replace('"', '')
×
115
                elif attr == 'workitemsid' or attr == 'workitemsids':
×
116
                    value = ast.literal_eval(value)
×
117
                    if isinstance(value, (str, int)):
×
118
                        self.workItemsID.append(str(value))
×
119
                    elif isinstance(value, list):
×
120
                        self.workItemsID.extend([str(i) for i in value])
×
121
                    else:
122
                        logger.error(f"[TestIt] Wrong workitem format: {value}")
×
123
                elif attr == 'links':
×
124
                    value = ast.literal_eval(value)
×
125
                    try:
×
126
                        if isinstance(value, dict):
×
127
                            self.links.append(Link()\
×
128
                                .set_url(value['url'])\
129
                                .set_title(value.get('title', None))\
130
                                .set_link_type(value.get('type', None))\
131
                                .set_description(value.get('description', None)))
132
                        elif isinstance(value, list):
×
133
                            self.links.extend([Link()\
×
134
                                .set_url(link['url'])\
135
                                .set_title(link.get('title', None))\
136
                                .set_link_type(link.get('type', None))\
137
                                .set_description(link.get('description', None)) for link in value if isinstance(link, dict)])
138
                    except ValueError as e:
×
139
                        logger.error(f"[TestIt] Link Error: {e}")
×
140
                elif attr == 'labels':
×
141
                    value = ast.literal_eval(value)
×
142
                    if isinstance(value, (str, int)):
×
143
                        self.labels.append(Label(value))
×
144
                    elif isinstance(value, list):
×
145
                        self.labels.extend([Label(item) for item in value if isinstance(item, (str, int))])
×
NEW
146
                elif attr == 'tags':
×
NEW
147
                    value = ast.literal_eval(value)
×
NEW
148
                    if isinstance(value, (str, int)):
×
NEW
149
                        self.tags.append(str(value))
×
NEW
150
                    elif isinstance(value, list):
×
NEW
151
                        self.tags.extend([str(item) for item in value if isinstance(item, (str, int))])
×
152
                elif attr == 'namespace':
×
153
                    self.namespace = str(value).replace("'", "").replace('"', '')
×
154
                elif attr == 'classname':
×
155
                    self.classname = str(value).replace("'", "").replace('"', '')
×
156
                else:
157
                    logger.error(f"[TestIt] Unknown attribute: {attr}")
×
158
        if not self.externalID:
×
159
            self.externalID = get_hash(attrs['longname'])
×
160

161
    def add_step(self, step_type, title, description, parameters):
×
162
        if len(self.step_depth) == 0:
×
163
            if step_type.lower() == 'setup':
×
164
                self.setUp.append(Step(title, description))
×
165
                self.step_depth.append(self.setUp[-1])
×
166
                self.setUpResults.append(StepResult(title, description, parameters=parameters))
×
167
                self.result_depth.append(self.setUpResults[-1])
×
168
            elif step_type.lower() == 'teardown':
×
169
                self.tearDown.append(Step(title, description))
×
170
                self.step_depth.append(self.tearDown[-1])
×
171
                self.tearDownResults.append(StepResult(title, description, parameters=parameters))
×
172
                self.result_depth.append(self.tearDownResults[-1])
×
173
            else:
174
                self.steps.append(Step(title, description))
×
175
                self.step_depth.append(self.steps[-1])
×
176
                self.stepResults.append(StepResult(title, description, parameters=parameters))
×
177
                self.result_depth.append(self.stepResults[-1])
×
178
        elif 1 <= len(self.step_depth) < 14:
×
179
            self.step_depth[-1].steps.append(Step(title, description))
×
180
            self.step_depth.append(self.step_depth[-1].steps[-1])
×
181
            self.result_depth[-1].step_results.append(StepResult(title, description, parameters=parameters))
×
182
            self.result_depth.append(self.result_depth[-1].step_results[-1])
×
183

184
    def add_step_result(self, title, start, complete, duration, outcome, attachments):
×
185
        if self.result_depth:
×
186
            if self.result_depth[-1].title == title:
×
187
                step = self.result_depth.pop()
×
188
                step.started_on = start
×
189
                step.completed_on = complete
×
190
                step.duration = duration
×
191
                step.outcome = outcome
×
192
                step.attachments = attachments
×
193
        if self.step_depth:
×
194
            if self.step_depth[-1].title == title:
×
195
                self.step_depth.pop()
×
196

197

198
class Option:
×
199

200
    def __init__(self, **kwargs):
×
201
        if kwargs.get('tmsUrl', None):
×
202
            self.set_url = kwargs.get('tmsUrl', None)
×
203
        if kwargs.get('tmsPrivateToken', None):
×
204
            self.set_private_token = kwargs.get('tmsPrivateToken', None)
×
205
        if kwargs.get('tmsProjectId', None):
×
206
            self.set_project_id = kwargs.get('tmsProjectId', None)
×
207
        if kwargs.get('tmsConfigurationId', None):
×
208
            self.set_configuration_id = kwargs.get('tmsConfigurationId', None)
×
209
        if kwargs.get('tmsTestRunId', None):
×
210
            self.set_test_run_id = kwargs.get('tmsTestRunId', None)
×
211
        if kwargs.get('tmsProxy', None):
×
212
            self.set_tms_proxy = kwargs.get('tmsProxy', None)
×
213
        if kwargs.get('tmsTestRunName', None):
×
214
            self.set_test_run_name = kwargs.get('tmsTestRunName', None)
×
215
        if kwargs.get('tmsAdapterMode', None):
×
216
            self.set_adapter_mode = kwargs.get('tmsAdapterMode', None)
×
217
        if kwargs.get('tmsConfigFile', None):
×
218
            self.set_config_file = kwargs.get('tmsConfigFile', None)
×
219
        if kwargs.get('tmsCertValidation', None):
×
220
            self.set_cert_validation = kwargs.get('tmsCertValidation', None)
×
221
        if kwargs.get('tmsAutomaticCreationTestCases', None):
×
222
            self.set_automatic_creation_test_cases = kwargs.get('tmsAutomaticCreationTestCases', None)
×
223
        if kwargs.get('tmsAutomaticUpdationLinksToTestCases', None):
×
224
            self.set_automatic_updation_links_to_test_cases = kwargs.get('tmsAutomaticUpdationLinksToTestCases', None)
×
225
        if kwargs.get('tmsImportRealtime', None):
×
226
            self.set_import_realtime = kwargs.get('tmsImportRealtime', None)
×
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