src/eric7/Testing/Interfaces/UnittestRunner.py

branch
eric7-maintenance
changeset 10460
3b34efa2857c
parent 9654
7328efba128b
parent 10439
21c28b0f9e41
child 11118
967a88a16a21
equal deleted inserted replaced
10366:411df92e881f 10460:3b34efa2857c
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 2
3 # Copyright (c) 2022 - 2023 Detlev Offenbach <detlev@die-offenbachs.de> 3 # Copyright (c) 2022 - 2024 Detlev Offenbach <detlev@die-offenbachs.de>
4 # 4 #
5 5
6 """ 6 """
7 Module implementing the test runner script for the 'unittest' framework. 7 Module implementing the test runner script for the 'unittest' framework.
8 """ 8 """
9 9
10 import importlib 10 import importlib
11 import importlib.util
11 import json 12 import json
12 import os 13 import os
13 import sys 14 import sys
14 import time 15 import time
15 import unittest 16 import unittest
244 "tests": self.__testsRun, 245 "tests": self.__testsRun,
245 } 246 }
246 ) 247 )
247 248
248 249
249 def _assembleTestCasesList(suite): 250 def _assembleTestCasesList(suite, start):
250 """ 251 """
251 Protected function to assemble a list of test cases included in a test 252 Protected function to assemble a list of test cases included in a test
252 suite. 253 suite.
253 254
254 @param suite test suite to be inspected 255 @param suite test suite to be inspected
255 @type unittest.TestSuite 256 @type unittest.TestSuite
256 @return list of tuples containing the test case ID, the string 257 @param start name of directory discovery was started at
257 representation and the short description 258 @type str
258 @rtype list of tuples of (str, str) 259 @return list of tuples containing the test case ID, the string representation,
260 a short description and the path of the test file name
261 @rtype list of tuples of (str, str, str, str)
259 """ 262 """
260 testCases = [] 263 testCases = []
261 for test in suite: 264 for test in suite:
262 if isinstance(test, unittest.TestSuite): 265 if isinstance(test, unittest.TestSuite):
263 testCases.extend(_assembleTestCasesList(test)) 266 testCases.extend(_assembleTestCasesList(test, start))
264 else: 267 else:
265 testId = test.id() 268 testId = test.id()
266 if ( 269 if (
267 "ModuleImportFailure" not in testId 270 "ModuleImportFailure" not in testId
268 and "LoadTestsFailure" not in testId 271 and "LoadTestsFailure" not in testId
269 and "_FailedTest" not in testId 272 and "_FailedTest" not in testId
270 ): 273 ):
271 testCases.append((testId, str(test), test.shortDescription())) 274 filename = os.path.join(
275 start, test.__module__.replace(".", os.sep) + ".py"
276 )
277 testCases.append((testId, str(test), test.shortDescription(), filename))
272 return testCases 278 return testCases
273 279
274 280
275 def runtest(argv): 281 def runtest(argv, discoverOnly=False):
276 """ 282 """
277 Function to run the tests. 283 Function to run and/or discover the tests.
278 284
279 @param argv list of command line parameters. 285 @param argv list of command line parameters.
280 @type list of str 286 @type list of str
287 @param discoverOnly flag indicating to just discover the available test cases
288 (defaults to False)
289 @type bool (optional)
281 """ 290 """
282 from eric7.EricNetwork.EricJsonStreamWriter import EricJsonWriter 291 from eric7.EricNetwork.EricJsonStreamWriter import EricJsonWriter
283 292
284 writer = EricJsonWriter(argv[0], int(argv[1])) 293 writer = EricJsonWriter(argv[0], int(argv[1]))
285 del argv[:2] 294 del argv[:2]
328 failed = argv[2:] 337 failed = argv[2:]
329 else: 338 else:
330 failed = [] 339 failed = []
331 if discover: 340 if discover:
332 testFileName = testName = "" 341 testFileName = testName = ""
342 testCases = argv[:]
333 else: 343 else:
334 testFileName, testName = argv[:2] 344 testFileName, testName = argv[:2]
335 del argv[:2] 345 del argv[:2]
336
337 testCases = argv[:]
338 346
339 if testFileName: 347 if testFileName:
340 sys.path.insert(1, os.path.dirname(os.path.abspath(testFileName))) 348 sys.path.insert(1, os.path.dirname(os.path.abspath(testFileName)))
341 elif discoveryStart: 349 elif discoveryStart:
342 sys.path.insert(1, os.path.abspath(discoveryStart)) 350 sys.path.insert(1, os.path.abspath(discoveryStart))
360 os.path.join( 368 os.path.join(
361 os.path.dirname(__file__), "..", "..", "DebugClients", "Python" 369 os.path.dirname(__file__), "..", "..", "DebugClients", "Python"
362 ) 370 )
363 ), 371 ),
364 ) 372 )
365 from coverage import Coverage # __IGNORE_WARNING_I10__ 373 try:
366 374 from coverage import Coverage # __IGNORE_WARNING_I10__
367 cover = Coverage(data_file=covDataFile) 375
368 if coverageErase: 376 cover = Coverage(data_file=covDataFile)
369 cover.erase() 377 if coverageErase:
370 cover.start() 378 cover.erase()
379 cover.start()
380 except ImportError:
381 cover = None
371 else: 382 else:
372 cover = None 383 cover = None
373 384
374 try: 385 try:
375 testLoader = unittest.TestLoader() 386 testLoader = unittest.TestLoader()
409 sys.exit(1) 420 sys.exit(1)
410 421
411 collectedTests = { 422 collectedTests = {
412 "event": "collected", 423 "event": "collected",
413 "tests": [ 424 "tests": [
414 {"id": id, "name": name, "description": desc} 425 {"id": id, "name": name, "description": desc, "filename": filename}
415 for id, name, desc in _assembleTestCasesList(test) 426 for id, name, desc, filename in _assembleTestCasesList(test, discoveryStart)
416 ], 427 ],
417 } 428 }
418 writer.write(collectedTests) 429 writer.write(collectedTests)
419 430
420 testResult = EricTestResult(writer, failfast) 431 if not discoverOnly:
421 startTestRun = getattr(testResult, "startTestRun", None) 432 testResult = EricTestResult(writer, failfast)
422 if startTestRun is not None: 433 startTestRun = getattr(testResult, "startTestRun", None)
423 startTestRun() 434 if startTestRun is not None:
424 try: 435 startTestRun()
425 test.run(testResult) 436 try:
426 finally: 437 test.run(testResult)
427 if cover: 438 finally:
428 cover.stop() 439 if cover:
429 cover.save() 440 cover.stop()
430 writer.write( 441 cover.save()
431 { 442 writer.write(
432 "event": "coverage", 443 {
433 "file": covDataFile, 444 "event": "coverage",
434 } 445 "file": covDataFile,
435 ) 446 }
436 stopTestRun = getattr(testResult, "stopTestRun", None) 447 )
437 if stopTestRun is not None: 448 stopTestRun = getattr(testResult, "stopTestRun", None)
438 stopTestRun() 449 if stopTestRun is not None:
450 stopTestRun()
439 451
440 writer.close() 452 writer.close()
441 sys.exit(0) 453 sys.exit(0)
442 454
443 455
456 "plugins": [], 468 "plugins": [],
457 } 469 }
458 print(json.dumps(versions)) 470 print(json.dumps(versions))
459 sys.exit(0) 471 sys.exit(0)
460 472
473 elif command == "has_coverage":
474 if importlib.util.find_spec("coverage") is None:
475 # not available
476 sys.exit(1)
477 else:
478 # available
479 sys.exit(0)
480
461 elif command == "runtest": 481 elif command == "runtest":
462 runtest(sys.argv[2:]) 482 runtest(sys.argv[2:])
463 sys.exit(0) 483 sys.exit(0)
464 484
485 elif command == "discovery":
486 runtest(sys.argv[2:], discoverOnly=True)
487 sys.exit(0)
488
465 sys.exit(42) 489 sys.exit(42)
466 490
467 # 491 #
468 # eflag: noqa = M801 492 # eflag: noqa = M801

eric ide

mercurial