Skip to content
This repository was archived by the owner on Apr 22, 2020. It is now read-only.

Commit 65f70ff

Browse files
apallierallankp
authored andcommitted
Add duration in result (allankp#32)
* Manage existing test run or test plan * Fill the test failure comment and duration with information from test runner * Log only last error content * Add log * Add log * Fix: In case of 'parametrize', the test status reflects the last test performed (should reflect all the tests status) Now, worst results are published at the end (sort by status) * Manage existing testrun testplan (allankp#3) Synchronization with upstream * Merge branch 'fill-comment-in-test-result' * Synchro with upstream * Merge upstream * Fix problem with Tox/Python versions * Fix problem with Python 2.7
1 parent 3044e2d commit 65f70ff

File tree

3 files changed

+141
-72
lines changed

3 files changed

+141
-72
lines changed

pytest_testrail/plugin.py

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# -*- coding: UTF-8 -*-
22
from datetime import datetime
3+
from operator import itemgetter
4+
35
import pytest
46
import re
57
import warnings
@@ -20,6 +22,8 @@
2022
GET_TESTRUN_URL = 'get_run/{}'
2123
GET_TESTPLAN_URL = 'get_plan/{}'
2224

25+
COMMENT_SIZE_LIMIT = 4000
26+
2327

2428
class DeprecatedTestDecorator(DeprecationWarning):
2529
pass
@@ -150,44 +154,52 @@ def pytest_runtest_makereport(self, item, call):
150154
""" Collect result and associated testcases (TestRail) of an execution """
151155
outcome = yield
152156
rep = outcome.get_result()
153-
comment = ""
154-
if call.excinfo:
155-
comment = str(item.repr_failure(call.excinfo))
156157
if item.get_marker(TESTRAIL_PREFIX):
157158
testcaseids = item.get_marker(TESTRAIL_PREFIX).kwargs.get('ids')
158159

159160
if rep.when == 'call' and testcaseids:
160161
self.add_result(
161162
clean_test_ids(testcaseids),
162163
get_test_outcome(outcome.result.outcome),
163-
comment)
164+
comment=rep.longrepr,
165+
duration=rep.duration
166+
)
164167

165168
def pytest_sessionfinish(self, session, exitstatus):
166169
""" Publish results in TestRail """
170+
print('[{}] Start publishing'.format(TESTRAIL_PREFIX))
167171
if self.results:
172+
tests_list = [str(result['case_id']) for result in self.results]
173+
print('[{}] Testcases to publish: {}'.format(TESTRAIL_PREFIX, ', '.join(tests_list)))
168174

169175
if self.testrun_id:
170176
self.add_results(self.testrun_id)
171177
elif self.testplan_id:
172-
for testrun_id in self.get_available_testruns(self.testplan_id):
178+
testruns = self.get_available_testruns(self.testplan_id)
179+
print('[{}] Testruns to update: {}'.format(TESTRAIL_PREFIX, ', '.join([str(elt) for elt in testruns])))
180+
for testrun_id in testruns:
173181
self.add_results(testrun_id)
174182
else:
175-
print('No data published')
183+
print('[{}] No data published'.format(TESTRAIL_PREFIX))
184+
print('[{}] End publishing'.format(TESTRAIL_PREFIX))
176185

177186
# plugin
178187

179-
def add_result(self, test_ids, status, comment):
188+
def add_result(self, test_ids, status, comment='', duration=0):
180189
"""
181190
Add a new result to results dict to be submitted at the end.
182191
183192
:param list test_ids: list of test_ids.
184193
:param int status: status code of test (pass or fail).
194+
:param comment: None or a failure representation.
195+
:param duration: Time it took to run just the test.
185196
"""
186197
for test_id in test_ids:
187198
data = {
188199
'case_id': test_id,
189-
'comment': comment,
190200
'status_id': status,
201+
'comment': comment,
202+
'duration': duration
191203
}
192204
self.results.append(data)
193205

@@ -198,18 +210,35 @@ def add_results(self, testrun_id):
198210
:param testrun_id: Id of the testrun to feed
199211
200212
"""
213+
# Results are sorted by 'case_id' and by 'status_id' (worst result at the end)
214+
self.results.sort(key=itemgetter('status_id'))
215+
self.results.sort(key=itemgetter('case_id'))
216+
217+
# Publish results
201218
for result in self.results:
202219
data = {'status_id': result['status_id']}
203220
if self.version:
204221
data['version'] = self.version
222+
comment = result.get('comment', '')
223+
if comment:
224+
# Indent text to avoid string formatting by TestRail. Limit size of comment.
225+
data['comment'] = "# Pytest result: #\n"
226+
data['comment'] += 'Log truncated\n...\n' if len(str(comment)) > COMMENT_SIZE_LIMIT else ''
227+
data['comment'] += " " + str(comment)[-COMMENT_SIZE_LIMIT:].replace('\n', '\n ')
228+
duration = result.get('duration')
229+
if duration:
230+
duration = 1 if (duration < 1) else int(round(duration)) # TestRail API doesn't manage milliseconds
231+
data['elapsed'] = str(duration) + 's'
205232
response = self.client.send_post(
206233
ADD_RESULT_URL.format(testrun_id, result['case_id']),
207234
data,
208235
cert_check=self.cert_check
209236
)
210237
error = self.client.get_error(response)
211238
if error:
212-
print('Info: Testcase #{} not published for following reason: "{}"'.format(result['case_id'], error))
239+
print('[{}] Info: Testcase #{} not published for following reason: "{}"'.format(TESTRAIL_PREFIX,
240+
result['case_id'],
241+
error))
213242

214243
def create_test_run(
215244
self, assign_user_id, project_id, suite_id, testrun_name, tr_keys):
@@ -233,10 +262,12 @@ def create_test_run(
233262
)
234263
error = self.client.get_error(response)
235264
if error:
236-
print('Failed to create testrun: "{}"'.format(error))
265+
print('[{}] Failed to create testrun: "{}"'.format(TESTRAIL_PREFIX, error))
237266
else:
238267
self.testrun_id = response['id']
239-
print('New testrun created with name "{}" and ID={}'.format(testrun_name, self.testrun_id))
268+
print('[{}] New testrun created with name "{}" and ID={}'.format(TESTRAIL_PREFIX,
269+
testrun_name,
270+
self.testrun_id))
240271

241272
def is_testrun_available(self):
242273
"""
@@ -250,10 +281,10 @@ def is_testrun_available(self):
250281
)
251282
error = self.client.get_error(response)
252283
if error:
253-
print('Failed to retrieve testrun: "{}"'.format(error))
284+
print('[{}] Failed to retrieve testrun: "{}"'.format(TESTRAIL_PREFIX, error))
254285
return False
255-
else:
256-
return response['is_completed'] is False
286+
287+
return response['is_completed'] is False
257288

258289
def is_testplan_available(self):
259290
"""
@@ -267,10 +298,10 @@ def is_testplan_available(self):
267298
)
268299
error = self.client.get_error(response)
269300
if error:
270-
print('Failed to retrieve testplan: "{}"'.format(error))
301+
print('[{}] Failed to retrieve testplan: "{}"'.format(TESTRAIL_PREFIX, error))
271302
return False
272-
else:
273-
return response['is_completed'] is False
303+
304+
return response['is_completed'] is False
274305

275306
def get_available_testruns(self, plan_id):
276307
"""
@@ -284,7 +315,7 @@ def get_available_testruns(self, plan_id):
284315
)
285316
error = self.client.get_error(response)
286317
if error:
287-
print('Failed to retrieve testplan: "{}"'.format(error))
318+
print('[{}] Failed to retrieve testplan: "{}"'.format(TESTRAIL_PREFIX, error))
288319
else:
289320
for entry in response['entries']:
290321
for run in entry['runs']:

tests/livetest/livetest.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
# -*- coding: UTF-8 -*-
22
import pytest
3+
import time
34

45
from pytest_testrail.plugin import testrail, pytestrail
56

67
@testrail('C344', 'C366')
78
def test_func1():
8-
pass
9+
time.sleep(0.5)
910

1011
@testrail('C345')
1112
def test_func2():
13+
time.sleep(1.6)
1214
pytest.fail()
1315

1416
@testrail('C99999')
1517
def test_func3():
16-
pass
18+
time.sleep(0.5)
1719

1820
@pytestrail.case('C1788')
1921
def test_func4():
2022
pytest.skip()
2123

2224
@pytestrail.case('C1789')
2325
def test_func5():
24-
pass
26+
time.sleep(0.5)

0 commit comments

Comments
 (0)