src/eric7/Testing/Interfaces/PytestExecutor.py

branch
eric7-maintenance
changeset 10460
3b34efa2857c
parent 10079
0222a480e93d
parent 10439
21c28b0f9e41
child 10694
f46c1e224e8a
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 executor for the 'pytest' framework. 7 Module implementing the executor for the 'pytest' framework.
8 """ 8 """
71 71
72 return {} 72 return {}
73 73
74 def hasCoverage(self, interpreter): 74 def hasCoverage(self, interpreter):
75 """ 75 """
76 Public method to get the test framework version and version information 76 Public method to check, if the collection of coverage data is available.
77 of its installed plugins.
78 77
79 @param interpreter interpreter to be used for the test 78 @param interpreter interpreter to be used for the test
80 @type str 79 @type str
81 @return flag indicating the availability of coverage functionality 80 @return flag indicating the availability of coverage functionality
82 @rtype bool 81 @rtype bool
165 if config.failedOnly: 164 if config.failedOnly:
166 args.append("--last-failed") 165 args.append("--last-failed")
167 else: 166 else:
168 args.append("--cache-clear") 167 args.append("--cache-clear")
169 168
170 if config.collectCoverage: 169 if not config.discoverOnly and config.collectCoverage:
171 args.extend(["--cov=.", "--cov-report="]) 170 args.extend(["--cov=.", "--cov-report="])
172 if not config.eraseCoverage: 171 if not config.eraseCoverage:
173 args.append("--cov-append") 172 args.append("--cov-append")
174 173
175 if config.testMarkerExpression: 174 if config.testMarkerExpression:
178 177
179 if config.testNamePattern: 178 if config.testNamePattern:
180 args.append("-k") 179 args.append("-k")
181 args.append(config.testNamePattern) 180 args.append(config.testNamePattern)
182 181
183 if config.testFilename: 182 if config.discoverOnly:
183 args.append("--collect-only")
184
185 if config.testCases:
186 args.extend(config.testCases)
187 elif config.testFilename:
184 if config.testName: 188 if config.testName:
185 args.append( 189 args.append(
186 "{0}::{1}".format( 190 "{0}::{1}".format(
187 config.testFilename, config.testName.replace(".", "::") 191 config.testFilename, config.testName.replace(".", "::")
188 ) 192 )
190 else: 194 else:
191 args.append(config.testFilename) 195 args.append(config.testFilename)
192 196
193 return args 197 return args
194 198
199 def discover(self, config, pythonpath):
200 """
201 Public method to start the test discovery process.
202
203 @param config configuration for the test discovery
204 @type TestConfig
205 @param pythonpath list of directories to be added to the Python path
206 @type list of str
207 """
208 self.reader = EricJsonReader(name="Pytest Reader", parent=self)
209 self.reader.dataReceived.connect(self.__processData)
210
211 self.__config = config
212
213 pythonpath.insert(0, os.path.abspath(config.discoveryStart))
214 self.__rootdir = config.discoveryStart
215
216 super().discover(config, pythonpath)
217
195 def start(self, config, pythonpath): 218 def start(self, config, pythonpath):
196 """ 219 """
197 Public method to start the testing process. 220 Public method to start the testing process.
198 221
199 @param config configuration for the test execution 222 @param config configuration for the test execution
218 else: 241 else:
219 self.__rootdir = "" 242 self.__rootdir = ""
220 243
221 super().start(config, pythonpath) 244 super().start(config, pythonpath)
222 245
246 def startDebug(self, config, pythonpath, debugger):
247 """
248 Public method to start the test run with debugger support.
249
250 @param config configuration for the test execution
251 @type TestConfig
252 @param pythonpath list of directories to be added to the Python path
253 @type list of str
254 @param debugger refference to the debugger interface
255 @type DebugUI
256 """
257 self.reader = EricJsonReader(name="Pytest Reader", parent=self)
258 self.reader.dataReceived.connect(self.__processData)
259
260 self.__config = config
261
262 if config.discoveryStart:
263 pythonpath.insert(0, os.path.abspath(config.discoveryStart))
264 elif config.testFilename:
265 pythonpath.insert(0, os.path.abspath(os.path.dirname(config.testFilename)))
266
267 if config.discover:
268 self.__rootdir = config.discoveryStart
269 elif config.testFilename:
270 self.__rootdir = os.path.dirname(config.testFilename)
271 else:
272 self.__rootdir = ""
273
274 super().startDebug(config, pythonpath, debugger)
275
223 def finished(self): 276 def finished(self):
224 """ 277 """
225 Public method handling the unit test process been finished. 278 Public method handling the unit test process been finished.
226 279
227 This method should read the results (if necessary) and emit the signal 280 This method should read the results (if necessary) and emit the signal
234 287
235 self.reader.close() 288 self.reader.close()
236 289
237 output = self.readAllOutput() 290 output = self.readAllOutput()
238 self.testFinished.emit([], output) 291 self.testFinished.emit([], output)
292
293 super().finished()
239 294
240 @pyqtSlot(object) 295 @pyqtSlot(object)
241 def __processData(self, data): 296 def __processData(self, data):
242 """ 297 """
243 Private slot to process the received data. 298 Private slot to process the received data.
255 self.collectError.emit([(name, data["report"])]) 310 self.collectError.emit([(name, data["report"])])
256 311
257 # tests collected 312 # tests collected
258 elif data["event"] == "collected": 313 elif data["event"] == "collected":
259 self.collected.emit( 314 self.collected.emit(
260 [(data["nodeid"], self.__nodeid2testname(data["nodeid"]), "")] 315 [
316 (
317 data["nodeid"],
318 self.__nodeid2testname(data["nodeid"]),
319 "",
320 os.path.join(self.__rootdir, data["filename"]),
321 data["linenumber"],
322 self.__nodeid2testpath(data["nodeid"]),
323 )
324 ]
261 ) 325 )
262 326
263 # test started 327 # test started
264 elif data["event"] == "starttest": 328 elif data["event"] == "starttest":
265 self.startTest.emit( 329 self.startTest.emit(
358 module, name = nodeid.split("::", 1) 422 module, name = nodeid.split("::", 1)
359 module = self.__normalizeModuleName(module) 423 module = self.__normalizeModuleName(module)
360 name = name.replace("::", ".") 424 name = name.replace("::", ".")
361 testname, name = "{0}.{1}".format(module, name).rsplit(".", 1) 425 testname, name = "{0}.{1}".format(module, name).rsplit(".", 1)
362 return "{0} ({1})".format(name, testname) 426 return "{0} ({1})".format(name, testname)
427
428 def __nodeid2testpath(self, nodeid):
429 """
430 Private method to convert a nodeid to a test path list.
431
432 @param nodeid nodeid to be converted
433 @type str
434 @return test path list
435 @rtype list of str
436 """
437 module, name = nodeid.split("::", 1)
438 module = self.__normalizeModuleName(module)
439 name = "{0}.{1}".format(module, name.replace("::", "."))
440 return name.split(".")

eric ide

mercurial