Corrected the VCS tracing state of the recently merged files. eric7-maintenance

Sun, 05 Jun 2022 17:17:44 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 05 Jun 2022 17:17:44 +0200
branch
eric7-maintenance
changeset 9131
bc0c1b6d6adb
parent 9112
9967ae9f0906
child 9136
9e0cf68f727b

Corrected the VCS tracing state of the recently merged files.

eric7/DataViews/PyCoverageHtmlReportDialog.py file | annotate | diff | comparison | revisions
eric7/DataViews/PyCoverageHtmlReportDialog.ui file | annotate | diff | comparison | revisions
eric7/DataViews/PyCoverageJsonReportDialog.py file | annotate | diff | comparison | revisions
eric7/DataViews/PyCoverageJsonReportDialog.ui file | annotate | diff | comparison | revisions
eric7/DebugClients/Python/DCTestResult.py file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.DataViews.PyCoverageHtmlReportDialog.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.DataViews.PyCoverageJsonReportDialog.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.DebugClients.Python.DCTestResult.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.DocumentationTools.TemplatesListsStyle.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.EricNetwork.EricJsonStreamReader.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.EricNetwork.EricJsonStreamWriter.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.PyUnit.UnittestDialog.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.Testing.Interfaces.PytestExecutor.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.Testing.Interfaces.PytestRunner.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.Testing.Interfaces.TestExecutorBase.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.Testing.Interfaces.TestFrameworkRegistry.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.Testing.Interfaces.UnittestExecutor.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.Testing.Interfaces.UnittestRunner.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.Testing.TestResultsTree.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.Testing.TestingWidget.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.Testing.__init__.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.eric7_testing.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/eric7.eric7_unittest.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/index-eric7.PyUnit.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/index-eric7.Testing.Interfaces.html file | annotate | diff | comparison | revisions
eric7/Documentation/Source/index-eric7.Testing.html file | annotate | diff | comparison | revisions
eric7/EricNetwork/EricJsonStreamReader.py file | annotate | diff | comparison | revisions
eric7/EricNetwork/EricJsonStreamWriter.py file | annotate | diff | comparison | revisions
eric7/PyUnit/UnittestDialog.py file | annotate | diff | comparison | revisions
eric7/PyUnit/UnittestDialog.ui file | annotate | diff | comparison | revisions
eric7/PyUnit/UnittestStacktraceDialog.ui file | annotate | diff | comparison | revisions
eric7/PyUnit/__init__.py file | annotate | diff | comparison | revisions
eric7/Testing/Interfaces/PytestExecutor.py file | annotate | diff | comparison | revisions
eric7/Testing/Interfaces/PytestRunner.py file | annotate | diff | comparison | revisions
eric7/Testing/Interfaces/TestExecutorBase.py file | annotate | diff | comparison | revisions
eric7/Testing/Interfaces/TestFrameworkRegistry.py file | annotate | diff | comparison | revisions
eric7/Testing/Interfaces/UnittestExecutor.py file | annotate | diff | comparison | revisions
eric7/Testing/Interfaces/UnittestRunner.py file | annotate | diff | comparison | revisions
eric7/Testing/Interfaces/__init__.py file | annotate | diff | comparison | revisions
eric7/Testing/TestResultsTree.py file | annotate | diff | comparison | revisions
eric7/Testing/TestingWidget.py file | annotate | diff | comparison | revisions
eric7/Testing/TestingWidget.ui file | annotate | diff | comparison | revisions
eric7/Testing/__init__.py file | annotate | diff | comparison | revisions
eric7/eric7_testing.py file | annotate | diff | comparison | revisions
eric7/eric7_testing.pyw file | annotate | diff | comparison | revisions
eric7/eric7_unittest.py file | annotate | diff | comparison | revisions
eric7/eric7_unittest.pyw file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/DataViews/PyCoverageHtmlReportDialog.py	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to enter the parameters for a coverage HTML
+report.
+"""
+
+from PyQt6.QtCore import pyqtSlot
+from PyQt6.QtWidgets import QDialog, QDialogButtonBox
+
+from EricWidgets.EricPathPicker import EricPathPickerModes
+
+from .Ui_PyCoverageHtmlReportDialog import Ui_PyCoverageHtmlReportDialog
+
+
+class PyCoverageHtmlReportDialog(QDialog, Ui_PyCoverageHtmlReportDialog):
+    """
+    Class implementing a dialog to enter the parameters for a coverage HTML
+    report.
+    """
+    def __init__(self, defaultDirectory, parent=None):
+        """
+        Constructor
+        
+        @param defaultDirectory default directory for selecting the output
+            directory
+        @type str
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+        
+        self.outputDirectoryPicker.setMode(
+            EricPathPickerModes.DIRECTORY_SHOW_FILES_MODE)
+        self.outputDirectoryPicker.setDefaultDirectory(defaultDirectory)
+        
+        self.extraCssPicker.setMode(
+            EricPathPickerModes.OPEN_FILE_MODE)
+        
+        self.buttonBox.button(
+            QDialogButtonBox.StandardButton.Ok).setEnabled(False)
+        
+        msh = self.minimumSizeHint()
+        self.resize(max(self.width(), msh.width()), msh.height())
+    
+    @pyqtSlot(str)
+    def on_outputDirectoryPicker_textChanged(self, directory):
+        """
+        Private slot handling a change of the output directory.
+        
+        @param directory current text of the directory picker
+        @type str
+        """
+        self.buttonBox.button(
+            QDialogButtonBox.StandardButton.Ok).setEnabled(bool(directory))
+    
+    def getData(self):
+        """
+        Public method to get the entered data.
+        
+        @return tuple containing the report title, the output directory, the
+            path of a file containing extra CSS and a flag indicating to open
+            the generated report in a browser
+        
+        @rtype tuple of (str, str, str, bool)
+        """
+        title = self.titleEdit.text()
+        return (
+            title if bool(title) else None,
+            self.outputDirectoryPicker.currentText(),
+            self.extraCssPicker.currentText(),
+            self.openReportCheckBox.isChecked(),
+        )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/DataViews/PyCoverageHtmlReportDialog.ui	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PyCoverageHtmlReportDialog</class>
+ <widget class="QDialog" name="PyCoverageHtmlReportDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>500</width>
+    <height>154</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>HTML Report</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Title:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="EricPathPicker" name="extraCssPicker" native="true">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="focusPolicy">
+      <enum>Qt::StrongFocus</enum>
+     </property>
+     <property name="toolTip">
+      <string>Enter the path of a file containing additional CSS definitions</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>Extra CSS:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="QLineEdit" name="titleEdit">
+     <property name="toolTip">
+      <string>Enter the title for the HTML report</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Output Directory:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="EricPathPicker" name="outputDirectoryPicker" native="true">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="focusPolicy">
+      <enum>Qt::StrongFocus</enum>
+     </property>
+     <property name="toolTip">
+      <string>Enter the path of the output directory</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0" colspan="2">
+    <widget class="QCheckBox" name="openReportCheckBox">
+     <property name="toolTip">
+      <string>Select to open the generated report</string>
+     </property>
+     <property name="text">
+      <string>Open Report</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>EricPathPicker</class>
+   <extends>QWidget</extends>
+   <header>EricWidgets/EricPathPicker.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>titleEdit</tabstop>
+  <tabstop>outputDirectoryPicker</tabstop>
+  <tabstop>extraCssPicker</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>PyCoverageHtmlReportDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>PyCoverageHtmlReportDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/DataViews/PyCoverageJsonReportDialog.py	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a dialog to enter the parameters for a coverage JSON
+report.
+"""
+
+import os
+
+from PyQt6.QtCore import pyqtSlot
+from PyQt6.QtWidgets import QDialog, QDialogButtonBox
+
+from EricWidgets.EricPathPicker import EricPathPickerModes
+
+from .Ui_PyCoverageJsonReportDialog import Ui_PyCoverageJsonReportDialog
+
+
+class PyCoverageJsonReportDialog(QDialog, Ui_PyCoverageJsonReportDialog):
+    """
+    Class implementing a dialog to enter the parameters for a coverage JSON
+    report.
+    """
+    def __init__(self, defaultDirectory, parent=None):
+        """
+        Constructor
+        
+        @param defaultDirectory default directory for selecting the output
+            directory
+        @type str
+        @param parent reference to the parent widget (defaults to None)
+        @type QWidget (optional)
+        """
+        super().__init__(parent)
+        self.setupUi(self)
+        
+        self.outputFilePicker.setMode(
+            EricPathPickerModes.SAVE_FILE_ENSURE_EXTENSION_MODE)
+        self.outputFilePicker.setDefaultDirectory(defaultDirectory)
+        self.outputFilePicker.setFilters(
+            self.tr("JSON Files (*.json);;All Files (*)"))
+        self.outputFilePicker.setText(
+            os.path.join(defaultDirectory, "coverage.json"))
+        
+        msh = self.minimumSizeHint()
+        self.resize(max(self.width(), msh.width()), msh.height())
+    
+    @pyqtSlot(str)
+    def on_outputFilePicker_textChanged(self, filename):
+        """
+        Private slot handling a change of the output file.
+        
+        @param filename current text of the file picker
+        @type str
+        """
+        self.buttonBox.button(
+            QDialogButtonBox.StandardButton.Ok).setEnabled(bool(filename))
+    
+    def getData(self):
+        """
+        Public method to get the entered data.
+        
+        @return tuple containing the output file and a flag indicating the
+            creation of a compact JSON file
+        
+        @rtype tuple of (str, bool)
+        """
+        return (
+            self.outputFilePicker.currentText(),
+            self.compactCheckBox.isChecked(),
+        )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/DataViews/PyCoverageJsonReportDialog.ui	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PyCoverageJsonReportDialog</class>
+ <widget class="QDialog" name="PyCoverageJsonReportDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>500</width>
+    <height>98</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>JSON Report</string>
+  </property>
+  <property name="sizeGripEnabled">
+   <bool>true</bool>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="1" column="0" colspan="2">
+    <widget class="QCheckBox" name="compactCheckBox">
+     <property name="toolTip">
+      <string>Select to create the report using the compact format</string>
+     </property>
+     <property name="text">
+      <string>Compact Format</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Output File:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="1">
+    <widget class="EricPathPicker" name="outputFilePicker" native="true">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="focusPolicy">
+      <enum>Qt::StrongFocus</enum>
+     </property>
+     <property name="toolTip">
+      <string>Enter the path of the output file</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>EricPathPicker</class>
+   <extends>QWidget</extends>
+   <header>EricWidgets/EricPathPicker.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>outputFilePicker</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>PyCoverageJsonReportDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>PyCoverageJsonReportDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- a/eric7/DebugClients/Python/DCTestResult.py	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2003 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing a TestResult derivative for the eric debugger.
-"""
-
-import select
-from unittest import TestResult
-
-
-class DCTestResult(TestResult):
-    """
-    A TestResult derivative to work with eric's debug client.
-    
-    For more details see unittest.py of the standard python distribution.
-    """
-    def __init__(self, dbgClient, failfast):
-        """
-        Constructor
-        
-        @param dbgClient reference to the debug client
-        @type DebugClientBase
-        @param failfast flag indicating to stop at the first error
-        @type bool
-        """
-        TestResult.__init__(self)
-        self.__dbgClient = dbgClient
-        self.failfast = failfast
-    
-    def addFailure(self, test, err):
-        """
-        Public method called if a test failed.
-        
-        @param test Reference to the test object
-        @param err The error traceback
-        """
-        TestResult.addFailure(self, test, err)
-        tracebackLines = self._exc_info_to_string(err, test)
-        self.__dbgClient.sendJsonCommand("ResponseUTTestFailed", {
-            "testname": str(test),
-            "traceback": tracebackLines,
-            "id": test.id(),
-        })
-    
-    def addError(self, test, err):
-        """
-        Public method called if a test errored.
-        
-        @param test Reference to the test object
-        @param err The error traceback
-        """
-        TestResult.addError(self, test, err)
-        tracebackLines = self._exc_info_to_string(err, test)
-        self.__dbgClient.sendJsonCommand("ResponseUTTestErrored", {
-            "testname": str(test),
-            "traceback": tracebackLines,
-            "id": test.id(),
-        })
-    
-    def addSubTest(self, test, subtest, err):
-        """
-        Public method called for each subtest to record its result.
-        
-        @param test reference to the test object
-        @param subtest reference to the subtest object
-        @param err error traceback
-        """
-        if err is not None:
-            TestResult.addSubTest(self, test, subtest, err)
-            tracebackLines = self._exc_info_to_string(err, test)
-            if issubclass(err[0], test.failureException):
-                self.__dbgClient.sendJsonCommand("ResponseUTTestFailed", {
-                    "testname": str(subtest),
-                    "traceback": tracebackLines,
-                    "id": test.id(),
-                })
-            else:
-                self.__dbgClient.sendJsonCommand("ResponseUTTestErrored", {
-                    "testname": str(subtest),
-                    "traceback": tracebackLines,
-                    "id": test.id(),
-                })
-    
-    def addSkip(self, test, reason):
-        """
-        Public method called if a test was skipped.
-        
-        @param test reference to the test object
-        @param reason reason for skipping the test (string)
-        """
-        TestResult.addSkip(self, test, reason)
-        self.__dbgClient.sendJsonCommand("ResponseUTTestSkipped", {
-            "testname": str(test),
-            "reason": reason,
-            "id": test.id(),
-        })
-    
-    def addExpectedFailure(self, test, err):
-        """
-        Public method called if a test failed expected.
-        
-        @param test reference to the test object
-        @param err error traceback
-        """
-        TestResult.addExpectedFailure(self, test, err)
-        tracebackLines = self._exc_info_to_string(err, test)
-        self.__dbgClient.sendJsonCommand("ResponseUTTestFailedExpected", {
-            "testname": str(test),
-            "traceback": tracebackLines,
-            "id": test.id(),
-        })
-    
-    def addUnexpectedSuccess(self, test):
-        """
-        Public method called if a test succeeded expectedly.
-        
-        @param test reference to the test object
-        """
-        TestResult.addUnexpectedSuccess(self, test)
-        self.__dbgClient.sendJsonCommand("ResponseUTTestSucceededUnexpected", {
-            "testname": str(test),
-            "id": test.id(),
-        })
-    
-    def startTest(self, test):
-        """
-        Public method called at the start of a test.
-        
-        @param test Reference to the test object
-        """
-        TestResult.startTest(self, test)
-        self.__dbgClient.sendJsonCommand("ResponseUTStartTest", {
-            "testname": str(test),
-            "description": test.shortDescription(),
-        })
-    
-    def stopTest(self, test):
-        """
-        Public method called at the end of a test.
-        
-        @param test Reference to the test object
-        """
-        TestResult.stopTest(self, test)
-        self.__dbgClient.sendJsonCommand("ResponseUTStopTest", {})
-        
-        # ensure that pending input is processed
-        rrdy, wrdy, xrdy = select.select(
-            [self.__dbgClient.readstream], [], [], 0.01)
-
-        if self.__dbgClient.readstream in rrdy:
-            self.__dbgClient.readReady(self.__dbgClient.readstream)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.DataViews.PyCoverageHtmlReportDialog.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.DataViews.PyCoverageHtmlReportDialog</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.DataViews.PyCoverageHtmlReportDialog</h1>
+
+<p>
+Module implementing a dialog to enter the parameters for a coverage HTML
+report.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#PyCoverageHtmlReportDialog">PyCoverageHtmlReportDialog</a></td>
+<td>Class implementing a dialog to enter the parameters for a coverage HTML report.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="PyCoverageHtmlReportDialog" ID="PyCoverageHtmlReportDialog"></a>
+<h2>PyCoverageHtmlReportDialog</h2>
+
+<p>
+    Class implementing a dialog to enter the parameters for a coverage HTML
+    report.
+</p>
+<h3>Derived from</h3>
+QDialog, Ui_PyCoverageHtmlReportDialog
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#PyCoverageHtmlReportDialog.__init__">PyCoverageHtmlReportDialog</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#PyCoverageHtmlReportDialog.getData">getData</a></td>
+<td>Public method to get the entered data.</td>
+</tr>
+<tr>
+<td><a href="#PyCoverageHtmlReportDialog.on_outputDirectoryPicker_textChanged">on_outputDirectoryPicker_textChanged</a></td>
+<td>Private slot handling a change of the output directory.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="PyCoverageHtmlReportDialog.__init__" ID="PyCoverageHtmlReportDialog.__init__"></a>
+<h4>PyCoverageHtmlReportDialog (Constructor)</h4>
+<b>PyCoverageHtmlReportDialog</b>(<i>defaultDirectory, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>defaultDirectory</i> (str)</dt>
+<dd>
+default directory for selecting the output
+            directory
+</dd>
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="PyCoverageHtmlReportDialog.getData" ID="PyCoverageHtmlReportDialog.getData"></a>
+<h4>PyCoverageHtmlReportDialog.getData</h4>
+<b>getData</b>(<i></i>)
+
+<p>
+        Public method to get the entered data.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the report title, the output directory, the
+            path of a file containing extra CSS and a flag indicating to open
+            the generated report in a browser
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (str, str, str, bool)
+</dd>
+</dl>
+<a NAME="PyCoverageHtmlReportDialog.on_outputDirectoryPicker_textChanged" ID="PyCoverageHtmlReportDialog.on_outputDirectoryPicker_textChanged"></a>
+<h4>PyCoverageHtmlReportDialog.on_outputDirectoryPicker_textChanged</h4>
+<b>on_outputDirectoryPicker_textChanged</b>(<i>directory</i>)
+
+<p>
+        Private slot handling a change of the output directory.
+</p>
+<dl>
+
+<dt><i>directory</i> (str)</dt>
+<dd>
+current text of the directory picker
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.DataViews.PyCoverageJsonReportDialog.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.DataViews.PyCoverageJsonReportDialog</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.DataViews.PyCoverageJsonReportDialog</h1>
+
+<p>
+Module implementing a dialog to enter the parameters for a coverage JSON
+report.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#PyCoverageJsonReportDialog">PyCoverageJsonReportDialog</a></td>
+<td>Class implementing a dialog to enter the parameters for a coverage JSON report.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="PyCoverageJsonReportDialog" ID="PyCoverageJsonReportDialog"></a>
+<h2>PyCoverageJsonReportDialog</h2>
+
+<p>
+    Class implementing a dialog to enter the parameters for a coverage JSON
+    report.
+</p>
+<h3>Derived from</h3>
+QDialog, Ui_PyCoverageJsonReportDialog
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#PyCoverageJsonReportDialog.__init__">PyCoverageJsonReportDialog</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#PyCoverageJsonReportDialog.getData">getData</a></td>
+<td>Public method to get the entered data.</td>
+</tr>
+<tr>
+<td><a href="#PyCoverageJsonReportDialog.on_outputFilePicker_textChanged">on_outputFilePicker_textChanged</a></td>
+<td>Private slot handling a change of the output file.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="PyCoverageJsonReportDialog.__init__" ID="PyCoverageJsonReportDialog.__init__"></a>
+<h4>PyCoverageJsonReportDialog (Constructor)</h4>
+<b>PyCoverageJsonReportDialog</b>(<i>defaultDirectory, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>defaultDirectory</i> (str)</dt>
+<dd>
+default directory for selecting the output
+            directory
+</dd>
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="PyCoverageJsonReportDialog.getData" ID="PyCoverageJsonReportDialog.getData"></a>
+<h4>PyCoverageJsonReportDialog.getData</h4>
+<b>getData</b>(<i></i>)
+
+<p>
+        Public method to get the entered data.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the output file and a flag indicating the
+            creation of a compact JSON file
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (str, bool)
+</dd>
+</dl>
+<a NAME="PyCoverageJsonReportDialog.on_outputFilePicker_textChanged" ID="PyCoverageJsonReportDialog.on_outputFilePicker_textChanged"></a>
+<h4>PyCoverageJsonReportDialog.on_outputFilePicker_textChanged</h4>
+<b>on_outputFilePicker_textChanged</b>(<i>filename</i>)
+
+<p>
+        Private slot handling a change of the output file.
+</p>
+<dl>
+
+<dt><i>filename</i> (str)</dt>
+<dd>
+current text of the file picker
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/eric7/Documentation/Source/eric7.DebugClients.Python.DCTestResult.html	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,259 +0,0 @@
-<!DOCTYPE html>
-<html><head>
-<title>eric7.DebugClients.Python.DCTestResult</title>
-<meta charset="UTF-8">
-<link rel="stylesheet" href="styles.css">
-</head>
-<body>
-<a NAME="top" ID="top"></a>
-<h1>eric7.DebugClients.Python.DCTestResult</h1>
-
-<p>
-Module implementing a TestResult derivative for the eric debugger.
-</p>
-<h3>Global Attributes</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Classes</h3>
-
-<table>
-
-<tr>
-<td><a href="#DCTestResult">DCTestResult</a></td>
-<td>A TestResult derivative to work with eric's debug client.</td>
-</tr>
-</table>
-<h3>Functions</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<hr />
-<hr />
-<a NAME="DCTestResult" ID="DCTestResult"></a>
-<h2>DCTestResult</h2>
-
-<p>
-    A TestResult derivative to work with eric's debug client.
-</p>
-<p>
-    For more details see unittest.py of the standard python distribution.
-</p>
-<h3>Derived from</h3>
-TestResult
-<h3>Class Attributes</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Class Methods</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Methods</h3>
-
-<table>
-
-<tr>
-<td><a href="#DCTestResult.__init__">DCTestResult</a></td>
-<td>Constructor</td>
-</tr>
-<tr>
-<td><a href="#DCTestResult.addError">addError</a></td>
-<td>Public method called if a test errored.</td>
-</tr>
-<tr>
-<td><a href="#DCTestResult.addExpectedFailure">addExpectedFailure</a></td>
-<td>Public method called if a test failed expected.</td>
-</tr>
-<tr>
-<td><a href="#DCTestResult.addFailure">addFailure</a></td>
-<td>Public method called if a test failed.</td>
-</tr>
-<tr>
-<td><a href="#DCTestResult.addSkip">addSkip</a></td>
-<td>Public method called if a test was skipped.</td>
-</tr>
-<tr>
-<td><a href="#DCTestResult.addSubTest">addSubTest</a></td>
-<td>Public method called for each subtest to record its result.</td>
-</tr>
-<tr>
-<td><a href="#DCTestResult.addUnexpectedSuccess">addUnexpectedSuccess</a></td>
-<td>Public method called if a test succeeded expectedly.</td>
-</tr>
-<tr>
-<td><a href="#DCTestResult.startTest">startTest</a></td>
-<td>Public method called at the start of a test.</td>
-</tr>
-<tr>
-<td><a href="#DCTestResult.stopTest">stopTest</a></td>
-<td>Public method called at the end of a test.</td>
-</tr>
-</table>
-<h3>Static Methods</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-
-<a NAME="DCTestResult.__init__" ID="DCTestResult.__init__"></a>
-<h4>DCTestResult (Constructor)</h4>
-<b>DCTestResult</b>(<i>dbgClient, failfast</i>)
-
-<p>
-        Constructor
-</p>
-<dl>
-
-<dt><i>dbgClient</i> (DebugClientBase)</dt>
-<dd>
-reference to the debug client
-</dd>
-<dt><i>failfast</i> (bool)</dt>
-<dd>
-flag indicating to stop at the first error
-</dd>
-</dl>
-<a NAME="DCTestResult.addError" ID="DCTestResult.addError"></a>
-<h4>DCTestResult.addError</h4>
-<b>addError</b>(<i>test, err</i>)
-
-<p>
-        Public method called if a test errored.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-Reference to the test object
-</dd>
-<dt><i>err</i></dt>
-<dd>
-The error traceback
-</dd>
-</dl>
-<a NAME="DCTestResult.addExpectedFailure" ID="DCTestResult.addExpectedFailure"></a>
-<h4>DCTestResult.addExpectedFailure</h4>
-<b>addExpectedFailure</b>(<i>test, err</i>)
-
-<p>
-        Public method called if a test failed expected.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-<dt><i>err</i></dt>
-<dd>
-error traceback
-</dd>
-</dl>
-<a NAME="DCTestResult.addFailure" ID="DCTestResult.addFailure"></a>
-<h4>DCTestResult.addFailure</h4>
-<b>addFailure</b>(<i>test, err</i>)
-
-<p>
-        Public method called if a test failed.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-Reference to the test object
-</dd>
-<dt><i>err</i></dt>
-<dd>
-The error traceback
-</dd>
-</dl>
-<a NAME="DCTestResult.addSkip" ID="DCTestResult.addSkip"></a>
-<h4>DCTestResult.addSkip</h4>
-<b>addSkip</b>(<i>test, reason</i>)
-
-<p>
-        Public method called if a test was skipped.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-<dt><i>reason</i></dt>
-<dd>
-reason for skipping the test (string)
-</dd>
-</dl>
-<a NAME="DCTestResult.addSubTest" ID="DCTestResult.addSubTest"></a>
-<h4>DCTestResult.addSubTest</h4>
-<b>addSubTest</b>(<i>test, subtest, err</i>)
-
-<p>
-        Public method called for each subtest to record its result.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-<dt><i>subtest</i></dt>
-<dd>
-reference to the subtest object
-</dd>
-<dt><i>err</i></dt>
-<dd>
-error traceback
-</dd>
-</dl>
-<a NAME="DCTestResult.addUnexpectedSuccess" ID="DCTestResult.addUnexpectedSuccess"></a>
-<h4>DCTestResult.addUnexpectedSuccess</h4>
-<b>addUnexpectedSuccess</b>(<i>test</i>)
-
-<p>
-        Public method called if a test succeeded expectedly.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-</dl>
-<a NAME="DCTestResult.startTest" ID="DCTestResult.startTest"></a>
-<h4>DCTestResult.startTest</h4>
-<b>startTest</b>(<i>test</i>)
-
-<p>
-        Public method called at the start of a test.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-Reference to the test object
-</dd>
-</dl>
-<a NAME="DCTestResult.stopTest" ID="DCTestResult.stopTest"></a>
-<h4>DCTestResult.stopTest</h4>
-<b>stopTest</b>(<i>test</i>)
-
-<p>
-        Public method called at the end of a test.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-Reference to the test object
-</dd>
-</dl>
-<div align="right"><a href="#top">Up</a></div>
-<hr />
-</body></html>
\ No newline at end of file
--- a/eric7/Documentation/Source/eric7.DocumentationTools.TemplatesListsStyle.html	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<html><head>
-<title>eric7.DocumentationTools.TemplatesListsStyle</title>
-<meta charset="UTF-8">
-<link rel="stylesheet" href="styles.css">
-</head>
-<body>
-<a NAME="top" ID="top"></a>
-<h1>eric7.DocumentationTools.TemplatesListsStyle</h1>
-
-<p>
-Module implementing templates for the documentation generator (lists style).
-</p>
-<h3>Global Attributes</h3>
-
-<table>
-<tr><td>authorInfoTemplate</td></tr><tr><td>classTemplate</td></tr><tr><td>constructorTemplate</td></tr><tr><td>deprecatedTemplate</td></tr><tr><td>eventsListEntryTemplate</td></tr><tr><td>eventsListTemplate</td></tr><tr><td>exceptionsListEntryTemplate</td></tr><tr><td>exceptionsListTemplate</td></tr><tr><td>footerTemplate</td></tr><tr><td>functionTemplate</td></tr><tr><td>headerTemplate</td></tr><tr><td>indexBodyTemplate</td></tr><tr><td>indexListEntryTemplate</td></tr><tr><td>indexListModulesTemplate</td></tr><tr><td>indexListPackagesTemplate</td></tr><tr><td>listEntryDeprecatedTemplate</td></tr><tr><td>listEntryNoneTemplate</td></tr><tr><td>listEntrySimpleTemplate</td></tr><tr><td>listEntryTemplate</td></tr><tr><td>listTemplate</td></tr><tr><td>methodTemplate</td></tr><tr><td>moduleTemplate</td></tr><tr><td>paragraphTemplate</td></tr><tr><td>parameterTypesListEntryTemplate</td></tr><tr><td>parametersListEntryTemplate</td></tr><tr><td>parametersListTemplate</td></tr><tr><td>rbFileTemplate</td></tr><tr><td>rbModuleTemplate</td></tr><tr><td>rbModulesClassTemplate</td></tr><tr><td>returnTypesTemplate</td></tr><tr><td>returnsTemplate</td></tr><tr><td>seeLinkTemplate</td></tr><tr><td>seeListEntryTemplate</td></tr><tr><td>seeListTemplate</td></tr><tr><td>signalsListEntryTemplate</td></tr><tr><td>signalsListTemplate</td></tr><tr><td>sinceInfoTemplate</td></tr><tr><td>yieldTypesTemplate</td></tr><tr><td>yieldsTemplate</td></tr>
-</table>
-<h3>Classes</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Functions</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<hr />
-</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.EricNetwork.EricJsonStreamReader.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,183 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.EricNetwork.EricJsonStreamReader</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.EricNetwork.EricJsonStreamReader</h1>
+
+<p>
+Module implementing a JSON based reader class.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricJsonReader">EricJsonReader</a></td>
+<td>Class implementing a JSON based reader class.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="EricJsonReader" ID="EricJsonReader"></a>
+<h2>EricJsonReader</h2>
+
+<p>
+    Class implementing a JSON based reader class.
+</p>
+<p>
+    The reader is responsible for opening a socket to listen for writer
+    connections.
+</p>
+<h3>Signals</h3>
+<dl>
+
+<dt>dataReceived(object)</dt>
+<dd>
+emitted after a data object was received
+</dd>
+</dl>
+<h3>Derived from</h3>
+QTcpServer
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricJsonReader.__init__">EricJsonReader</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#EricJsonReader.__handleDisconnect">__handleDisconnect</a></td>
+<td>Private slot handling a disconnect of the writer.</td>
+</tr>
+<tr>
+<td><a href="#EricJsonReader.__receiveJson">__receiveJson</a></td>
+<td>Private slot handling received data from the writer.</td>
+</tr>
+<tr>
+<td><a href="#EricJsonReader.address">address</a></td>
+<td>Public method to get the host address.</td>
+</tr>
+<tr>
+<td><a href="#EricJsonReader.handleNewConnection">handleNewConnection</a></td>
+<td>Public slot for new incoming connections from a writer.</td>
+</tr>
+<tr>
+<td><a href="#EricJsonReader.port">port</a></td>
+<td>Public method to get the port number to connect to.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="EricJsonReader.__init__" ID="EricJsonReader.__init__"></a>
+<h4>EricJsonReader (Constructor)</h4>
+<b>EricJsonReader</b>(<i>name="", ip=None, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>name</i> (str)</dt>
+<dd>
+name of the server (used for output only)
+</dd>
+<dt><i>ip</i> (str)</dt>
+<dd>
+IP address to listen at
+</dd>
+<dt><i>parent</i> (QObject)</dt>
+<dd>
+parent object
+</dd>
+</dl>
+<a NAME="EricJsonReader.__handleDisconnect" ID="EricJsonReader.__handleDisconnect"></a>
+<h4>EricJsonReader.__handleDisconnect</h4>
+<b>__handleDisconnect</b>(<i></i>)
+
+<p>
+        Private slot handling a disconnect of the writer.
+</p>
+<a NAME="EricJsonReader.__receiveJson" ID="EricJsonReader.__receiveJson"></a>
+<h4>EricJsonReader.__receiveJson</h4>
+<b>__receiveJson</b>(<i></i>)
+
+<p>
+        Private slot handling received data from the writer.
+</p>
+<a NAME="EricJsonReader.address" ID="EricJsonReader.address"></a>
+<h4>EricJsonReader.address</h4>
+<b>address</b>(<i></i>)
+
+<p>
+        Public method to get the host address.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+host address
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
+<a NAME="EricJsonReader.handleNewConnection" ID="EricJsonReader.handleNewConnection"></a>
+<h4>EricJsonReader.handleNewConnection</h4>
+<b>handleNewConnection</b>(<i></i>)
+
+<p>
+        Public slot for new incoming connections from a writer.
+</p>
+<a NAME="EricJsonReader.port" ID="EricJsonReader.port"></a>
+<h4>EricJsonReader.port</h4>
+<b>port</b>(<i></i>)
+
+<p>
+        Public method to get the port number to connect to.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+port number
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.EricNetwork.EricJsonStreamWriter.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.EricNetwork.EricJsonStreamWriter</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.EricNetwork.EricJsonStreamWriter</h1>
+
+<p>
+Module implementing a JSON based writer class.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricJsonWriter">EricJsonWriter</a></td>
+<td>Class implementing a JSON based writer class.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="EricJsonWriter" ID="EricJsonWriter"></a>
+<h2>EricJsonWriter</h2>
+
+<p>
+    Class implementing a JSON based writer class.
+</p>
+<h3>Derived from</h3>
+None
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricJsonWriter.__init__">EricJsonWriter</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#EricJsonWriter.close">close</a></td>
+<td>Public method to close the stream.</td>
+</tr>
+<tr>
+<td><a href="#EricJsonWriter.write">write</a></td>
+<td>Public method to send JSON serializable data.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="EricJsonWriter.__init__" ID="EricJsonWriter.__init__"></a>
+<h4>EricJsonWriter (Constructor)</h4>
+<b>EricJsonWriter</b>(<i>host, port</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>host</i> (str)</dt>
+<dd>
+IP address the reader is listening on
+</dd>
+<dt><i>port</i> (int)</dt>
+<dd>
+port the reader is listening on
+</dd>
+</dl>
+<a NAME="EricJsonWriter.close" ID="EricJsonWriter.close"></a>
+<h4>EricJsonWriter.close</h4>
+<b>close</b>(<i></i>)
+
+<p>
+        Public method to close the stream.
+</p>
+<a NAME="EricJsonWriter.write" ID="EricJsonWriter.write"></a>
+<h4>EricJsonWriter.write</h4>
+<b>write</b>(<i>data</i>)
+
+<p>
+        Public method to send JSON serializable data.
+</p>
+<dl>
+
+<dt><i>data</i> (object)</dt>
+<dd>
+JSON serializable object to be sent
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/eric7/Documentation/Source/eric7.PyUnit.UnittestDialog.html	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1236 +0,0 @@
-<!DOCTYPE html>
-<html><head>
-<title>eric7.PyUnit.UnittestDialog</title>
-<meta charset="UTF-8">
-<link rel="stylesheet" href="styles.css">
-</head>
-<body>
-<a NAME="top" ID="top"></a>
-<h1>eric7.PyUnit.UnittestDialog</h1>
-
-<p>
-Module implementing the UI to the pyunit package.
-</p>
-<h3>Global Attributes</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Classes</h3>
-
-<table>
-
-<tr>
-<td><a href="#QtTestResult">QtTestResult</a></td>
-<td>A TestResult derivative to work with a graphical GUI.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog">UnittestDialog</a></td>
-<td>Class implementing the UI to the pyunit package.</td>
-</tr>
-<tr>
-<td><a href="#UnittestWindow">UnittestWindow</a></td>
-<td>Main window class for the standalone dialog.</td>
-</tr>
-</table>
-<h3>Functions</h3>
-
-<table>
-
-<tr>
-<td><a href="#clearSavedHistories">clearSavedHistories</a></td>
-<td>Function to clear the saved history lists.</td>
-</tr>
-</table>
-<hr />
-<hr />
-<a NAME="QtTestResult" ID="QtTestResult"></a>
-<h2>QtTestResult</h2>
-
-<p>
-    A TestResult derivative to work with a graphical GUI.
-</p>
-<p>
-    For more details see pyunit.py of the standard Python distribution.
-</p>
-<h3>Derived from</h3>
-unittest.TestResult
-<h3>Class Attributes</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Class Methods</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Methods</h3>
-
-<table>
-
-<tr>
-<td><a href="#QtTestResult.__init__">QtTestResult</a></td>
-<td>Constructor</td>
-</tr>
-<tr>
-<td><a href="#QtTestResult.addError">addError</a></td>
-<td>Public method called if a test errored.</td>
-</tr>
-<tr>
-<td><a href="#QtTestResult.addExpectedFailure">addExpectedFailure</a></td>
-<td>Public method called if a test failed expected.</td>
-</tr>
-<tr>
-<td><a href="#QtTestResult.addFailure">addFailure</a></td>
-<td>Public method called if a test failed.</td>
-</tr>
-<tr>
-<td><a href="#QtTestResult.addSkip">addSkip</a></td>
-<td>Public method called if a test was skipped.</td>
-</tr>
-<tr>
-<td><a href="#QtTestResult.addSubTest">addSubTest</a></td>
-<td>Public method called for each subtest to record its result.</td>
-</tr>
-<tr>
-<td><a href="#QtTestResult.addUnexpectedSuccess">addUnexpectedSuccess</a></td>
-<td>Public method called if a test succeeded expectedly.</td>
-</tr>
-<tr>
-<td><a href="#QtTestResult.startTest">startTest</a></td>
-<td>Public method called at the start of a test.</td>
-</tr>
-<tr>
-<td><a href="#QtTestResult.stopTest">stopTest</a></td>
-<td>Public method called at the end of a test.</td>
-</tr>
-</table>
-<h3>Static Methods</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-
-<a NAME="QtTestResult.__init__" ID="QtTestResult.__init__"></a>
-<h4>QtTestResult (Constructor)</h4>
-<b>QtTestResult</b>(<i>parent, failfast</i>)
-
-<p>
-        Constructor
-</p>
-<dl>
-
-<dt><i>parent</i> (UnittestDialog)</dt>
-<dd>
-reference to the parent widget
-</dd>
-<dt><i>failfast</i> (bool)</dt>
-<dd>
-flag indicating to stop at the first error
-</dd>
-</dl>
-<a NAME="QtTestResult.addError" ID="QtTestResult.addError"></a>
-<h4>QtTestResult.addError</h4>
-<b>addError</b>(<i>test, err</i>)
-
-<p>
-        Public method called if a test errored.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-<dt><i>err</i></dt>
-<dd>
-error traceback
-</dd>
-</dl>
-<a NAME="QtTestResult.addExpectedFailure" ID="QtTestResult.addExpectedFailure"></a>
-<h4>QtTestResult.addExpectedFailure</h4>
-<b>addExpectedFailure</b>(<i>test, err</i>)
-
-<p>
-        Public method called if a test failed expected.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-<dt><i>err</i></dt>
-<dd>
-error traceback
-</dd>
-</dl>
-<a NAME="QtTestResult.addFailure" ID="QtTestResult.addFailure"></a>
-<h4>QtTestResult.addFailure</h4>
-<b>addFailure</b>(<i>test, err</i>)
-
-<p>
-        Public method called if a test failed.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-<dt><i>err</i></dt>
-<dd>
-error traceback
-</dd>
-</dl>
-<a NAME="QtTestResult.addSkip" ID="QtTestResult.addSkip"></a>
-<h4>QtTestResult.addSkip</h4>
-<b>addSkip</b>(<i>test, reason</i>)
-
-<p>
-        Public method called if a test was skipped.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-<dt><i>reason</i></dt>
-<dd>
-reason for skipping the test (string)
-</dd>
-</dl>
-<a NAME="QtTestResult.addSubTest" ID="QtTestResult.addSubTest"></a>
-<h4>QtTestResult.addSubTest</h4>
-<b>addSubTest</b>(<i>test, subtest, err</i>)
-
-<p>
-        Public method called for each subtest to record its result.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-<dt><i>subtest</i></dt>
-<dd>
-reference to the subtest object
-</dd>
-<dt><i>err</i></dt>
-<dd>
-error traceback
-</dd>
-</dl>
-<a NAME="QtTestResult.addUnexpectedSuccess" ID="QtTestResult.addUnexpectedSuccess"></a>
-<h4>QtTestResult.addUnexpectedSuccess</h4>
-<b>addUnexpectedSuccess</b>(<i>test</i>)
-
-<p>
-        Public method called if a test succeeded expectedly.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-reference to the test object
-</dd>
-</dl>
-<a NAME="QtTestResult.startTest" ID="QtTestResult.startTest"></a>
-<h4>QtTestResult.startTest</h4>
-<b>startTest</b>(<i>test</i>)
-
-<p>
-        Public method called at the start of a test.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-Reference to the test object
-</dd>
-</dl>
-<a NAME="QtTestResult.stopTest" ID="QtTestResult.stopTest"></a>
-<h4>QtTestResult.stopTest</h4>
-<b>stopTest</b>(<i>test</i>)
-
-<p>
-        Public method called at the end of a test.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-Reference to the test object
-</dd>
-</dl>
-<div align="right"><a href="#top">Up</a></div>
-<hr />
-<hr />
-<a NAME="UnittestDialog" ID="UnittestDialog"></a>
-<h2>UnittestDialog</h2>
-
-<p>
-    Class implementing the UI to the pyunit package.
-</p>
-<h3>Signals</h3>
-<dl>
-
-<dt>unittestFile(str, int, bool)</dt>
-<dd>
-emitted to show the source of a
-        unittest file
-</dd>
-<dt>unittestStopped()</dt>
-<dd>
-emitted after a unit test was run
-</dd>
-</dl>
-<h3>Derived from</h3>
-QWidget, Ui_UnittestDialog
-<h3>Class Attributes</h3>
-
-<table>
-<tr><td>ErrorsInfoRole</td></tr><tr><td>FailedExpectedColorDarkTheme</td></tr><tr><td>FailedExpectedColorLightTheme</td></tr><tr><td>SkippedColorDarkTheme</td></tr><tr><td>SkippedColorLightTheme</td></tr><tr><td>SucceededUnexpectedColorDarkTheme</td></tr><tr><td>SucceededUnexpectedColorLightTheme</td></tr><tr><td>TestCaseFileRole</td></tr><tr><td>TestCaseNameRole</td></tr>
-</table>
-<h3>Class Methods</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Methods</h3>
-
-<table>
-
-<tr>
-<td><a href="#UnittestDialog.__init__">UnittestDialog</a></td>
-<td>Constructor</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__UTDiscovered">__UTDiscovered</a></td>
-<td>Private slot to handle the utDiscovered signal.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__UTPrepared">__UTPrepared</a></td>
-<td>Private slot to handle the utPrepared signal.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__assembleTestCasesList">__assembleTestCasesList</a></td>
-<td>Private method to assemble a list of test cases included in a test suite.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__discover">__discover</a></td>
-<td>Private slot to discover unit test but don't run them.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__findDiscoveryItem">__findDiscoveryItem</a></td>
-<td>Private method to find an item given the module path.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__loadRecent">__loadRecent</a></td>
-<td>Private method to load the most recently used lists.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__openEditor">__openEditor</a></td>
-<td>Private method to open an editor window for the given file.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__populateDiscoveryResults">__populateDiscoveryResults</a></td>
-<td>Private method to populate the test discovery results list.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__populateVenvComboBox">__populateVenvComboBox</a></td>
-<td>Private method to (re-)populate the virtual environments selector.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__saveRecent">__saveRecent</a></td>
-<td>Private method to save the most recently used lists.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__selectedTestCases">__selectedTestCases</a></td>
-<td>Private method to assemble the list of selected test cases and suites.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__setProgressColor">__setProgressColor</a></td>
-<td>Private method to set the color of the progress color label.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__setRunningMode">__setRunningMode</a></td>
-<td>Private method to set the GUI in running mode.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__setStoppedMode">__setStoppedMode</a></td>
-<td>Private method to set the GUI in stopped mode.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__showSource">__showSource</a></td>
-<td>Private slot to show the source of a traceback in an eric editor.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.__stopTests">__stopTests</a></td>
-<td>Private slot to stop the test.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.clearRecent">clearRecent</a></td>
-<td>Public slot to clear the recently used lists.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.closeEvent">closeEvent</a></td>
-<td>Protected method to handle the close event.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.hasFailedTests">hasFailedTests</a></td>
-<td>Public method to check, if there are failed tests from the last run.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.insertDiscovery">insertDiscovery</a></td>
-<td>Public slot to insert the discovery start directory into the discoveryPicker object.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.insertProg">insertProg</a></td>
-<td>Public slot to insert the filename prog into the testsuitePicker object.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.insertTestName">insertTestName</a></td>
-<td>Public slot to insert a test name into the testComboBox object.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.keyPressEvent">keyPressEvent</a></td>
-<td>Protected slot to handle key press events.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.on_buttonBox_clicked">on_buttonBox_clicked</a></td>
-<td>Private slot called by a button of the button box clicked.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.on_discoverCheckBox_toggled">on_discoverCheckBox_toggled</a></td>
-<td>Private slot handling state changes of the 'discover' checkbox.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.on_discoveryList_itemChanged">on_discoveryList_itemChanged</a></td>
-<td>Private slot handling the user checking or unchecking an item.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.on_discoveryList_itemDoubleClicked">on_discoveryList_itemDoubleClicked</a></td>
-<td>Private slot handling the user double clicking an item.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.on_errorsListWidget_currentTextChanged">on_errorsListWidget_currentTextChanged</a></td>
-<td>Private slot to handle the highlighted signal.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.on_errorsListWidget_itemDoubleClicked">on_errorsListWidget_itemDoubleClicked</a></td>
-<td>Private slot called by doubleclicking an errorlist entry.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.on_testsuitePicker_aboutToShowPathPickerDialog">on_testsuitePicker_aboutToShowPathPickerDialog</a></td>
-<td>Private slot called before the test suite selection dialog is shown.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.on_testsuitePicker_editTextChanged">on_testsuitePicker_editTextChanged</a></td>
-<td>Private slot handling changes of the test suite path.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.on_testsuitePicker_pathSelected">on_testsuitePicker_pathSelected</a></td>
-<td>Private slot called after a test suite has been selected.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.setProjectMode">setProjectMode</a></td>
-<td>Public method to set the project mode of the dialog.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.startTests">startTests</a></td>
-<td>Public slot to start the test.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.testErrored">testErrored</a></td>
-<td>Public method called if a test errors.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.testFailed">testFailed</a></td>
-<td>Public method called if a test fails.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.testFailedExpected">testFailedExpected</a></td>
-<td>Public method called if a test fails as expected.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.testFinished">testFinished</a></td>
-<td>Public method called if a test has finished.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.testSkipped">testSkipped</a></td>
-<td>Public method called if a test was skipped.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.testStarted">testStarted</a></td>
-<td>Public method called if a test is about to be run.</td>
-</tr>
-<tr>
-<td><a href="#UnittestDialog.testSucceededUnexpected">testSucceededUnexpected</a></td>
-<td>Public method called if a test succeeds unexpectedly.</td>
-</tr>
-</table>
-<h3>Static Methods</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-
-<a NAME="UnittestDialog.__init__" ID="UnittestDialog.__init__"></a>
-<h4>UnittestDialog (Constructor)</h4>
-<b>UnittestDialog</b>(<i>prog=None, dbs=None, ui=None, parent=None, name=None</i>)
-
-<p>
-        Constructor
-</p>
-<dl>
-
-<dt><i>prog</i> (str)</dt>
-<dd>
-filename of the program to open
-</dd>
-<dt><i>dbs</i> (DebugServer)</dt>
-<dd>
-reference to the debug server object. It is an indication
-            whether we were called from within the eric IDE.
-</dd>
-<dt><i>ui</i> (UserInterface)</dt>
-<dd>
-reference to the UI object
-</dd>
-<dt><i>parent</i> (QWidget)</dt>
-<dd>
-parent widget of this dialog
-</dd>
-<dt><i>name</i> (str)</dt>
-<dd>
-name of this dialog
-</dd>
-</dl>
-<a NAME="UnittestDialog.__UTDiscovered" ID="UnittestDialog.__UTDiscovered"></a>
-<h4>UnittestDialog.__UTDiscovered</h4>
-<b>__UTDiscovered</b>(<i>testCases, exc_type, exc_value</i>)
-
-<p>
-        Private slot to handle the utDiscovered signal.
-</p>
-<p>
-        If the unittest suite was loaded successfully, we ask the
-        client to run the test suite.
-</p>
-<dl>
-
-<dt><i>testCases</i> (str)</dt>
-<dd>
-list of detected test cases
-</dd>
-<dt><i>exc_type</i> (str)</dt>
-<dd>
-exception type occured during discovery
-</dd>
-<dt><i>exc_value</i> (str)</dt>
-<dd>
-value of exception occured during discovery
-</dd>
-</dl>
-<a NAME="UnittestDialog.__UTPrepared" ID="UnittestDialog.__UTPrepared"></a>
-<h4>UnittestDialog.__UTPrepared</h4>
-<b>__UTPrepared</b>(<i>nrTests, exc_type, exc_value</i>)
-
-<p>
-        Private slot to handle the utPrepared signal.
-</p>
-<p>
-        If the unittest suite was loaded successfully, we ask the
-        client to run the test suite.
-</p>
-<dl>
-
-<dt><i>nrTests</i></dt>
-<dd>
-number of tests contained in the test suite (integer)
-</dd>
-<dt><i>exc_type</i></dt>
-<dd>
-type of exception occured during preparation (string)
-</dd>
-<dt><i>exc_value</i></dt>
-<dd>
-value of exception occured during preparation (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.__assembleTestCasesList" ID="UnittestDialog.__assembleTestCasesList"></a>
-<h4>UnittestDialog.__assembleTestCasesList</h4>
-<b>__assembleTestCasesList</b>(<i>suite, start</i>)
-
-<p>
-        Private method to assemble a list of test cases included in a test
-        suite.
-</p>
-<dl>
-
-<dt><i>suite</i> (unittest.TestSuite)</dt>
-<dd>
-test suite to be inspected
-</dd>
-<dt><i>start</i> (str)</dt>
-<dd>
-name of directory discovery was started at
-</dd>
-</dl>
-<dl>
-<dt>Return:</dt>
-<dd>
-list of tuples containing the test case ID, a short description
-            and the path of the test file name
-</dd>
-</dl>
-<dl>
-<dt>Return Type:</dt>
-<dd>
-list of tuples of (str, str, str)
-</dd>
-</dl>
-<a NAME="UnittestDialog.__discover" ID="UnittestDialog.__discover"></a>
-<h4>UnittestDialog.__discover</h4>
-<b>__discover</b>(<i></i>)
-
-<p>
-        Private slot to discover unit test but don't run them.
-</p>
-<a NAME="UnittestDialog.__findDiscoveryItem" ID="UnittestDialog.__findDiscoveryItem"></a>
-<h4>UnittestDialog.__findDiscoveryItem</h4>
-<b>__findDiscoveryItem</b>(<i>modulePath</i>)
-
-<p>
-        Private method to find an item given the module path.
-</p>
-<dl>
-
-<dt><i>modulePath</i> (str)</dt>
-<dd>
-path of the module in dotted notation
-</dd>
-</dl>
-<dl>
-<dt>Return:</dt>
-<dd>
-reference to the item or None
-</dd>
-</dl>
-<dl>
-<dt>Return Type:</dt>
-<dd>
-QTreeWidgetItem or None
-</dd>
-</dl>
-<a NAME="UnittestDialog.__loadRecent" ID="UnittestDialog.__loadRecent"></a>
-<h4>UnittestDialog.__loadRecent</h4>
-<b>__loadRecent</b>(<i></i>)
-
-<p>
-        Private method to load the most recently used lists.
-</p>
-<a NAME="UnittestDialog.__openEditor" ID="UnittestDialog.__openEditor"></a>
-<h4>UnittestDialog.__openEditor</h4>
-<b>__openEditor</b>(<i>filename, linenumber</i>)
-
-<p>
-        Private method to open an editor window for the given file.
-</p>
-<p>
-        Note: This method opens an editor window when the unittest dialog
-        is called as a standalone application.
-</p>
-<dl>
-
-<dt><i>filename</i> (str)</dt>
-<dd>
-path of the file to be opened
-</dd>
-<dt><i>linenumber</i> (int)</dt>
-<dd>
-line number to place the cursor at
-</dd>
-</dl>
-<a NAME="UnittestDialog.__populateDiscoveryResults" ID="UnittestDialog.__populateDiscoveryResults"></a>
-<h4>UnittestDialog.__populateDiscoveryResults</h4>
-<b>__populateDiscoveryResults</b>(<i>tests</i>)
-
-<p>
-        Private method to populate the test discovery results list.
-</p>
-<dl>
-
-<dt><i>tests</i> (list of tuples of (str, str, str))</dt>
-<dd>
-list of tuples containing the discovery results
-</dd>
-</dl>
-<a NAME="UnittestDialog.__populateVenvComboBox" ID="UnittestDialog.__populateVenvComboBox"></a>
-<h4>UnittestDialog.__populateVenvComboBox</h4>
-<b>__populateVenvComboBox</b>(<i></i>)
-
-<p>
-        Private method to (re-)populate the virtual environments selector.
-</p>
-<a NAME="UnittestDialog.__saveRecent" ID="UnittestDialog.__saveRecent"></a>
-<h4>UnittestDialog.__saveRecent</h4>
-<b>__saveRecent</b>(<i></i>)
-
-<p>
-        Private method to save the most recently used lists.
-</p>
-<a NAME="UnittestDialog.__selectedTestCases" ID="UnittestDialog.__selectedTestCases"></a>
-<h4>UnittestDialog.__selectedTestCases</h4>
-<b>__selectedTestCases</b>(<i>parent=None</i>)
-
-<p>
-        Private method to assemble the list of selected test cases and suites.
-</p>
-<dl>
-
-<dt><i>parent</i> (QTreeWidgetItem)</dt>
-<dd>
-reference to the parent item
-</dd>
-</dl>
-<dl>
-<dt>Return:</dt>
-<dd>
-list of selected test cases
-</dd>
-</dl>
-<dl>
-<dt>Return Type:</dt>
-<dd>
-list of str
-</dd>
-</dl>
-<a NAME="UnittestDialog.__setProgressColor" ID="UnittestDialog.__setProgressColor"></a>
-<h4>UnittestDialog.__setProgressColor</h4>
-<b>__setProgressColor</b>(<i>color</i>)
-
-<p>
-        Private method to set the color of the progress color label.
-</p>
-<dl>
-
-<dt><i>color</i></dt>
-<dd>
-colour to be shown (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.__setRunningMode" ID="UnittestDialog.__setRunningMode"></a>
-<h4>UnittestDialog.__setRunningMode</h4>
-<b>__setRunningMode</b>(<i></i>)
-
-<p>
-        Private method to set the GUI in running mode.
-</p>
-<a NAME="UnittestDialog.__setStoppedMode" ID="UnittestDialog.__setStoppedMode"></a>
-<h4>UnittestDialog.__setStoppedMode</h4>
-<b>__setStoppedMode</b>(<i></i>)
-
-<p>
-        Private method to set the GUI in stopped mode.
-</p>
-<a NAME="UnittestDialog.__showSource" ID="UnittestDialog.__showSource"></a>
-<h4>UnittestDialog.__showSource</h4>
-<b>__showSource</b>(<i></i>)
-
-<p>
-        Private slot to show the source of a traceback in an eric editor.
-</p>
-<a NAME="UnittestDialog.__stopTests" ID="UnittestDialog.__stopTests"></a>
-<h4>UnittestDialog.__stopTests</h4>
-<b>__stopTests</b>(<i></i>)
-
-<p>
-        Private slot to stop the test.
-</p>
-<a NAME="UnittestDialog.clearRecent" ID="UnittestDialog.clearRecent"></a>
-<h4>UnittestDialog.clearRecent</h4>
-<b>clearRecent</b>(<i></i>)
-
-<p>
-        Public slot to clear the recently used lists.
-</p>
-<a NAME="UnittestDialog.closeEvent" ID="UnittestDialog.closeEvent"></a>
-<h4>UnittestDialog.closeEvent</h4>
-<b>closeEvent</b>(<i>event</i>)
-
-<p>
-        Protected method to handle the close event.
-</p>
-<dl>
-
-<dt><i>event</i> (QCloseEvent)</dt>
-<dd>
-close event
-</dd>
-</dl>
-<a NAME="UnittestDialog.hasFailedTests" ID="UnittestDialog.hasFailedTests"></a>
-<h4>UnittestDialog.hasFailedTests</h4>
-<b>hasFailedTests</b>(<i></i>)
-
-<p>
-        Public method to check, if there are failed tests from the last run.
-</p>
-<dl>
-<dt>Return:</dt>
-<dd>
-flag indicating the presence of failed tests (boolean)
-</dd>
-</dl>
-<a NAME="UnittestDialog.insertDiscovery" ID="UnittestDialog.insertDiscovery"></a>
-<h4>UnittestDialog.insertDiscovery</h4>
-<b>insertDiscovery</b>(<i>start</i>)
-
-<p>
-        Public slot to insert the discovery start directory into the
-        discoveryPicker object.
-</p>
-<dl>
-
-<dt><i>start</i> (str)</dt>
-<dd>
-start directory name to be inserted
-</dd>
-</dl>
-<a NAME="UnittestDialog.insertProg" ID="UnittestDialog.insertProg"></a>
-<h4>UnittestDialog.insertProg</h4>
-<b>insertProg</b>(<i>prog</i>)
-
-<p>
-        Public slot to insert the filename prog into the testsuitePicker
-        object.
-</p>
-<dl>
-
-<dt><i>prog</i></dt>
-<dd>
-filename to be inserted (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.insertTestName" ID="UnittestDialog.insertTestName"></a>
-<h4>UnittestDialog.insertTestName</h4>
-<b>insertTestName</b>(<i>testName</i>)
-
-<p>
-        Public slot to insert a test name into the testComboBox object.
-</p>
-<dl>
-
-<dt><i>testName</i></dt>
-<dd>
-name of the test to be inserted (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.keyPressEvent" ID="UnittestDialog.keyPressEvent"></a>
-<h4>UnittestDialog.keyPressEvent</h4>
-<b>keyPressEvent</b>(<i>evt</i>)
-
-<p>
-        Protected slot to handle key press events.
-</p>
-<dl>
-
-<dt><i>evt</i></dt>
-<dd>
-key press event to handle (QKeyEvent)
-</dd>
-</dl>
-<a NAME="UnittestDialog.on_buttonBox_clicked" ID="UnittestDialog.on_buttonBox_clicked"></a>
-<h4>UnittestDialog.on_buttonBox_clicked</h4>
-<b>on_buttonBox_clicked</b>(<i>button</i>)
-
-<p>
-        Private slot called by a button of the button box clicked.
-</p>
-<dl>
-
-<dt><i>button</i></dt>
-<dd>
-button that was clicked (QAbstractButton)
-</dd>
-</dl>
-<a NAME="UnittestDialog.on_discoverCheckBox_toggled" ID="UnittestDialog.on_discoverCheckBox_toggled"></a>
-<h4>UnittestDialog.on_discoverCheckBox_toggled</h4>
-<b>on_discoverCheckBox_toggled</b>(<i>checked</i>)
-
-<p>
-        Private slot handling state changes of the 'discover' checkbox.
-</p>
-<dl>
-
-<dt><i>checked</i> (bool)</dt>
-<dd>
-state of the checkbox
-</dd>
-</dl>
-<a NAME="UnittestDialog.on_discoveryList_itemChanged" ID="UnittestDialog.on_discoveryList_itemChanged"></a>
-<h4>UnittestDialog.on_discoveryList_itemChanged</h4>
-<b>on_discoveryList_itemChanged</b>(<i>item, column</i>)
-
-<p>
-        Private slot handling the user checking or unchecking an item.
-</p>
-<dl>
-
-<dt><i>item</i> (QTreeWidgetItem)</dt>
-<dd>
-reference to the item
-</dd>
-<dt><i>column</i> (int)</dt>
-<dd>
-changed column
-</dd>
-</dl>
-<a NAME="UnittestDialog.on_discoveryList_itemDoubleClicked" ID="UnittestDialog.on_discoveryList_itemDoubleClicked"></a>
-<h4>UnittestDialog.on_discoveryList_itemDoubleClicked</h4>
-<b>on_discoveryList_itemDoubleClicked</b>(<i>item, column</i>)
-
-<p>
-        Private slot handling the user double clicking an item.
-</p>
-<dl>
-
-<dt><i>item</i> (QTreeWidgetItem)</dt>
-<dd>
-reference to the item
-</dd>
-<dt><i>column</i> (int)</dt>
-<dd>
-column of the double click
-</dd>
-</dl>
-<a NAME="UnittestDialog.on_errorsListWidget_currentTextChanged" ID="UnittestDialog.on_errorsListWidget_currentTextChanged"></a>
-<h4>UnittestDialog.on_errorsListWidget_currentTextChanged</h4>
-<b>on_errorsListWidget_currentTextChanged</b>(<i>text</i>)
-
-<p>
-        Private slot to handle the highlighted signal.
-</p>
-<dl>
-
-<dt><i>text</i></dt>
-<dd>
-current text (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.on_errorsListWidget_itemDoubleClicked" ID="UnittestDialog.on_errorsListWidget_itemDoubleClicked"></a>
-<h4>UnittestDialog.on_errorsListWidget_itemDoubleClicked</h4>
-<b>on_errorsListWidget_itemDoubleClicked</b>(<i>lbitem</i>)
-
-<p>
-        Private slot called by doubleclicking an errorlist entry.
-</p>
-<p>
-        It will popup a dialog showing the stacktrace.
-        If called from eric, an additional button is displayed
-        to show the python source in an eric source viewer (in
-        erics main window.
-</p>
-<dl>
-
-<dt><i>lbitem</i></dt>
-<dd>
-the listbox item that was double clicked
-</dd>
-</dl>
-<a NAME="UnittestDialog.on_testsuitePicker_aboutToShowPathPickerDialog" ID="UnittestDialog.on_testsuitePicker_aboutToShowPathPickerDialog"></a>
-<h4>UnittestDialog.on_testsuitePicker_aboutToShowPathPickerDialog</h4>
-<b>on_testsuitePicker_aboutToShowPathPickerDialog</b>(<i></i>)
-
-<p>
-        Private slot called before the test suite selection dialog is shown.
-</p>
-<a NAME="UnittestDialog.on_testsuitePicker_editTextChanged" ID="UnittestDialog.on_testsuitePicker_editTextChanged"></a>
-<h4>UnittestDialog.on_testsuitePicker_editTextChanged</h4>
-<b>on_testsuitePicker_editTextChanged</b>(<i>path</i>)
-
-<p>
-        Private slot handling changes of the test suite path.
-</p>
-<dl>
-
-<dt><i>path</i> (str)</dt>
-<dd>
-path of the test suite file
-</dd>
-</dl>
-<a NAME="UnittestDialog.on_testsuitePicker_pathSelected" ID="UnittestDialog.on_testsuitePicker_pathSelected"></a>
-<h4>UnittestDialog.on_testsuitePicker_pathSelected</h4>
-<b>on_testsuitePicker_pathSelected</b>(<i>suite</i>)
-
-<p>
-        Private slot called after a test suite has been selected.
-</p>
-<dl>
-
-<dt><i>suite</i> (str)</dt>
-<dd>
-file name of the test suite
-</dd>
-</dl>
-<a NAME="UnittestDialog.setProjectMode" ID="UnittestDialog.setProjectMode"></a>
-<h4>UnittestDialog.setProjectMode</h4>
-<b>setProjectMode</b>(<i>forProject</i>)
-
-<p>
-        Public method to set the project mode of the dialog.
-</p>
-<dl>
-
-<dt><i>forProject</i> (bool)</dt>
-<dd>
-flag indicating to run for the open project
-</dd>
-</dl>
-<a NAME="UnittestDialog.startTests" ID="UnittestDialog.startTests"></a>
-<h4>UnittestDialog.startTests</h4>
-<b>startTests</b>(<i>failedOnly=False</i>)
-
-<p>
-        Public slot to start the test.
-</p>
-<dl>
-
-<dt><i>failedOnly</i></dt>
-<dd>
-flag indicating to run only failed tests (boolean)
-</dd>
-</dl>
-<a NAME="UnittestDialog.testErrored" ID="UnittestDialog.testErrored"></a>
-<h4>UnittestDialog.testErrored</h4>
-<b>testErrored</b>(<i>test, exc, testId</i>)
-
-<p>
-        Public method called if a test errors.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-name of the test (string)
-</dd>
-<dt><i>exc</i></dt>
-<dd>
-string representation of the exception (string)
-</dd>
-<dt><i>testId</i></dt>
-<dd>
-id of the test (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.testFailed" ID="UnittestDialog.testFailed"></a>
-<h4>UnittestDialog.testFailed</h4>
-<b>testFailed</b>(<i>test, exc, testId</i>)
-
-<p>
-        Public method called if a test fails.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-name of the test (string)
-</dd>
-<dt><i>exc</i></dt>
-<dd>
-string representation of the exception (string)
-</dd>
-<dt><i>testId</i></dt>
-<dd>
-id of the test (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.testFailedExpected" ID="UnittestDialog.testFailedExpected"></a>
-<h4>UnittestDialog.testFailedExpected</h4>
-<b>testFailedExpected</b>(<i>test, exc, testId</i>)
-
-<p>
-        Public method called if a test fails as expected.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-name of the test (string)
-</dd>
-<dt><i>exc</i></dt>
-<dd>
-string representation of the exception (string)
-</dd>
-<dt><i>testId</i></dt>
-<dd>
-id of the test (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.testFinished" ID="UnittestDialog.testFinished"></a>
-<h4>UnittestDialog.testFinished</h4>
-<b>testFinished</b>(<i></i>)
-
-<p>
-        Public method called if a test has finished.
-</p>
-<p>
-        <b>Note</b>: It is also called if it has already failed or errored.
-</p>
-<a NAME="UnittestDialog.testSkipped" ID="UnittestDialog.testSkipped"></a>
-<h4>UnittestDialog.testSkipped</h4>
-<b>testSkipped</b>(<i>test, reason, testId</i>)
-
-<p>
-        Public method called if a test was skipped.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-name of the test (string)
-</dd>
-<dt><i>reason</i></dt>
-<dd>
-reason for skipping the test (string)
-</dd>
-<dt><i>testId</i></dt>
-<dd>
-id of the test (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.testStarted" ID="UnittestDialog.testStarted"></a>
-<h4>UnittestDialog.testStarted</h4>
-<b>testStarted</b>(<i>test, doc</i>)
-
-<p>
-        Public method called if a test is about to be run.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-name of the started test (string)
-</dd>
-<dt><i>doc</i></dt>
-<dd>
-documentation of the started test (string)
-</dd>
-</dl>
-<a NAME="UnittestDialog.testSucceededUnexpected" ID="UnittestDialog.testSucceededUnexpected"></a>
-<h4>UnittestDialog.testSucceededUnexpected</h4>
-<b>testSucceededUnexpected</b>(<i>test, testId</i>)
-
-<p>
-        Public method called if a test succeeds unexpectedly.
-</p>
-<dl>
-
-<dt><i>test</i></dt>
-<dd>
-name of the test (string)
-</dd>
-<dt><i>testId</i></dt>
-<dd>
-id of the test (string)
-</dd>
-</dl>
-<div align="right"><a href="#top">Up</a></div>
-<hr />
-<hr />
-<a NAME="UnittestWindow" ID="UnittestWindow"></a>
-<h2>UnittestWindow</h2>
-
-<p>
-    Main window class for the standalone dialog.
-</p>
-<h3>Derived from</h3>
-EricMainWindow
-<h3>Class Attributes</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Class Methods</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Methods</h3>
-
-<table>
-
-<tr>
-<td><a href="#UnittestWindow.__init__">UnittestWindow</a></td>
-<td>Constructor</td>
-</tr>
-<tr>
-<td><a href="#UnittestWindow.eventFilter">eventFilter</a></td>
-<td>Public method to filter events.</td>
-</tr>
-</table>
-<h3>Static Methods</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-
-<a NAME="UnittestWindow.__init__" ID="UnittestWindow.__init__"></a>
-<h4>UnittestWindow (Constructor)</h4>
-<b>UnittestWindow</b>(<i>prog=None, parent=None</i>)
-
-<p>
-        Constructor
-</p>
-<dl>
-
-<dt><i>prog</i></dt>
-<dd>
-filename of the program to open
-</dd>
-<dt><i>parent</i></dt>
-<dd>
-reference to the parent widget (QWidget)
-</dd>
-</dl>
-<a NAME="UnittestWindow.eventFilter" ID="UnittestWindow.eventFilter"></a>
-<h4>UnittestWindow.eventFilter</h4>
-<b>eventFilter</b>(<i>obj, event</i>)
-
-<p>
-        Public method to filter events.
-</p>
-<dl>
-
-<dt><i>obj</i></dt>
-<dd>
-reference to the object the event is meant for (QObject)
-</dd>
-<dt><i>event</i></dt>
-<dd>
-reference to the event object (QEvent)
-</dd>
-</dl>
-<dl>
-<dt>Return:</dt>
-<dd>
-flag indicating, whether the event was handled (boolean)
-</dd>
-</dl>
-<div align="right"><a href="#top">Up</a></div>
-<hr />
-<hr />
-<a NAME="clearSavedHistories" ID="clearSavedHistories"></a>
-<h2>clearSavedHistories</h2>
-<b>clearSavedHistories</b>(<i>self</i>)
-
-<p>
-    Function to clear the saved history lists.
-</p>
-<div align="right"><a href="#top">Up</a></div>
-<hr />
-</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.Testing.Interfaces.PytestExecutor.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,297 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.Interfaces.PytestExecutor</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.Testing.Interfaces.PytestExecutor</h1>
+
+<p>
+Module implementing the executor for the 'pytest' framework.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#PytestExecutor">PytestExecutor</a></td>
+<td>Class implementing the executor for the 'pytest' framework.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="PytestExecutor" ID="PytestExecutor"></a>
+<h2>PytestExecutor</h2>
+
+<p>
+    Class implementing the executor for the 'pytest' framework.
+</p>
+<h3>Derived from</h3>
+TestExecutorBase
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>module</td></tr><tr><td>name</td></tr><tr><td>runner</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#PytestExecutor.__init__">PytestExecutor</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#PytestExecutor.__nodeid2testname">__nodeid2testname</a></td>
+<td>Private method to convert a nodeid to a test name.</td>
+</tr>
+<tr>
+<td><a href="#PytestExecutor.__normalizeModuleName">__normalizeModuleName</a></td>
+<td>Private method to convert a module name reported by pytest to Python conventions.</td>
+</tr>
+<tr>
+<td><a href="#PytestExecutor.__processData">__processData</a></td>
+<td>Private slot to process the received data.</td>
+</tr>
+<tr>
+<td><a href="#PytestExecutor.createArguments">createArguments</a></td>
+<td>Public method to create the arguments needed to start the test process.</td>
+</tr>
+<tr>
+<td><a href="#PytestExecutor.finished">finished</a></td>
+<td>Public method handling the unit test process been finished.</td>
+</tr>
+<tr>
+<td><a href="#PytestExecutor.getVersions">getVersions</a></td>
+<td>Public method to get the test framework version and version information of its installed plugins.</td>
+</tr>
+<tr>
+<td><a href="#PytestExecutor.hasCoverage">hasCoverage</a></td>
+<td>Public method to get the test framework version and version information of its installed plugins.</td>
+</tr>
+<tr>
+<td><a href="#PytestExecutor.start">start</a></td>
+<td>Public method to start the testing process.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="PytestExecutor.__init__" ID="PytestExecutor.__init__"></a>
+<h4>PytestExecutor (Constructor)</h4>
+<b>PytestExecutor</b>(<i>testWidget</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>testWidget</i> (TestingWidget)</dt>
+<dd>
+reference to the unit test widget
+</dd>
+</dl>
+<a NAME="PytestExecutor.__nodeid2testname" ID="PytestExecutor.__nodeid2testname"></a>
+<h4>PytestExecutor.__nodeid2testname</h4>
+<b>__nodeid2testname</b>(<i>nodeid</i>)
+
+<p>
+        Private method to convert a nodeid to a test name.
+</p>
+<dl>
+
+<dt><i>nodeid</i> (str)</dt>
+<dd>
+nodeid to be converted
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+test name
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
+<a NAME="PytestExecutor.__normalizeModuleName" ID="PytestExecutor.__normalizeModuleName"></a>
+<h4>PytestExecutor.__normalizeModuleName</h4>
+<b>__normalizeModuleName</b>(<i>name</i>)
+
+<p>
+        Private method to convert a module name reported by pytest to Python
+        conventions.
+</p>
+<p>
+        This method strips the extensions '.pyw' and '.py' first and replaces
+        '/' and '\' thereafter.
+</p>
+<dl>
+
+<dt><i>name</i> (str)</dt>
+<dd>
+module name reported by pytest
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+module name iaw. Python conventions
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
+<a NAME="PytestExecutor.__processData" ID="PytestExecutor.__processData"></a>
+<h4>PytestExecutor.__processData</h4>
+<b>__processData</b>(<i>data</i>)
+
+<p>
+        Private slot to process the received data.
+</p>
+<dl>
+
+<dt><i>data</i> (dict)</dt>
+<dd>
+data object received
+</dd>
+</dl>
+<a NAME="PytestExecutor.createArguments" ID="PytestExecutor.createArguments"></a>
+<h4>PytestExecutor.createArguments</h4>
+<b>createArguments</b>(<i>config</i>)
+
+<p>
+        Public method to create the arguments needed to start the test process.
+</p>
+<dl>
+
+<dt><i>config</i> (TestConfig)</dt>
+<dd>
+configuration for the test execution
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of process arguments
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
+</dd>
+</dl>
+<a NAME="PytestExecutor.finished" ID="PytestExecutor.finished"></a>
+<h4>PytestExecutor.finished</h4>
+<b>finished</b>(<i></i>)
+
+<p>
+        Public method handling the unit test process been finished.
+</p>
+<p>
+        This method should read the results (if necessary) and emit the signal
+        testFinished.
+</p>
+<a NAME="PytestExecutor.getVersions" ID="PytestExecutor.getVersions"></a>
+<h4>PytestExecutor.getVersions</h4>
+<b>getVersions</b>(<i>interpreter</i>)
+
+<p>
+        Public method to get the test framework version and version information
+        of its installed plugins.
+</p>
+<dl>
+
+<dt><i>interpreter</i> (str)</dt>
+<dd>
+interpreter to be used for the test
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing the framework name and version and the
+            list of available plugins with name and version each
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
+</dd>
+</dl>
+<a NAME="PytestExecutor.hasCoverage" ID="PytestExecutor.hasCoverage"></a>
+<h4>PytestExecutor.hasCoverage</h4>
+<b>hasCoverage</b>(<i>interpreter</i>)
+
+<p>
+        Public method to get the test framework version and version information
+        of its installed plugins.
+</p>
+<dl>
+
+<dt><i>interpreter</i> (str)</dt>
+<dd>
+interpreter to be used for the test
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating the availability of coverage functionality
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="PytestExecutor.start" ID="PytestExecutor.start"></a>
+<h4>PytestExecutor.start</h4>
+<b>start</b>(<i>config, pythonpath</i>)
+
+<p>
+        Public method to start the testing process.
+</p>
+<dl>
+
+<dt><i>config</i> (TestConfig)</dt>
+<dd>
+configuration for the test execution
+</dd>
+<dt><i>pythonpath</i> (list of str)</dt>
+<dd>
+list of directories to be added to the Python path
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.Testing.Interfaces.PytestRunner.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,364 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.Interfaces.PytestRunner</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.Testing.Interfaces.PytestRunner</h1>
+
+<p>
+Module implementing the test runner script for the 'pytest' framework.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricPlugin">EricPlugin</a></td>
+<td>Class implementing a pytest plugin which reports the data in a format suitable for the PytestExecutor.</td>
+</tr>
+<tr>
+<td><a href="#GetPluginVersionsPlugin">GetPluginVersionsPlugin</a></td>
+<td>Class implementing a pytest plugin to extract the version info of all installed plugins.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+
+<tr>
+<td><a href="#getVersions">getVersions</a></td>
+<td>Function to determine the framework version and versions of all available plugins.</td>
+</tr>
+</table>
+<hr />
+<hr />
+<a NAME="EricPlugin" ID="EricPlugin"></a>
+<h2>EricPlugin</h2>
+
+<p>
+    Class implementing a pytest plugin which reports the data in a format
+    suitable for the PytestExecutor.
+</p>
+<h3>Derived from</h3>
+None
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricPlugin.__init__">EricPlugin</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#EricPlugin.__initializeReportData">__initializeReportData</a></td>
+<td>Private method to initialize attributes for data collection.</td>
+</tr>
+<tr>
+<td><a href="#EricPlugin.pytest_collectreport">pytest_collectreport</a></td>
+<td>Public method called by pytest after the tests have been collected.</td>
+</tr>
+<tr>
+<td><a href="#EricPlugin.pytest_itemcollected">pytest_itemcollected</a></td>
+<td>Public malled by pytest after a test item has been collected.</td>
+</tr>
+<tr>
+<td><a href="#EricPlugin.pytest_report_header">pytest_report_header</a></td>
+<td>Public method called by pytest before any reporting.</td>
+</tr>
+<tr>
+<td><a href="#EricPlugin.pytest_runtest_logfinish">pytest_runtest_logfinish</a></td>
+<td>Public method called by pytest after a test has been completed.</td>
+</tr>
+<tr>
+<td><a href="#EricPlugin.pytest_runtest_logreport">pytest_runtest_logreport</a></td>
+<td>Public method called by pytest when a test phase (setup, call and teardown) has been completed.</td>
+</tr>
+<tr>
+<td><a href="#EricPlugin.pytest_runtest_logstart">pytest_runtest_logstart</a></td>
+<td>Public method called by pytest before running a test.</td>
+</tr>
+<tr>
+<td><a href="#EricPlugin.pytest_sessionfinish">pytest_sessionfinish</a></td>
+<td>Public method called by pytest after the whole test run finished.</td>
+</tr>
+<tr>
+<td><a href="#EricPlugin.pytest_sessionstart">pytest_sessionstart</a></td>
+<td>Public method called by pytest before performing collection and entering the run test loop.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="EricPlugin.__init__" ID="EricPlugin.__init__"></a>
+<h4>EricPlugin (Constructor)</h4>
+<b>EricPlugin</b>(<i>writer</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>writer</i> (EricJsonWriter)</dt>
+<dd>
+reference to the object to write the results to
+</dd>
+</dl>
+<a NAME="EricPlugin.__initializeReportData" ID="EricPlugin.__initializeReportData"></a>
+<h4>EricPlugin.__initializeReportData</h4>
+<b>__initializeReportData</b>(<i></i>)
+
+<p>
+        Private method to initialize attributes for data collection.
+</p>
+<a NAME="EricPlugin.pytest_collectreport" ID="EricPlugin.pytest_collectreport"></a>
+<h4>EricPlugin.pytest_collectreport</h4>
+<b>pytest_collectreport</b>(<i>report</i>)
+
+<p>
+        Public method called by pytest after the tests have been collected.
+</p>
+<dl>
+
+<dt><i>report</i> (CollectReport)</dt>
+<dd>
+reference to the report object
+</dd>
+</dl>
+<a NAME="EricPlugin.pytest_itemcollected" ID="EricPlugin.pytest_itemcollected"></a>
+<h4>EricPlugin.pytest_itemcollected</h4>
+<b>pytest_itemcollected</b>(<i>item</i>)
+
+<p>
+        Public malled by pytest after a test item has been collected.
+</p>
+<dl>
+
+<dt><i>item</i> (Item)</dt>
+<dd>
+reference to the collected test item
+</dd>
+</dl>
+<a NAME="EricPlugin.pytest_report_header" ID="EricPlugin.pytest_report_header"></a>
+<h4>EricPlugin.pytest_report_header</h4>
+<b>pytest_report_header</b>(<i>config, startdir</i>)
+
+<p>
+        Public method called by pytest before any reporting.
+</p>
+<dl>
+
+<dt><i>config</i> (Config)</dt>
+<dd>
+reference to the configuration object
+</dd>
+<dt><i>startdir</i> (LocalPath)</dt>
+<dd>
+starting directory
+</dd>
+</dl>
+<a NAME="EricPlugin.pytest_runtest_logfinish" ID="EricPlugin.pytest_runtest_logfinish"></a>
+<h4>EricPlugin.pytest_runtest_logfinish</h4>
+<b>pytest_runtest_logfinish</b>(<i>nodeid, location</i>)
+
+<p>
+        Public method called by pytest after a test has been completed.
+</p>
+<dl>
+
+<dt><i>nodeid</i> (str)</dt>
+<dd>
+node id of the test item
+</dd>
+<dt><i>location</i> (tuple of (str, int, str))</dt>
+<dd>
+tuple containing the file name, the line number and
+            the test name
+</dd>
+</dl>
+<a NAME="EricPlugin.pytest_runtest_logreport" ID="EricPlugin.pytest_runtest_logreport"></a>
+<h4>EricPlugin.pytest_runtest_logreport</h4>
+<b>pytest_runtest_logreport</b>(<i>report</i>)
+
+<p>
+        Public method called by pytest when a test phase (setup, call and
+            teardown) has been completed.
+</p>
+<dl>
+
+<dt><i>report</i> (TestReport)</dt>
+<dd>
+reference to the test report object
+</dd>
+</dl>
+<a NAME="EricPlugin.pytest_runtest_logstart" ID="EricPlugin.pytest_runtest_logstart"></a>
+<h4>EricPlugin.pytest_runtest_logstart</h4>
+<b>pytest_runtest_logstart</b>(<i>nodeid, location</i>)
+
+<p>
+        Public method called by pytest before running a test.
+</p>
+<dl>
+
+<dt><i>nodeid</i> (str)</dt>
+<dd>
+node id of the test item
+</dd>
+<dt><i>location</i> (tuple of (str, int, str))</dt>
+<dd>
+tuple containing the file name, the line number and
+            the test name
+</dd>
+</dl>
+<a NAME="EricPlugin.pytest_sessionfinish" ID="EricPlugin.pytest_sessionfinish"></a>
+<h4>EricPlugin.pytest_sessionfinish</h4>
+<b>pytest_sessionfinish</b>(<i>session, exitstatus</i>)
+
+<p>
+        Public method called by pytest after the whole test run finished.
+</p>
+<dl>
+
+<dt><i>session</i> (Session)</dt>
+<dd>
+reference to the session object
+</dd>
+<dt><i>exitstatus</i> (int or ExitCode)</dt>
+<dd>
+exit status
+</dd>
+</dl>
+<a NAME="EricPlugin.pytest_sessionstart" ID="EricPlugin.pytest_sessionstart"></a>
+<h4>EricPlugin.pytest_sessionstart</h4>
+<b>pytest_sessionstart</b>(<i>session</i>)
+
+<p>
+        Public method called by pytest before performing collection and
+        entering the run test loop.
+</p>
+<dl>
+
+<dt><i>session</i> (Session)</dt>
+<dd>
+reference to the session object
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="GetPluginVersionsPlugin" ID="GetPluginVersionsPlugin"></a>
+<h2>GetPluginVersionsPlugin</h2>
+
+<p>
+    Class implementing a pytest plugin to extract the version info of all
+    installed plugins.
+</p>
+<h3>Derived from</h3>
+None
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#GetPluginVersionsPlugin.__init__">GetPluginVersionsPlugin</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#GetPluginVersionsPlugin.getVersions">getVersions</a></td>
+<td>Public method to get the assembled list of plugin versions.</td>
+</tr>
+<tr>
+<td><a href="#GetPluginVersionsPlugin.pytest_cmdline_main">pytest_cmdline_main</a></td>
+<td>Public method called for performing the main command line action.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="GetPluginVersionsPlugin.__init__" ID="GetPluginVersionsPlugin.__init__"></a>
+<h4>GetPluginVersionsPlugin (Constructor)</h4>
+<b>GetPluginVersionsPlugin</b>(<i></i>)
+
+<p>
+        Constructor
+</p>
+<a NAME="GetPluginVersionsPlugin.getVersions" ID="GetPluginVersionsPlugin.getVersions"></a>
+<h4>GetPluginVersionsPlugin.getVersions</h4>
+<b>getVersions</b>(<i></i>)
+
+<p>
+        Public method to get the assembled list of plugin versions.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of collected plugin versions
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of dict
+</dd>
+</dl>
+<a NAME="GetPluginVersionsPlugin.pytest_cmdline_main" ID="GetPluginVersionsPlugin.pytest_cmdline_main"></a>
+<h4>GetPluginVersionsPlugin.pytest_cmdline_main</h4>
+<b>pytest_cmdline_main</b>(<i>config</i>)
+
+<p>
+        Public method called for performing the main command line action.
+</p>
+<dl>
+
+<dt><i>config</i> (Config)</dt>
+<dd>
+pytest config object
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="getVersions" ID="getVersions"></a>
+<h2>getVersions</h2>
+<b>getVersions</b>(<i></i>)
+
+<p>
+    Function to determine the framework version and versions of all available
+    plugins.
+</p>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.Testing.Interfaces.TestExecutorBase.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,520 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.Interfaces.TestExecutorBase</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.Testing.Interfaces.TestExecutorBase</h1>
+
+<p>
+Module implementing the executor base class for the various testing frameworks
+and supporting classes.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestConfig">TestConfig</a></td>
+<td>Class containing the test run configuration.</td>
+</tr>
+<tr>
+<td><a href="#TestExecutorBase">TestExecutorBase</a></td>
+<td>Base class for test framework specific implementations.</td>
+</tr>
+<tr>
+<td><a href="#TestResult">TestResult</a></td>
+<td>Class containing the test result data.</td>
+</tr>
+<tr>
+<td><a href="#TestResultCategory">TestResultCategory</a></td>
+<td>Class defining the supported result categories.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="TestConfig" ID="TestConfig"></a>
+<h2>TestConfig</h2>
+
+<p>
+    Class containing the test run configuration.
+</p>
+<h3>Derived from</h3>
+None
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="TestExecutorBase" ID="TestExecutorBase"></a>
+<h2>TestExecutorBase</h2>
+
+<p>
+    Base class for test framework specific implementations.
+</p>
+<h3>Signals</h3>
+<dl>
+
+<dt>collectError(list of tuple of (str, str)</dt>
+<dd>
+) emitted when errors
+        are encountered during test collection. Tuple elements are the
+        test name and the error message.
+</dd>
+<dt>collected(list of tuple of (str, str, str)</dt>
+<dd>
+) emitted after all tests
+        have been collected. Tuple elements are the test id, the test name and
+        a short description of the test.
+</dd>
+<dt>coverageDataSaved(str)</dt>
+<dd>
+emitted after the coverage data was saved.
+        The element is the absolute path of the coverage data file.
+</dd>
+<dt>startTest(tuple of (str, str, str)</dt>
+<dd>
+emitted before tests are run.
+        Tuple elements are test id, test name and short description.
+</dd>
+<dt>stop()</dt>
+<dd>
+emitted when the test process is being stopped.
+</dd>
+<dt>testFinished(list, str)</dt>
+<dd>
+emitted when the test has finished.
+        The elements are the list of test results and the captured output
+        of the test worker (if any).
+</dd>
+<dt>testResult(TestResult)</dt>
+<dd>
+emitted when a test result is ready
+</dd>
+<dt>testRunAboutToBeStarted()</dt>
+<dd>
+emitted just before the test run will
+        be started.
+</dd>
+<dt>testRunFinished(int, float)</dt>
+<dd>
+emitted when the test run has finished.
+        The elements are the number of tests run and the duration in seconds
+</dd>
+</dl>
+<h3>Derived from</h3>
+QObject
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>module</td></tr><tr><td>name</td></tr><tr><td>runner</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestExecutorBase.isInstalled">isInstalled</a></td>
+<td>Class method to check whether a test framework is installed.</td>
+</tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestExecutorBase.__init__">TestExecutorBase</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#TestExecutorBase._prepareProcess">_prepareProcess</a></td>
+<td>Protected method to prepare a process object to be started.</td>
+</tr>
+<tr>
+<td><a href="#TestExecutorBase.createArguments">createArguments</a></td>
+<td>Public method to create the arguments needed to start the test process.</td>
+</tr>
+<tr>
+<td><a href="#TestExecutorBase.finished">finished</a></td>
+<td>Public method handling the unit test process been finished.</td>
+</tr>
+<tr>
+<td><a href="#TestExecutorBase.getVersions">getVersions</a></td>
+<td>Public method to get the test framework version and version information of its installed plugins.</td>
+</tr>
+<tr>
+<td><a href="#TestExecutorBase.hasCoverage">hasCoverage</a></td>
+<td>Public method to get the test framework version and version information of its installed plugins.</td>
+</tr>
+<tr>
+<td><a href="#TestExecutorBase.readAllOutput">readAllOutput</a></td>
+<td>Public method to read all output of the test process.</td>
+</tr>
+<tr>
+<td><a href="#TestExecutorBase.start">start</a></td>
+<td>Public method to start the testing process.</td>
+</tr>
+<tr>
+<td><a href="#TestExecutorBase.stopIfRunning">stopIfRunning</a></td>
+<td>Public method to stop the testing process, if it is running.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="TestExecutorBase.isInstalled" ID="TestExecutorBase.isInstalled"></a>
+<h4>TestExecutorBase.isInstalled (class method)</h4>
+<b>isInstalled</b>(<i>interpreter</i>)
+
+<p>
+        Class method to check whether a test framework is installed.
+</p>
+<p>
+        The test is performed by checking, if a module loader can found.
+</p>
+<dl>
+
+<dt><i>interpreter</i> (str)</dt>
+<dd>
+interpreter to be used for the test
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating the test framework module is installed
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="TestExecutorBase.__init__" ID="TestExecutorBase.__init__"></a>
+<h4>TestExecutorBase (Constructor)</h4>
+<b>TestExecutorBase</b>(<i>testWidget</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>testWidget</i> (TestingWidget)</dt>
+<dd>
+reference to the unit test widget
+</dd>
+</dl>
+<a NAME="TestExecutorBase._prepareProcess" ID="TestExecutorBase._prepareProcess"></a>
+<h4>TestExecutorBase._prepareProcess</h4>
+<b>_prepareProcess</b>(<i>workDir, pythonpath</i>)
+
+<p>
+        Protected method to prepare a process object to be started.
+</p>
+<dl>
+
+<dt><i>workDir</i> (str)</dt>
+<dd>
+working directory
+</dd>
+<dt><i>pythonpath</i> (list of str)</dt>
+<dd>
+list of directories to be added to the Python path
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+prepared process object
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QProcess
+</dd>
+</dl>
+<a NAME="TestExecutorBase.createArguments" ID="TestExecutorBase.createArguments"></a>
+<h4>TestExecutorBase.createArguments</h4>
+<b>createArguments</b>(<i>config</i>)
+
+<p>
+        Public method to create the arguments needed to start the test process.
+</p>
+<dl>
+
+<dt><i>config</i> (TestConfig)</dt>
+<dd>
+configuration for the test execution
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of process arguments
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+this method needs to be implemented by
+            derived classes
+</dd>
+</dl>
+<a NAME="TestExecutorBase.finished" ID="TestExecutorBase.finished"></a>
+<h4>TestExecutorBase.finished</h4>
+<b>finished</b>(<i></i>)
+
+<p>
+        Public method handling the unit test process been finished.
+</p>
+<p>
+        This method should read the results (if necessary) and emit the signal
+        testFinished.
+</p>
+<dl>
+
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+this method needs to be implemented by
+            derived classes
+</dd>
+</dl>
+<a NAME="TestExecutorBase.getVersions" ID="TestExecutorBase.getVersions"></a>
+<h4>TestExecutorBase.getVersions</h4>
+<b>getVersions</b>(<i>interpreter</i>)
+
+<p>
+        Public method to get the test framework version and version information
+        of its installed plugins.
+</p>
+<dl>
+
+<dt><i>interpreter</i> (str)</dt>
+<dd>
+interpreter to be used for the test
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing the framework name and version and the
+            list of available plugins with name and version each
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+this method needs to be implemented by
+            derived classes
+</dd>
+</dl>
+<a NAME="TestExecutorBase.hasCoverage" ID="TestExecutorBase.hasCoverage"></a>
+<h4>TestExecutorBase.hasCoverage</h4>
+<b>hasCoverage</b>(<i>interpreter</i>)
+
+<p>
+        Public method to get the test framework version and version information
+        of its installed plugins.
+</p>
+<dl>
+
+<dt><i>interpreter</i> (str)</dt>
+<dd>
+interpreter to be used for the test
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating the availability of coverage functionality
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>NotImplementedError</b>:</dt>
+<dd>
+this method needs to be implemented by
+            derived classes
+</dd>
+</dl>
+<a NAME="TestExecutorBase.readAllOutput" ID="TestExecutorBase.readAllOutput"></a>
+<h4>TestExecutorBase.readAllOutput</h4>
+<b>readAllOutput</b>(<i>process=None</i>)
+
+<p>
+        Public method to read all output of the test process.
+</p>
+<dl>
+
+<dt><i>process</i> (QProcess)</dt>
+<dd>
+reference to the process object
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+test process output
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
+<a NAME="TestExecutorBase.start" ID="TestExecutorBase.start"></a>
+<h4>TestExecutorBase.start</h4>
+<b>start</b>(<i>config, pythonpath</i>)
+
+<p>
+        Public method to start the testing process.
+</p>
+<dl>
+
+<dt><i>config</i> (TestConfig)</dt>
+<dd>
+configuration for the test execution
+</dd>
+<dt><i>pythonpath</i> (list of str)</dt>
+<dd>
+list of directories to be added to the Python path
+</dd>
+</dl>
+<dl>
+
+<dt>Raises <b>RuntimeError</b>:</dt>
+<dd>
+raised if the the testing process did not start
+</dd>
+</dl>
+<a NAME="TestExecutorBase.stopIfRunning" ID="TestExecutorBase.stopIfRunning"></a>
+<h4>TestExecutorBase.stopIfRunning</h4>
+<b>stopIfRunning</b>(<i></i>)
+
+<p>
+        Public method to stop the testing process, if it is running.
+</p>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="TestResult" ID="TestResult"></a>
+<h2>TestResult</h2>
+
+<p>
+    Class containing the test result data.
+</p>
+<h3>Derived from</h3>
+None
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="TestResultCategory" ID="TestResultCategory"></a>
+<h2>TestResultCategory</h2>
+
+<p>
+    Class defining the supported result categories.
+</p>
+<h3>Derived from</h3>
+IntEnum
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>FAIL</td></tr><tr><td>OK</td></tr><tr><td>PENDING</td></tr><tr><td>RUNNING</td></tr><tr><td>SKIP</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.Testing.Interfaces.TestFrameworkRegistry.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.Interfaces.TestFrameworkRegistry</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.Testing.Interfaces.TestFrameworkRegistry</h1>
+
+<p>
+Module implementing a simple registry containing the available test framework
+interfaces.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestFrameworkRegistry">TestFrameworkRegistry</a></td>
+<td>Class implementing a simple registry of test framework interfaces.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="TestFrameworkRegistry" ID="TestFrameworkRegistry"></a>
+<h2>TestFrameworkRegistry</h2>
+
+<p>
+    Class implementing a simple registry of test framework interfaces.
+</p>
+<p>
+    The test executor for a framework is responsible for running the tests,
+    receiving the results and preparing them for display. It must implement
+    the interface of TestExecutorBase.
+</p>
+<p>
+    Frameworks must first be registered using '.register()'. This registry
+    can then create the assoicated test executor when '.createExecutor()' is
+    called.
+</p>
+<h3>Derived from</h3>
+None
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestFrameworkRegistry.__init__">TestFrameworkRegistry</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#TestFrameworkRegistry.createExecutor">createExecutor</a></td>
+<td>Public method to create a test framework executor.</td>
+</tr>
+<tr>
+<td><a href="#TestFrameworkRegistry.getFrameworks">getFrameworks</a></td>
+<td>Public method to get a copy of the registered frameworks.</td>
+</tr>
+<tr>
+<td><a href="#TestFrameworkRegistry.register">register</a></td>
+<td>Public method to register a test framework executor.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="TestFrameworkRegistry.__init__" ID="TestFrameworkRegistry.__init__"></a>
+<h4>TestFrameworkRegistry (Constructor)</h4>
+<b>TestFrameworkRegistry</b>(<i></i>)
+
+<p>
+        Constructor
+</p>
+<a NAME="TestFrameworkRegistry.createExecutor" ID="TestFrameworkRegistry.createExecutor"></a>
+<h4>TestFrameworkRegistry.createExecutor</h4>
+<b>createExecutor</b>(<i>framework, widget</i>)
+
+<p>
+        Public method to create a test framework executor.
+</p>
+<p>
+        Note: The executor classes have to be registered first.
+</p>
+<dl>
+
+<dt><i>framework</i> (str)</dt>
+<dd>
+name of the test framework
+</dd>
+<dt><i>widget</i> (TestingWidget)</dt>
+<dd>
+reference to the unit test widget
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+test framework executor object
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+TestExecutorBase
+</dd>
+</dl>
+<a NAME="TestFrameworkRegistry.getFrameworks" ID="TestFrameworkRegistry.getFrameworks"></a>
+<h4>TestFrameworkRegistry.getFrameworks</h4>
+<b>getFrameworks</b>(<i></i>)
+
+<p>
+        Public method to get a copy of the registered frameworks.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+copy of the registered frameworks
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
+</dd>
+</dl>
+<a NAME="TestFrameworkRegistry.register" ID="TestFrameworkRegistry.register"></a>
+<h4>TestFrameworkRegistry.register</h4>
+<b>register</b>(<i>executorClass</i>)
+
+<p>
+        Public method to register a test framework executor.
+</p>
+<dl>
+
+<dt><i>executorClass</i> (TestExecutorBase)</dt>
+<dd>
+class implementing the test framework executor
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.Testing.Interfaces.UnittestExecutor.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,232 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.Interfaces.UnittestExecutor</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.Testing.Interfaces.UnittestExecutor</h1>
+
+<p>
+Module implementing the executor for the standard 'unittest' framework.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#UnittestExecutor">UnittestExecutor</a></td>
+<td>Class implementing the executor for the standard 'unittest' framework.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="UnittestExecutor" ID="UnittestExecutor"></a>
+<h2>UnittestExecutor</h2>
+
+<p>
+    Class implementing the executor for the standard 'unittest' framework.
+</p>
+<h3>Derived from</h3>
+TestExecutorBase
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>module</td></tr><tr><td>name</td></tr><tr><td>runner</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#UnittestExecutor.__init__">UnittestExecutor</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#UnittestExecutor.__processData">__processData</a></td>
+<td>Private slot to process the received data.</td>
+</tr>
+<tr>
+<td><a href="#UnittestExecutor.createArguments">createArguments</a></td>
+<td>Public method to create the arguments needed to start the test process.</td>
+</tr>
+<tr>
+<td><a href="#UnittestExecutor.finished">finished</a></td>
+<td>Public method handling the unit test process been finished.</td>
+</tr>
+<tr>
+<td><a href="#UnittestExecutor.getVersions">getVersions</a></td>
+<td>Public method to get the test framework version and version information of its installed plugins.</td>
+</tr>
+<tr>
+<td><a href="#UnittestExecutor.hasCoverage">hasCoverage</a></td>
+<td>Public method to get the test framework version and version information of its installed plugins.</td>
+</tr>
+<tr>
+<td><a href="#UnittestExecutor.start">start</a></td>
+<td>Public method to start the testing process.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="UnittestExecutor.__init__" ID="UnittestExecutor.__init__"></a>
+<h4>UnittestExecutor (Constructor)</h4>
+<b>UnittestExecutor</b>(<i>testWidget</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>testWidget</i> (TestingWidget)</dt>
+<dd>
+reference to the unit test widget
+</dd>
+</dl>
+<a NAME="UnittestExecutor.__processData" ID="UnittestExecutor.__processData"></a>
+<h4>UnittestExecutor.__processData</h4>
+<b>__processData</b>(<i>data</i>)
+
+<p>
+        Private slot to process the received data.
+</p>
+<dl>
+
+<dt><i>data</i> (dict)</dt>
+<dd>
+data object received
+</dd>
+</dl>
+<a NAME="UnittestExecutor.createArguments" ID="UnittestExecutor.createArguments"></a>
+<h4>UnittestExecutor.createArguments</h4>
+<b>createArguments</b>(<i>config</i>)
+
+<p>
+        Public method to create the arguments needed to start the test process.
+</p>
+<dl>
+
+<dt><i>config</i> (TestConfig)</dt>
+<dd>
+configuration for the test execution
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of process arguments
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
+</dd>
+</dl>
+<a NAME="UnittestExecutor.finished" ID="UnittestExecutor.finished"></a>
+<h4>UnittestExecutor.finished</h4>
+<b>finished</b>(<i></i>)
+
+<p>
+        Public method handling the unit test process been finished.
+</p>
+<p>
+        This method should read the results (if necessary) and emit the signal
+        testFinished.
+</p>
+<a NAME="UnittestExecutor.getVersions" ID="UnittestExecutor.getVersions"></a>
+<h4>UnittestExecutor.getVersions</h4>
+<b>getVersions</b>(<i>interpreter</i>)
+
+<p>
+        Public method to get the test framework version and version information
+        of its installed plugins.
+</p>
+<dl>
+
+<dt><i>interpreter</i> (str)</dt>
+<dd>
+interpreter to be used for the test
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing the framework name and version and the
+            list of available plugins with name and version each
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
+</dd>
+</dl>
+<a NAME="UnittestExecutor.hasCoverage" ID="UnittestExecutor.hasCoverage"></a>
+<h4>UnittestExecutor.hasCoverage</h4>
+<b>hasCoverage</b>(<i>interpreter</i>)
+
+<p>
+        Public method to get the test framework version and version information
+        of its installed plugins.
+</p>
+<dl>
+
+<dt><i>interpreter</i> (str)</dt>
+<dd>
+interpreter to be used for the test
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating the availability of coverage functionality
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="UnittestExecutor.start" ID="UnittestExecutor.start"></a>
+<h4>UnittestExecutor.start</h4>
+<b>start</b>(<i>config, pythonpath</i>)
+
+<p>
+        Public method to start the testing process.
+</p>
+<dl>
+
+<dt><i>config</i> (TestConfig)</dt>
+<dd>
+configuration for the test execution
+</dd>
+<dt><i>pythonpath</i> (list of str)</dt>
+<dd>
+list of directories to be added to the Python path
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.Testing.Interfaces.UnittestRunner.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,339 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.Interfaces.UnittestRunner</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.Testing.Interfaces.UnittestRunner</h1>
+
+<p>
+Module implementing the test runner script for the 'unittest' framework.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricTestResult">EricTestResult</a></td>
+<td>Class implementing a TestResult derivative to send the data via a network connection.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+
+<tr>
+<td><a href="#_assembleTestCasesList">_assembleTestCasesList</a></td>
+<td>Protected function to assemble a list of test cases included in a test suite.</td>
+</tr>
+<tr>
+<td><a href="#runtest">runtest</a></td>
+<td>Function to run the tests.</td>
+</tr>
+</table>
+<hr />
+<hr />
+<a NAME="EricTestResult" ID="EricTestResult"></a>
+<h2>EricTestResult</h2>
+
+<p>
+    Class implementing a TestResult derivative to send the data via a network
+    connection.
+</p>
+<h3>Derived from</h3>
+unittest.TestResult
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#EricTestResult.__init__">EricTestResult</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.addError">addError</a></td>
+<td>Public method called if a test errored.</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.addExpectedFailure">addExpectedFailure</a></td>
+<td>Public method called if a test failed expected.</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.addFailure">addFailure</a></td>
+<td>Public method called if a test failed.</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.addSkip">addSkip</a></td>
+<td>Public method called if a test was skipped.</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.addSubTest">addSubTest</a></td>
+<td>Public method called for each subtest to record its result.</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.addUnexpectedSuccess">addUnexpectedSuccess</a></td>
+<td>Public method called if a test succeeded expectedly.</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.startTest">startTest</a></td>
+<td>Public method called at the start of a test.</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.startTestRun">startTestRun</a></td>
+<td>Public method called once before any tests are executed.</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.stopTest">stopTest</a></td>
+<td>Public method called at the end of a test.</td>
+</tr>
+<tr>
+<td><a href="#EricTestResult.stopTestRun">stopTestRun</a></td>
+<td>Public method called once after all tests are executed.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="EricTestResult.__init__" ID="EricTestResult.__init__"></a>
+<h4>EricTestResult (Constructor)</h4>
+<b>EricTestResult</b>(<i>writer, failfast</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>writer</i> (EricJsonWriter)</dt>
+<dd>
+reference to the object to write the results to
+</dd>
+<dt><i>failfast</i> (bool)</dt>
+<dd>
+flag indicating to stop at the first error
+</dd>
+</dl>
+<a NAME="EricTestResult.addError" ID="EricTestResult.addError"></a>
+<h4>EricTestResult.addError</h4>
+<b>addError</b>(<i>test, err</i>)
+
+<p>
+        Public method called if a test errored.
+</p>
+<dl>
+
+<dt><i>test</i> (TestCase)</dt>
+<dd>
+reference to the test object
+</dd>
+<dt><i>err</i> (tuple)</dt>
+<dd>
+tuple containing the exception data like sys.exc_info
+            (exception type, exception instance, traceback)
+</dd>
+</dl>
+<a NAME="EricTestResult.addExpectedFailure" ID="EricTestResult.addExpectedFailure"></a>
+<h4>EricTestResult.addExpectedFailure</h4>
+<b>addExpectedFailure</b>(<i>test, err</i>)
+
+<p>
+        Public method called if a test failed expected.
+</p>
+<dl>
+
+<dt><i>test</i> (TestCase)</dt>
+<dd>
+reference to the test object
+</dd>
+<dt><i>err</i> (tuple)</dt>
+<dd>
+tuple containing the exception data like sys.exc_info
+            (exception type, exception instance, traceback)
+</dd>
+</dl>
+<a NAME="EricTestResult.addFailure" ID="EricTestResult.addFailure"></a>
+<h4>EricTestResult.addFailure</h4>
+<b>addFailure</b>(<i>test, err</i>)
+
+<p>
+        Public method called if a test failed.
+</p>
+<dl>
+
+<dt><i>test</i> (TestCase)</dt>
+<dd>
+reference to the test object
+</dd>
+<dt><i>err</i> (tuple)</dt>
+<dd>
+tuple containing the exception data like sys.exc_info
+            (exception type, exception instance, traceback)
+</dd>
+</dl>
+<a NAME="EricTestResult.addSkip" ID="EricTestResult.addSkip"></a>
+<h4>EricTestResult.addSkip</h4>
+<b>addSkip</b>(<i>test, reason</i>)
+
+<p>
+        Public method called if a test was skipped.
+</p>
+<dl>
+
+<dt><i>test</i> (TestCase)</dt>
+<dd>
+reference to the test object
+</dd>
+<dt><i>reason</i> (str)</dt>
+<dd>
+reason for skipping the test
+</dd>
+</dl>
+<a NAME="EricTestResult.addSubTest" ID="EricTestResult.addSubTest"></a>
+<h4>EricTestResult.addSubTest</h4>
+<b>addSubTest</b>(<i>test, subtest, err</i>)
+
+<p>
+        Public method called for each subtest to record its result.
+</p>
+<dl>
+
+<dt><i>test</i> (TestCase)</dt>
+<dd>
+reference to the test object
+</dd>
+<dt><i>subtest</i> (TestCase)</dt>
+<dd>
+reference to the subtest object
+</dd>
+<dt><i>err</i> (tuple)</dt>
+<dd>
+tuple containing the exception data like sys.exc_info
+            (exception type, exception instance, traceback)
+</dd>
+</dl>
+<a NAME="EricTestResult.addUnexpectedSuccess" ID="EricTestResult.addUnexpectedSuccess"></a>
+<h4>EricTestResult.addUnexpectedSuccess</h4>
+<b>addUnexpectedSuccess</b>(<i>test</i>)
+
+<p>
+        Public method called if a test succeeded expectedly.
+</p>
+<dl>
+
+<dt><i>test</i> (TestCase)</dt>
+<dd>
+reference to the test object
+</dd>
+</dl>
+<a NAME="EricTestResult.startTest" ID="EricTestResult.startTest"></a>
+<h4>EricTestResult.startTest</h4>
+<b>startTest</b>(<i>test</i>)
+
+<p>
+        Public method called at the start of a test.
+</p>
+<dl>
+
+<dt><i>test</i> (TestCase)</dt>
+<dd>
+reference to the test object
+</dd>
+</dl>
+<a NAME="EricTestResult.startTestRun" ID="EricTestResult.startTestRun"></a>
+<h4>EricTestResult.startTestRun</h4>
+<b>startTestRun</b>(<i></i>)
+
+<p>
+        Public method called once before any tests are executed.
+</p>
+<a NAME="EricTestResult.stopTest" ID="EricTestResult.stopTest"></a>
+<h4>EricTestResult.stopTest</h4>
+<b>stopTest</b>(<i>test</i>)
+
+<p>
+        Public method called at the end of a test.
+</p>
+<dl>
+
+<dt><i>test</i> (TestCase)</dt>
+<dd>
+reference to the test object
+</dd>
+</dl>
+<a NAME="EricTestResult.stopTestRun" ID="EricTestResult.stopTestRun"></a>
+<h4>EricTestResult.stopTestRun</h4>
+<b>stopTestRun</b>(<i></i>)
+
+<p>
+        Public method called once after all tests are executed.
+</p>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="_assembleTestCasesList" ID="_assembleTestCasesList"></a>
+<h2>_assembleTestCasesList</h2>
+<b>_assembleTestCasesList</b>(<i>suite</i>)
+
+<p>
+    Protected function to assemble a list of test cases included in a test
+    suite.
+</p>
+<dl>
+
+<dt><i>suite</i> (unittest.TestSuite)</dt>
+<dd>
+test suite to be inspected
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of tuples containing the test case ID, the string
+        representation and the short description
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of tuples of (str, str)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="runtest" ID="runtest"></a>
+<h2>runtest</h2>
+<b>runtest</b>(<i>argv</i>)
+
+<p>
+    Function to run the tests.
+</p>
+<dl>
+
+<dt><i>argv</i> (list of str)</dt>
+<dd>
+list of command line parameters.
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.Testing.TestResultsTree.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,770 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.TestResultsTree</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.Testing.TestResultsTree</h1>
+
+<p>
+Module implementing a tree view and associated model to show the test result
+data.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>TopLevelId</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestResultsModel">TestResultsModel</a></td>
+<td>Class implementing the item model containing the test data.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView">TestResultsTreeView</a></td>
+<td>Class implementing a tree view to show the test result data.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="TestResultsModel" ID="TestResultsModel"></a>
+<h2>TestResultsModel</h2>
+
+<p>
+    Class implementing the item model containing the test data.
+</p>
+<h3>Signals</h3>
+<dl>
+
+<dt>summary(str)</dt>
+<dd>
+emitted whenever the model data changes. The element
+        is a summary of the test results of the model.
+</dd>
+</dl>
+<h3>Derived from</h3>
+QAbstractItemModel
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>DurationColumn</td></tr><tr><td>Headers</td></tr><tr><td>MessageColumn</td></tr><tr><td>NameColumn</td></tr><tr><td>StatusColumn</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestResultsModel.__init__">TestResultsModel</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.__summary">__summary</a></td>
+<td>Private method to generate a test results summary text.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.addTestResults">addTestResults</a></td>
+<td>Public method to add test results to the ones already managed by the model.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.clear">clear</a></td>
+<td>Public method to clear the model data.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.columnCount">columnCount</a></td>
+<td>Public method to get the number of columns.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.data">data</a></td>
+<td>Public method to get the data for the various columns and roles.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.durationKey">durationKey</a></td>
+<td>Function to generate a key for duration sorting</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.getFailedTests">getFailedTests</a></td>
+<td>Public method to extract the test ids of all failed tests.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.getTestResults">getTestResults</a></td>
+<td>Public method to get the list of test results managed by the model.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.headerData">headerData</a></td>
+<td>Public method to get the header string for the various sections.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.index">index</a></td>
+<td>Public method to generate an index for the given row and column to identify the item.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.parent">parent</a></td>
+<td>Public method to get the parent of the item pointed to by index.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.rowCount">rowCount</a></td>
+<td>Public method to get the number of row for a given parent index.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.setTestResults">setTestResults</a></td>
+<td>Public method to set the list of test results of the model.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.sort">sort</a></td>
+<td>Public method to sort the model data by column in order.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsModel.updateTestResults">updateTestResults</a></td>
+<td>Public method to update the data of managed test result items.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="TestResultsModel.__init__" ID="TestResultsModel.__init__"></a>
+<h4>TestResultsModel (Constructor)</h4>
+<b>TestResultsModel</b>(<i>parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>parent</i> (QObject (optional))</dt>
+<dd>
+reference to the parent object (defaults to None)
+</dd>
+</dl>
+<a NAME="TestResultsModel.__summary" ID="TestResultsModel.__summary"></a>
+<h4>TestResultsModel.__summary</h4>
+<b>__summary</b>(<i></i>)
+
+<p>
+        Private method to generate a test results summary text.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+test results summary text
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
+<a NAME="TestResultsModel.addTestResults" ID="TestResultsModel.addTestResults"></a>
+<h4>TestResultsModel.addTestResults</h4>
+<b>addTestResults</b>(<i>testResults</i>)
+
+<p>
+        Public method to add test results to the ones already managed by the
+        model.
+</p>
+<dl>
+
+<dt><i>testResults</i> (list of TestResult)</dt>
+<dd>
+test results to be added to the model
+</dd>
+</dl>
+<a NAME="TestResultsModel.clear" ID="TestResultsModel.clear"></a>
+<h4>TestResultsModel.clear</h4>
+<b>clear</b>(<i></i>)
+
+<p>
+        Public method to clear the model data.
+</p>
+<a NAME="TestResultsModel.columnCount" ID="TestResultsModel.columnCount"></a>
+<h4>TestResultsModel.columnCount</h4>
+<b>columnCount</b>(<i>parent=QModelIndex()</i>)
+
+<p>
+        Public method to get the number of columns.
+</p>
+<dl>
+
+<dt><i>parent</i> (QModelIndex (optional))</dt>
+<dd>
+index of the parent item (defaults to QModelIndex())
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+number of columns
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
+</dd>
+</dl>
+<a NAME="TestResultsModel.data" ID="TestResultsModel.data"></a>
+<h4>TestResultsModel.data</h4>
+<b>data</b>(<i>index, role</i>)
+
+<p>
+        Public method to get the data for the various columns and roles.
+</p>
+<dl>
+
+<dt><i>index</i> (QModelIndex)</dt>
+<dd>
+index of the data to be returned
+</dd>
+<dt><i>role</i> (Qt.ItemDataRole)</dt>
+<dd>
+role designating the data to return
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+requested data item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+Any
+</dd>
+</dl>
+<a NAME="TestResultsModel.durationKey" ID="TestResultsModel.durationKey"></a>
+<h4>TestResultsModel.durationKey</h4>
+<b>durationKey</b>(<i></i>)
+
+<p>
+            Function to generate a key for duration sorting
+</p>
+<dl>
+
+<dt><i>result</i> (TestResult)</dt>
+<dd>
+result object
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+sort key
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+float
+</dd>
+</dl>
+<a NAME="TestResultsModel.getFailedTests" ID="TestResultsModel.getFailedTests"></a>
+<h4>TestResultsModel.getFailedTests</h4>
+<b>getFailedTests</b>(<i></i>)
+
+<p>
+        Public method to extract the test ids of all failed tests.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+test ids of all failed tests
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
+</dd>
+</dl>
+<a NAME="TestResultsModel.getTestResults" ID="TestResultsModel.getTestResults"></a>
+<h4>TestResultsModel.getTestResults</h4>
+<b>getTestResults</b>(<i></i>)
+
+<p>
+        Public method to get the list of test results managed by the model.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of test results managed by the model
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of TestResult
+</dd>
+</dl>
+<a NAME="TestResultsModel.headerData" ID="TestResultsModel.headerData"></a>
+<h4>TestResultsModel.headerData</h4>
+<b>headerData</b>(<i>section, orientation, role=Qt.ItemDataRole.DisplayRole</i>)
+
+<p>
+        Public method to get the header string for the various sections.
+</p>
+<dl>
+
+<dt><i>section</i> (int)</dt>
+<dd>
+section number
+</dd>
+<dt><i>orientation</i> (Qt.Orientation)</dt>
+<dd>
+orientation of the header
+</dd>
+<dt><i>role</i> (Qt.ItemDataRole (optional))</dt>
+<dd>
+data role (defaults to Qt.ItemDataRole.DisplayRole)
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+header string of the section
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
+<a NAME="TestResultsModel.index" ID="TestResultsModel.index"></a>
+<h4>TestResultsModel.index</h4>
+<b>index</b>(<i>row, column, parent=QModelIndex()</i>)
+
+<p>
+        Public method to generate an index for the given row and column to
+        identify the item.
+</p>
+<dl>
+
+<dt><i>row</i> (int)</dt>
+<dd>
+row for the index
+</dd>
+<dt><i>column</i> (int)</dt>
+<dd>
+column for the index
+</dd>
+<dt><i>parent</i> (QModelIndex (optional))</dt>
+<dd>
+index of the parent item (defaults to QModelIndex())
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+index for the item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QModelIndex
+</dd>
+</dl>
+<a NAME="TestResultsModel.parent" ID="TestResultsModel.parent"></a>
+<h4>TestResultsModel.parent</h4>
+<b>parent</b>(<i>index</i>)
+
+<p>
+        Public method to get the parent of the item pointed to by index.
+</p>
+<dl>
+
+<dt><i>index</i> (QModelIndex)</dt>
+<dd>
+index of the item
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+index of the parent item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QModelIndex
+</dd>
+</dl>
+<a NAME="TestResultsModel.rowCount" ID="TestResultsModel.rowCount"></a>
+<h4>TestResultsModel.rowCount</h4>
+<b>rowCount</b>(<i>parent=QModelIndex()</i>)
+
+<p>
+        Public method to get the number of row for a given parent index.
+</p>
+<dl>
+
+<dt><i>parent</i> (QModelIndex (optional))</dt>
+<dd>
+index of the parent item (defaults to QModelIndex())
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+number of rows
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
+</dd>
+</dl>
+<a NAME="TestResultsModel.setTestResults" ID="TestResultsModel.setTestResults"></a>
+<h4>TestResultsModel.setTestResults</h4>
+<b>setTestResults</b>(<i>testResults</i>)
+
+<p>
+        Public method to set the list of test results of the model.
+</p>
+<dl>
+
+<dt><i>testResults</i> (list of TestResult)</dt>
+<dd>
+test results to be managed by the model
+</dd>
+</dl>
+<a NAME="TestResultsModel.sort" ID="TestResultsModel.sort"></a>
+<h4>TestResultsModel.sort</h4>
+<b>sort</b>(<i>column, order</i>)
+
+<p>
+        Public method to sort the model data by column in order.
+</p>
+<dl>
+
+<dt><i>column</i> (int)</dt>
+<dd>
+sort column number
+</dd>
+<dt><i>order</i> (Qt.SortOrder)</dt>
+<dd>
+sort order
+</dd>
+</dl>
+<a NAME="TestResultsModel.updateTestResults" ID="TestResultsModel.updateTestResults"></a>
+<h4>TestResultsModel.updateTestResults</h4>
+<b>updateTestResults</b>(<i>testResults</i>)
+
+<p>
+        Public method to update the data of managed test result items.
+</p>
+<dl>
+
+<dt><i>testResults</i> (list of TestResult)</dt>
+<dd>
+test results to be updated
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="TestResultsTreeView" ID="TestResultsTreeView"></a>
+<h2>TestResultsTreeView</h2>
+
+<p>
+    Class implementing a tree view to show the test result data.
+</p>
+<h3>Signals</h3>
+<dl>
+
+<dt>goto(str, int)</dt>
+<dd>
+emitted to go to the position given by file name
+        and line number
+</dd>
+</dl>
+<h3>Derived from</h3>
+QTreeView
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestResultsTreeView.__init__">TestResultsTreeView</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.__canonicalIndex">__canonicalIndex</a></td>
+<td>Private method to create the canonical index for a given index.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.__createBackgroundContextMenu">__createBackgroundContextMenu</a></td>
+<td>Private method to create a context menu for the background.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.__createContextMenu">__createContextMenu</a></td>
+<td>Private method to create a context menu for the item pointed to by the given index.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.__gotoTestDefinition">__gotoTestDefinition</a></td>
+<td>Private slot to show the test definition.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.__showContextMenu">__showContextMenu</a></td>
+<td>Private slot to show the context menu.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.dataChanged">dataChanged</a></td>
+<td>Public method called when the model data has changed.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.reset">reset</a></td>
+<td>Public method to reset the internal state of the view.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.resizeColumns">resizeColumns</a></td>
+<td>Public method to resize the columns to their contents.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.rowsInserted">rowsInserted</a></td>
+<td>Public method called when rows are inserted.</td>
+</tr>
+<tr>
+<td><a href="#TestResultsTreeView.spanFirstColumn">spanFirstColumn</a></td>
+<td>Public method to make the first column span the row for second level items.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="TestResultsTreeView.__init__" ID="TestResultsTreeView.__init__"></a>
+<h4>TestResultsTreeView (Constructor)</h4>
+<b>TestResultsTreeView</b>(<i>parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="TestResultsTreeView.__canonicalIndex" ID="TestResultsTreeView.__canonicalIndex"></a>
+<h4>TestResultsTreeView.__canonicalIndex</h4>
+<b>__canonicalIndex</b>(<i>index</i>)
+
+<p>
+        Private method to create the canonical index for a given index.
+</p>
+<p>
+        The canonical index is the index of the first column of the test
+        result entry (i.e. the top-level item). If the index is invalid,
+        None is returned.
+</p>
+<dl>
+
+<dt><i>index</i> (QModelIndex)</dt>
+<dd>
+index to determine the canonical index for
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+index of the firt column of the associated top-level item index
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QModelIndex
+</dd>
+</dl>
+<a NAME="TestResultsTreeView.__createBackgroundContextMenu" ID="TestResultsTreeView.__createBackgroundContextMenu"></a>
+<h4>TestResultsTreeView.__createBackgroundContextMenu</h4>
+<b>__createBackgroundContextMenu</b>(<i></i>)
+
+<p>
+        Private method to create a context menu for the background.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+created context menu
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QMenu
+</dd>
+</dl>
+<a NAME="TestResultsTreeView.__createContextMenu" ID="TestResultsTreeView.__createContextMenu"></a>
+<h4>TestResultsTreeView.__createContextMenu</h4>
+<b>__createContextMenu</b>(<i>index</i>)
+
+<p>
+        Private method to create a context menu for the item pointed to by the
+        given index.
+</p>
+<dl>
+
+<dt><i>index</i> (QModelIndex)</dt>
+<dd>
+index of the item
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+created context menu
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QMenu
+</dd>
+</dl>
+<a NAME="TestResultsTreeView.__gotoTestDefinition" ID="TestResultsTreeView.__gotoTestDefinition"></a>
+<h4>TestResultsTreeView.__gotoTestDefinition</h4>
+<b>__gotoTestDefinition</b>(<i>index</i>)
+
+<p>
+        Private slot to show the test definition.
+</p>
+<dl>
+
+<dt><i>index</i> (QModelIndex)</dt>
+<dd>
+index for the double-clicked item
+</dd>
+</dl>
+<a NAME="TestResultsTreeView.__showContextMenu" ID="TestResultsTreeView.__showContextMenu"></a>
+<h4>TestResultsTreeView.__showContextMenu</h4>
+<b>__showContextMenu</b>(<i>pos</i>)
+
+<p>
+        Private slot to show the context menu.
+</p>
+<dl>
+
+<dt><i>pos</i> (QPoint)</dt>
+<dd>
+relative position for the context menu
+</dd>
+</dl>
+<a NAME="TestResultsTreeView.dataChanged" ID="TestResultsTreeView.dataChanged"></a>
+<h4>TestResultsTreeView.dataChanged</h4>
+<b>dataChanged</b>(<i>topLeft, bottomRight, roles=[]</i>)
+
+<p>
+        Public method called when the model data has changed.
+</p>
+<dl>
+
+<dt><i>topLeft</i> (QModelIndex)</dt>
+<dd>
+index of the top left element
+</dd>
+<dt><i>bottomRight</i> (QModelIndex)</dt>
+<dd>
+index of the bottom right element
+</dd>
+<dt><i>roles</i> (list of Qt.ItemDataRole (optional))</dt>
+<dd>
+list of roles changed (defaults to [])
+</dd>
+</dl>
+<a NAME="TestResultsTreeView.reset" ID="TestResultsTreeView.reset"></a>
+<h4>TestResultsTreeView.reset</h4>
+<b>reset</b>(<i></i>)
+
+<p>
+        Public method to reset the internal state of the view.
+</p>
+<a NAME="TestResultsTreeView.resizeColumns" ID="TestResultsTreeView.resizeColumns"></a>
+<h4>TestResultsTreeView.resizeColumns</h4>
+<b>resizeColumns</b>(<i></i>)
+
+<p>
+        Public method to resize the columns to their contents.
+</p>
+<a NAME="TestResultsTreeView.rowsInserted" ID="TestResultsTreeView.rowsInserted"></a>
+<h4>TestResultsTreeView.rowsInserted</h4>
+<b>rowsInserted</b>(<i>parent, startRow, endRow</i>)
+
+<p>
+        Public method called when rows are inserted.
+</p>
+<dl>
+
+<dt><i>parent</i> (QModelIndex)</dt>
+<dd>
+model index of the parent item
+</dd>
+<dt><i>startRow</i> (int)</dt>
+<dd>
+first row been inserted
+</dd>
+<dt><i>endRow</i> (int)</dt>
+<dd>
+last row been inserted
+</dd>
+</dl>
+<a NAME="TestResultsTreeView.spanFirstColumn" ID="TestResultsTreeView.spanFirstColumn"></a>
+<h4>TestResultsTreeView.spanFirstColumn</h4>
+<b>spanFirstColumn</b>(<i>startRow, endRow</i>)
+
+<p>
+        Public method to make the first column span the row for second level
+        items.
+</p>
+<p>
+        These items contain the test results.
+</p>
+<dl>
+
+<dt><i>startRow</i> (QModelIndex)</dt>
+<dd>
+index of the first row to span
+</dd>
+<dt><i>endRow</i> (QModelIndex)</dt>
+<dd>
+index of the last row (including) to span
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.Testing.TestingWidget.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,970 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.TestingWidget</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.Testing.TestingWidget</h1>
+
+<p>
+Module implementing a widget to orchestrate unit test execution.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestingWidget">TestingWidget</a></td>
+<td>Class implementing a widget to orchestrate unit test execution.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidgetModes">TestingWidgetModes</a></td>
+<td>Class defining the various modes of the testing widget.</td>
+</tr>
+<tr>
+<td><a href="#TestingWindow">TestingWindow</a></td>
+<td>Main window class for the standalone dialog.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+
+<tr>
+<td><a href="#clearSavedHistories">clearSavedHistories</a></td>
+<td>Function to clear the saved history lists.</td>
+</tr>
+</table>
+<hr />
+<hr />
+<a NAME="TestingWidget" ID="TestingWidget"></a>
+<h2>TestingWidget</h2>
+
+<p>
+    Class implementing a widget to orchestrate unit test execution.
+</p>
+<h3>Signals</h3>
+<dl>
+
+<dt>testFile(str, int, bool)</dt>
+<dd>
+emitted to show the source of a
+       test file
+</dd>
+<dt>testRunStopped()</dt>
+<dd>
+emitted after a test run has finished
+</dd>
+</dl>
+<h3>Derived from</h3>
+QWidget, Ui_TestingWidget
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestingWidget.__init__">TestingWidget</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__adjustPendingState">__adjustPendingState</a></td>
+<td>Private method to change the status indicator of all still pending tests to "not run".</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__coverageData">__coverageData</a></td>
+<td>Private slot to handle the 'coverageData' signal of the executor.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__insertDiscovery">__insertDiscovery</a></td>
+<td>Private slot to insert the discovery start directory into the discoveryPicker object.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__insertHistory">__insertHistory</a></td>
+<td>Private slot to insert an item into a history object.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__insertTestFile">__insertTestFile</a></td>
+<td>Private slot to insert a test file name into the testsuitePicker object.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__insertTestName">__insertTestName</a></td>
+<td>Private slot to insert a test name into the testComboBox object.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__loadRecent">__loadRecent</a></td>
+<td>Private method to load the most recently used lists.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__openEditor">__openEditor</a></td>
+<td>Private method to open an editor window for the given file.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__populateTestFrameworkComboBox">__populateTestFrameworkComboBox</a></td>
+<td>Private method to (re-)populate the test framework selector.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__populateVenvComboBox">__populateVenvComboBox</a></td>
+<td>Private method to (re-)populate the virtual environments selector.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__processTestResult">__processTestResult</a></td>
+<td>Private slot to handle the receipt of a test result object.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__projectClosed">__projectClosed</a></td>
+<td>Private slot to handle a project being closed.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__projectOpened">__projectOpened</a></td>
+<td>Private slot to handle a project being opened.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__resetResults">__resetResults</a></td>
+<td>Private slot to reset the test results tab and data.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__saveRecent">__saveRecent</a></td>
+<td>Private method to save the most recently used lists.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__setIdleMode">__setIdleMode</a></td>
+<td>Private slot to switch the widget to idle mode.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__setRunningMode">__setRunningMode</a></td>
+<td>Private slot to switch the widget to running mode.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__setStatusLabel">__setStatusLabel</a></td>
+<td>Private slot to set the status label to the text sent by the model.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__setStoppedMode">__setStoppedMode</a></td>
+<td>Private slot to switch the widget to stopped mode.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__showCoverageDialog">__showCoverageDialog</a></td>
+<td>Private slot to show a code coverage dialog for the most recent test run.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__showLogOutput">__showLogOutput</a></td>
+<td>Private slot to show the output of the most recent test run.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__showSource">__showSource</a></td>
+<td>Private slot to show the source of a traceback in an editor.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__stopTests">__stopTests</a></td>
+<td>Private slot to stop the current test run.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__testProcessFinished">__testProcessFinished</a></td>
+<td>Private slot to handle the 'testFinished' signal of the executor.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__testRunAboutToBeStarted">__testRunAboutToBeStarted</a></td>
+<td>Private slot to handle the 'testRunAboutToBeStarted' signal of the executor.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__testRunFinished">__testRunFinished</a></td>
+<td>Private slot to handle the 'testRunFinished' signal of the executor.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__testStarted">__testStarted</a></td>
+<td>Private slot handling the 'startTest' signal of the executor.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__testsCollectError">__testsCollectError</a></td>
+<td>Private slot handling the 'collectError' signal of the executor.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__testsCollected">__testsCollected</a></td>
+<td>Private slot handling the 'collected' signal of the executor.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__testsStopped">__testsStopped</a></td>
+<td>Private slot to handle the 'stop' signal of the executor.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__updateButtonBoxButtons">__updateButtonBoxButtons</a></td>
+<td>Private slot to update the state of the buttons of the button box.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__updateCoverage">__updateCoverage</a></td>
+<td>Private slot to update the state of the coverage checkbox depending on the selected framework's capabilities.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.__updateProgress">__updateProgress</a></td>
+<td>Private slot update the progress indicators.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.clearRecent">clearRecent</a></td>
+<td>Public slot to clear the recently used lists.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.closeEvent">closeEvent</a></td>
+<td>Protected method to handle the close event.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.getFailedTests">getFailedTests</a></td>
+<td>Public method to get the list of failed tests (if any).</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.getResultsModel">getResultsModel</a></td>
+<td>Public method to get a reference to the model containing the test result data.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.hasFailedTests">hasFailedTests</a></td>
+<td>Public method to check for failed tests.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.on_buttonBox_clicked">on_buttonBox_clicked</a></td>
+<td>Private slot called by a button of the button box clicked.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.on_discoverCheckBox_toggled">on_discoverCheckBox_toggled</a></td>
+<td>Private slot handling state changes of the 'discover' checkbox.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.on_frameworkComboBox_currentIndexChanged">on_frameworkComboBox_currentIndexChanged</a></td>
+<td>Private slot handling the selection of a test framework.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.on_testsuitePicker_aboutToShowPathPickerDialog">on_testsuitePicker_aboutToShowPathPickerDialog</a></td>
+<td>Private slot called before the test file selection dialog is shown.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.on_venvComboBox_currentIndexChanged">on_venvComboBox_currentIndexChanged</a></td>
+<td>Private slot handling the selection of a virtual environment.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.on_versionsButton_clicked">on_versionsButton_clicked</a></td>
+<td>Private slot to show the versions of available plugins.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.setTestFile">setTestFile</a></td>
+<td>Public slot to set the given test file as the current one.</td>
+</tr>
+<tr>
+<td><a href="#TestingWidget.startTests">startTests</a></td>
+<td>Public slot to start the test run.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="TestingWidget.__init__" ID="TestingWidget.__init__"></a>
+<h4>TestingWidget (Constructor)</h4>
+<b>TestingWidget</b>(<i>testfile=None, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>testfile</i> (str)</dt>
+<dd>
+file name of the test to load
+</dd>
+<dt><i>parent</i> (QWidget (optional))</dt>
+<dd>
+reference to the parent widget (defaults to None)
+</dd>
+</dl>
+<a NAME="TestingWidget.__adjustPendingState" ID="TestingWidget.__adjustPendingState"></a>
+<h4>TestingWidget.__adjustPendingState</h4>
+<b>__adjustPendingState</b>(<i></i>)
+
+<p>
+        Private method to change the status indicator of all still pending
+        tests to "not run".
+</p>
+<a NAME="TestingWidget.__coverageData" ID="TestingWidget.__coverageData"></a>
+<h4>TestingWidget.__coverageData</h4>
+<b>__coverageData</b>(<i>coverageFile</i>)
+
+<p>
+        Private slot to handle the 'coverageData' signal of the executor.
+</p>
+<dl>
+
+<dt><i>coverageFile</i> (str)</dt>
+<dd>
+file containing the coverage data
+</dd>
+</dl>
+<a NAME="TestingWidget.__insertDiscovery" ID="TestingWidget.__insertDiscovery"></a>
+<h4>TestingWidget.__insertDiscovery</h4>
+<b>__insertDiscovery</b>(<i>start</i>)
+
+<p>
+        Private slot to insert the discovery start directory into the
+        discoveryPicker object.
+</p>
+<dl>
+
+<dt><i>start</i> (str)</dt>
+<dd>
+start directory name to be inserted
+</dd>
+</dl>
+<a NAME="TestingWidget.__insertHistory" ID="TestingWidget.__insertHistory"></a>
+<h4>TestingWidget.__insertHistory</h4>
+<b>__insertHistory</b>(<i>widget, history, item</i>)
+
+<p>
+        Private slot to insert an item into a history object.
+</p>
+<dl>
+
+<dt><i>widget</i> (QComboBox or EricComboPathPicker)</dt>
+<dd>
+reference to the widget
+</dd>
+<dt><i>history</i> (list of str)</dt>
+<dd>
+array containing the history
+</dd>
+<dt><i>item</i> (str)</dt>
+<dd>
+item to be inserted
+</dd>
+</dl>
+<a NAME="TestingWidget.__insertTestFile" ID="TestingWidget.__insertTestFile"></a>
+<h4>TestingWidget.__insertTestFile</h4>
+<b>__insertTestFile</b>(<i>prog</i>)
+
+<p>
+        Private slot to insert a test file name into the testsuitePicker
+        object.
+</p>
+<dl>
+
+<dt><i>prog</i> (str)</dt>
+<dd>
+test file name to be inserted
+</dd>
+</dl>
+<a NAME="TestingWidget.__insertTestName" ID="TestingWidget.__insertTestName"></a>
+<h4>TestingWidget.__insertTestName</h4>
+<b>__insertTestName</b>(<i>testName</i>)
+
+<p>
+        Private slot to insert a test name into the testComboBox object.
+</p>
+<dl>
+
+<dt><i>testName</i> (str)</dt>
+<dd>
+name of the test to be inserted
+</dd>
+</dl>
+<a NAME="TestingWidget.__loadRecent" ID="TestingWidget.__loadRecent"></a>
+<h4>TestingWidget.__loadRecent</h4>
+<b>__loadRecent</b>(<i></i>)
+
+<p>
+        Private method to load the most recently used lists.
+</p>
+<a NAME="TestingWidget.__openEditor" ID="TestingWidget.__openEditor"></a>
+<h4>TestingWidget.__openEditor</h4>
+<b>__openEditor</b>(<i>filename, linenumber=1</i>)
+
+<p>
+        Private method to open an editor window for the given file.
+</p>
+<p>
+        Note: This method opens an editor window when the testing dialog
+        is called as a standalone application.
+</p>
+<dl>
+
+<dt><i>filename</i> (str)</dt>
+<dd>
+path of the file to be opened
+</dd>
+<dt><i>linenumber</i> (int (optional))</dt>
+<dd>
+line number to place the cursor at (defaults to 1)
+</dd>
+</dl>
+<a NAME="TestingWidget.__populateTestFrameworkComboBox" ID="TestingWidget.__populateTestFrameworkComboBox"></a>
+<h4>TestingWidget.__populateTestFrameworkComboBox</h4>
+<b>__populateTestFrameworkComboBox</b>(<i></i>)
+
+<p>
+        Private method to (re-)populate the test framework selector.
+</p>
+<a NAME="TestingWidget.__populateVenvComboBox" ID="TestingWidget.__populateVenvComboBox"></a>
+<h4>TestingWidget.__populateVenvComboBox</h4>
+<b>__populateVenvComboBox</b>(<i></i>)
+
+<p>
+        Private method to (re-)populate the virtual environments selector.
+</p>
+<a NAME="TestingWidget.__processTestResult" ID="TestingWidget.__processTestResult"></a>
+<h4>TestingWidget.__processTestResult</h4>
+<b>__processTestResult</b>(<i>result</i>)
+
+<p>
+        Private slot to handle the receipt of a test result object.
+</p>
+<dl>
+
+<dt><i>result</i> (TestResult)</dt>
+<dd>
+test result object
+</dd>
+</dl>
+<a NAME="TestingWidget.__projectClosed" ID="TestingWidget.__projectClosed"></a>
+<h4>TestingWidget.__projectClosed</h4>
+<b>__projectClosed</b>(<i></i>)
+
+<p>
+        Private slot to handle a project being closed.
+</p>
+<a NAME="TestingWidget.__projectOpened" ID="TestingWidget.__projectOpened"></a>
+<h4>TestingWidget.__projectOpened</h4>
+<b>__projectOpened</b>(<i></i>)
+
+<p>
+        Private slot to handle a project being opened.
+</p>
+<a NAME="TestingWidget.__resetResults" ID="TestingWidget.__resetResults"></a>
+<h4>TestingWidget.__resetResults</h4>
+<b>__resetResults</b>(<i></i>)
+
+<p>
+        Private slot to reset the test results tab and data.
+</p>
+<a NAME="TestingWidget.__saveRecent" ID="TestingWidget.__saveRecent"></a>
+<h4>TestingWidget.__saveRecent</h4>
+<b>__saveRecent</b>(<i></i>)
+
+<p>
+        Private method to save the most recently used lists.
+</p>
+<a NAME="TestingWidget.__setIdleMode" ID="TestingWidget.__setIdleMode"></a>
+<h4>TestingWidget.__setIdleMode</h4>
+<b>__setIdleMode</b>(<i></i>)
+
+<p>
+        Private slot to switch the widget to idle mode.
+</p>
+<a NAME="TestingWidget.__setRunningMode" ID="TestingWidget.__setRunningMode"></a>
+<h4>TestingWidget.__setRunningMode</h4>
+<b>__setRunningMode</b>(<i></i>)
+
+<p>
+        Private slot to switch the widget to running mode.
+</p>
+<a NAME="TestingWidget.__setStatusLabel" ID="TestingWidget.__setStatusLabel"></a>
+<h4>TestingWidget.__setStatusLabel</h4>
+<b>__setStatusLabel</b>(<i>statusText</i>)
+
+<p>
+        Private slot to set the status label to the text sent by the model.
+</p>
+<dl>
+
+<dt><i>statusText</i> (str)</dt>
+<dd>
+text to be shown
+</dd>
+</dl>
+<a NAME="TestingWidget.__setStoppedMode" ID="TestingWidget.__setStoppedMode"></a>
+<h4>TestingWidget.__setStoppedMode</h4>
+<b>__setStoppedMode</b>(<i></i>)
+
+<p>
+        Private slot to switch the widget to stopped mode.
+</p>
+<a NAME="TestingWidget.__showCoverageDialog" ID="TestingWidget.__showCoverageDialog"></a>
+<h4>TestingWidget.__showCoverageDialog</h4>
+<b>__showCoverageDialog</b>(<i></i>)
+
+<p>
+        Private slot to show a code coverage dialog for the most recent test
+        run.
+</p>
+<a NAME="TestingWidget.__showLogOutput" ID="TestingWidget.__showLogOutput"></a>
+<h4>TestingWidget.__showLogOutput</h4>
+<b>__showLogOutput</b>(<i></i>)
+
+<p>
+        Private slot to show the output of the most recent test run.
+</p>
+<a NAME="TestingWidget.__showSource" ID="TestingWidget.__showSource"></a>
+<h4>TestingWidget.__showSource</h4>
+<b>__showSource</b>(<i>filename, lineno</i>)
+
+<p>
+        Private slot to show the source of a traceback in an editor.
+</p>
+<dl>
+
+<dt><i>filename</i> (str)</dt>
+<dd>
+file name of the file to be shown
+</dd>
+<dt><i>lineno</i> (int)</dt>
+<dd>
+line number to go to in the file
+</dd>
+</dl>
+<a NAME="TestingWidget.__stopTests" ID="TestingWidget.__stopTests"></a>
+<h4>TestingWidget.__stopTests</h4>
+<b>__stopTests</b>(<i></i>)
+
+<p>
+        Private slot to stop the current test run.
+</p>
+<a NAME="TestingWidget.__testProcessFinished" ID="TestingWidget.__testProcessFinished"></a>
+<h4>TestingWidget.__testProcessFinished</h4>
+<b>__testProcessFinished</b>(<i>results, output</i>)
+
+<p>
+        Private slot to handle the 'testFinished' signal of the executor.
+</p>
+<dl>
+
+<dt><i>results</i> (list of TestResult)</dt>
+<dd>
+list of test result objects (if not sent via the
+            'testResult' signal
+</dd>
+<dt><i>output</i> (str)</dt>
+<dd>
+string containing the test process output (if any)
+</dd>
+</dl>
+<a NAME="TestingWidget.__testRunAboutToBeStarted" ID="TestingWidget.__testRunAboutToBeStarted"></a>
+<h4>TestingWidget.__testRunAboutToBeStarted</h4>
+<b>__testRunAboutToBeStarted</b>(<i></i>)
+
+<p>
+        Private slot to handle the 'testRunAboutToBeStarted' signal of the
+        executor.
+</p>
+<a NAME="TestingWidget.__testRunFinished" ID="TestingWidget.__testRunFinished"></a>
+<h4>TestingWidget.__testRunFinished</h4>
+<b>__testRunFinished</b>(<i>noTests, duration</i>)
+
+<p>
+        Private slot to handle the 'testRunFinished' signal of the executor.
+</p>
+<dl>
+
+<dt><i>noTests</i> (int)</dt>
+<dd>
+number of tests run by the executor
+</dd>
+<dt><i>duration</i> (float)</dt>
+<dd>
+time needed in seconds to run the tests
+</dd>
+</dl>
+<a NAME="TestingWidget.__testStarted" ID="TestingWidget.__testStarted"></a>
+<h4>TestingWidget.__testStarted</h4>
+<b>__testStarted</b>(<i>test</i>)
+
+<p>
+        Private slot handling the 'startTest' signal of the executor.
+</p>
+<dl>
+
+<dt><i>test</i> (tuple of (str, str, str))</dt>
+<dd>
+tuple containing the id, name and short description of the
+            tests about to be run
+</dd>
+</dl>
+<a NAME="TestingWidget.__testsCollectError" ID="TestingWidget.__testsCollectError"></a>
+<h4>TestingWidget.__testsCollectError</h4>
+<b>__testsCollectError</b>(<i>errors</i>)
+
+<p>
+        Private slot handling the 'collectError' signal of the executor.
+</p>
+<dl>
+
+<dt><i>errors</i> (list of tuple of (str, str))</dt>
+<dd>
+list of tuples containing the test name and a description
+            of the error
+</dd>
+</dl>
+<a NAME="TestingWidget.__testsCollected" ID="TestingWidget.__testsCollected"></a>
+<h4>TestingWidget.__testsCollected</h4>
+<b>__testsCollected</b>(<i>testNames</i>)
+
+<p>
+        Private slot handling the 'collected' signal of the executor.
+</p>
+<dl>
+
+<dt><i>testNames</i> (list of tuple of (str, str, str))</dt>
+<dd>
+list of tuples containing the test id, the test name
+            and a description of collected tests
+</dd>
+</dl>
+<a NAME="TestingWidget.__testsStopped" ID="TestingWidget.__testsStopped"></a>
+<h4>TestingWidget.__testsStopped</h4>
+<b>__testsStopped</b>(<i></i>)
+
+<p>
+        Private slot to handle the 'stop' signal of the executor.
+</p>
+<a NAME="TestingWidget.__updateButtonBoxButtons" ID="TestingWidget.__updateButtonBoxButtons"></a>
+<h4>TestingWidget.__updateButtonBoxButtons</h4>
+<b>__updateButtonBoxButtons</b>(<i></i>)
+
+<p>
+        Private slot to update the state of the buttons of the button box.
+</p>
+<a NAME="TestingWidget.__updateCoverage" ID="TestingWidget.__updateCoverage"></a>
+<h4>TestingWidget.__updateCoverage</h4>
+<b>__updateCoverage</b>(<i></i>)
+
+<p>
+        Private slot to update the state of the coverage checkbox depending on
+        the selected framework's capabilities.
+</p>
+<a NAME="TestingWidget.__updateProgress" ID="TestingWidget.__updateProgress"></a>
+<h4>TestingWidget.__updateProgress</h4>
+<b>__updateProgress</b>(<i></i>)
+
+<p>
+        Private slot update the progress indicators.
+</p>
+<a NAME="TestingWidget.clearRecent" ID="TestingWidget.clearRecent"></a>
+<h4>TestingWidget.clearRecent</h4>
+<b>clearRecent</b>(<i></i>)
+
+<p>
+        Public slot to clear the recently used lists.
+</p>
+<a NAME="TestingWidget.closeEvent" ID="TestingWidget.closeEvent"></a>
+<h4>TestingWidget.closeEvent</h4>
+<b>closeEvent</b>(<i>event</i>)
+
+<p>
+        Protected method to handle the close event.
+</p>
+<dl>
+
+<dt><i>event</i> (QCloseEvent)</dt>
+<dd>
+close event
+</dd>
+</dl>
+<a NAME="TestingWidget.getFailedTests" ID="TestingWidget.getFailedTests"></a>
+<h4>TestingWidget.getFailedTests</h4>
+<b>getFailedTests</b>(<i></i>)
+
+<p>
+        Public method to get the list of failed tests (if any).
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of IDs of failed tests
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
+</dd>
+</dl>
+<a NAME="TestingWidget.getResultsModel" ID="TestingWidget.getResultsModel"></a>
+<h4>TestingWidget.getResultsModel</h4>
+<b>getResultsModel</b>(<i></i>)
+
+<p>
+        Public method to get a reference to the model containing the test
+        result data.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+reference to the test results model
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+TestResultsModel
+</dd>
+</dl>
+<a NAME="TestingWidget.hasFailedTests" ID="TestingWidget.hasFailedTests"></a>
+<h4>TestingWidget.hasFailedTests</h4>
+<b>hasFailedTests</b>(<i></i>)
+
+<p>
+        Public method to check for failed tests.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating the existence of failed tests
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="TestingWidget.on_buttonBox_clicked" ID="TestingWidget.on_buttonBox_clicked"></a>
+<h4>TestingWidget.on_buttonBox_clicked</h4>
+<b>on_buttonBox_clicked</b>(<i>button</i>)
+
+<p>
+        Private slot called by a button of the button box clicked.
+</p>
+<dl>
+
+<dt><i>button</i> (QAbstractButton)</dt>
+<dd>
+button that was clicked
+</dd>
+</dl>
+<a NAME="TestingWidget.on_discoverCheckBox_toggled" ID="TestingWidget.on_discoverCheckBox_toggled"></a>
+<h4>TestingWidget.on_discoverCheckBox_toggled</h4>
+<b>on_discoverCheckBox_toggled</b>(<i>checked</i>)
+
+<p>
+        Private slot handling state changes of the 'discover' checkbox.
+</p>
+<dl>
+
+<dt><i>checked</i> (bool)</dt>
+<dd>
+state of the checkbox
+</dd>
+</dl>
+<a NAME="TestingWidget.on_frameworkComboBox_currentIndexChanged" ID="TestingWidget.on_frameworkComboBox_currentIndexChanged"></a>
+<h4>TestingWidget.on_frameworkComboBox_currentIndexChanged</h4>
+<b>on_frameworkComboBox_currentIndexChanged</b>(<i>index</i>)
+
+<p>
+        Private slot handling the selection of a test framework.
+</p>
+<dl>
+
+<dt><i>index</i> (int)</dt>
+<dd>
+index of the selected framework
+</dd>
+</dl>
+<a NAME="TestingWidget.on_testsuitePicker_aboutToShowPathPickerDialog" ID="TestingWidget.on_testsuitePicker_aboutToShowPathPickerDialog"></a>
+<h4>TestingWidget.on_testsuitePicker_aboutToShowPathPickerDialog</h4>
+<b>on_testsuitePicker_aboutToShowPathPickerDialog</b>(<i></i>)
+
+<p>
+        Private slot called before the test file selection dialog is shown.
+</p>
+<a NAME="TestingWidget.on_venvComboBox_currentIndexChanged" ID="TestingWidget.on_venvComboBox_currentIndexChanged"></a>
+<h4>TestingWidget.on_venvComboBox_currentIndexChanged</h4>
+<b>on_venvComboBox_currentIndexChanged</b>(<i>index</i>)
+
+<p>
+        Private slot handling the selection of a virtual environment.
+</p>
+<dl>
+
+<dt><i>index</i> (int)</dt>
+<dd>
+index of the selected environment
+</dd>
+</dl>
+<a NAME="TestingWidget.on_versionsButton_clicked" ID="TestingWidget.on_versionsButton_clicked"></a>
+<h4>TestingWidget.on_versionsButton_clicked</h4>
+<b>on_versionsButton_clicked</b>(<i></i>)
+
+<p>
+        Private slot to show the versions of available plugins.
+</p>
+<a NAME="TestingWidget.setTestFile" ID="TestingWidget.setTestFile"></a>
+<h4>TestingWidget.setTestFile</h4>
+<b>setTestFile</b>(<i>testFile, forProject=False</i>)
+
+<p>
+        Public slot to set the given test file as the current one.
+</p>
+<dl>
+
+<dt><i>testFile</i> (str)</dt>
+<dd>
+path of the test file
+</dd>
+<dt><i>forProject</i> (bool (optional))</dt>
+<dd>
+flag indicating that this call is for a project
+            (defaults to False)
+</dd>
+</dl>
+<a NAME="TestingWidget.startTests" ID="TestingWidget.startTests"></a>
+<h4>TestingWidget.startTests</h4>
+<b>startTests</b>(<i>failedOnly=False</i>)
+
+<p>
+        Public slot to start the test run.
+</p>
+<dl>
+
+<dt><i>failedOnly</i> (bool)</dt>
+<dd>
+flag indicating to run only failed tests
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="TestingWidgetModes" ID="TestingWidgetModes"></a>
+<h2>TestingWidgetModes</h2>
+
+<p>
+    Class defining the various modes of the testing widget.
+</p>
+<h3>Derived from</h3>
+enum.Enum
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>IDLE</td></tr><tr><td>RUNNING</td></tr><tr><td>STOPPED</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="TestingWindow" ID="TestingWindow"></a>
+<h2>TestingWindow</h2>
+
+<p>
+    Main window class for the standalone dialog.
+</p>
+<h3>Derived from</h3>
+EricMainWindow
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#TestingWindow.__init__">TestingWindow</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#TestingWindow.eventFilter">eventFilter</a></td>
+<td>Public method to filter events.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="TestingWindow.__init__" ID="TestingWindow.__init__"></a>
+<h4>TestingWindow (Constructor)</h4>
+<b>TestingWindow</b>(<i>testfile=None, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>testfile</i> (str)</dt>
+<dd>
+file name of the test script to open
+</dd>
+<dt><i>parent</i> (QWidget)</dt>
+<dd>
+reference to the parent widget
+</dd>
+</dl>
+<a NAME="TestingWindow.eventFilter" ID="TestingWindow.eventFilter"></a>
+<h4>TestingWindow.eventFilter</h4>
+<b>eventFilter</b>(<i>obj, event</i>)
+
+<p>
+        Public method to filter events.
+</p>
+<dl>
+
+<dt><i>obj</i></dt>
+<dd>
+reference to the object the event is meant for (QObject)
+</dd>
+<dt><i>event</i></dt>
+<dd>
+reference to the event object (QEvent)
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating, whether the event was handled (boolean)
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="clearSavedHistories" ID="clearSavedHistories"></a>
+<h2>clearSavedHistories</h2>
+<b>clearSavedHistories</b>(<i>self</i>)
+
+<p>
+    Function to clear the saved history lists.
+</p>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.Testing.__init__.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.__init__</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.Testing.__init__</h1>
+
+<p>
+Package implementing testing functionality and interface to various test
+frameworks.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+
+<tr>
+<td><a href="#isLanguageSupported">isLanguageSupported</a></td>
+<td>Function to check, if the given programming language is supported by any testing framework.</td>
+</tr>
+<tr>
+<td><a href="#supportedLanguages">supportedLanguages</a></td>
+<td>Function to get a list of supported programming languages.</td>
+</tr>
+</table>
+<hr />
+<hr />
+<a NAME="isLanguageSupported" ID="isLanguageSupported"></a>
+<h2>isLanguageSupported</h2>
+<b>isLanguageSupported</b>(<i>language</i>)
+
+<p>
+    Function to check, if the given programming language is supported by any
+    testing framework.
+</p>
+<dl>
+
+<dt><i>language</i> (str)</dt>
+<dd>
+programming language
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating support
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="supportedLanguages" ID="supportedLanguages"></a>
+<h2>supportedLanguages</h2>
+<b>supportedLanguages</b>(<i></i>)
+
+<p>
+    Function to get a list of supported programming languages.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of supported programming languages
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/eric7.eric7_testing.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.eric7_testing</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric7.eric7_testing</h1>
+
+<p>
+eric testing.
+</p>
+<p>
+This is the main Python script that performs the necessary initialization
+of the testing module and starts the Qt event loop. This is a standalone
+version of the integrated testing module.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+
+<tr>
+<td><a href="#createMainWidget">createMainWidget</a></td>
+<td>Function to create the main widget.</td>
+</tr>
+<tr>
+<td><a href="#main">main</a></td>
+<td>Main entry point into the application.</td>
+</tr>
+</table>
+<hr />
+<hr />
+<a NAME="createMainWidget" ID="createMainWidget"></a>
+<h2>createMainWidget</h2>
+<b>createMainWidget</b>(<i>argv</i>)
+
+<p>
+    Function to create the main widget.
+</p>
+<dl>
+
+<dt><i>argv</i> (list of str)</dt>
+<dd>
+list of commandline parameters
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+reference to the main widget
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QWidget
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="main" ID="main"></a>
+<h2>main</h2>
+<b>main</b>(<i></i>)
+
+<p>
+    Main entry point into the application.
+</p>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/eric7/Documentation/Source/eric7.eric7_unittest.html	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-<!DOCTYPE html>
-<html><head>
-<title>eric7.eric7_unittest</title>
-<meta charset="UTF-8">
-<link rel="stylesheet" href="styles.css">
-</head>
-<body>
-<a NAME="top" ID="top"></a>
-<h1>eric7.eric7_unittest</h1>
-
-<p>
-eric Unittest.
-</p>
-<p>
-This is the main Python script that performs the necessary initialization
-of the unittest module and starts the Qt event loop. This is a standalone
-version of the integrated unittest module.
-</p>
-<h3>Global Attributes</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Classes</h3>
-
-<table>
-<tr><td>None</td></tr>
-</table>
-<h3>Functions</h3>
-
-<table>
-
-<tr>
-<td><a href="#createMainWidget">createMainWidget</a></td>
-<td>Function to create the main widget.</td>
-</tr>
-<tr>
-<td><a href="#main">main</a></td>
-<td>Main entry point into the application.</td>
-</tr>
-</table>
-<hr />
-<hr />
-<a NAME="createMainWidget" ID="createMainWidget"></a>
-<h2>createMainWidget</h2>
-<b>createMainWidget</b>(<i>argv</i>)
-
-<p>
-    Function to create the main widget.
-</p>
-<dl>
-
-<dt><i>argv</i></dt>
-<dd>
-list of commandline parameters (list of strings)
-</dd>
-</dl>
-<dl>
-<dt>Return:</dt>
-<dd>
-reference to the main widget (QWidget)
-</dd>
-</dl>
-<div align="right"><a href="#top">Up</a></div>
-<hr />
-<hr />
-<a NAME="main" ID="main"></a>
-<h2>main</h2>
-<b>main</b>(<i></i>)
-
-<p>
-    Main entry point into the application.
-</p>
-<div align="right"><a href="#top">Up</a></div>
-<hr />
-</body></html>
\ No newline at end of file
--- a/eric7/Documentation/Source/index-eric7.PyUnit.html	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html><head>
-<title>eric7.PyUnit</title>
-<meta charset="UTF-8">
-<link rel="stylesheet" href="styles.css">
-</head>
-<body>
-<h1>eric7.PyUnit</h1>
-
-<p>
-Package implementing an interface to the pyunit unittest package.
-</p>
-<p>
-The package consist of a single dialog, which may be called as a
-standalone version using the eric7_unittest script or from within the eric
-IDE. If it is called from within eric, it has the additional function to
-open a source file that failed a test.
-</p>
-
-
-<h3>Modules</h3>
-<table>
-
-<tr>
-<td><a href="eric7.PyUnit.UnittestDialog.html">UnittestDialog</a></td>
-<td>Module implementing the UI to the pyunit package.</td>
-</tr>
-</table>
-</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/index-eric7.Testing.Interfaces.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing.Interfaces</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<h1>eric7.Testing.Interfaces</h1>
+
+<p>
+Package containg the various test framework interfaces.
+</p>
+
+
+<h3>Modules</h3>
+<table>
+
+<tr>
+<td><a href="eric7.Testing.Interfaces.PytestExecutor.html">PytestExecutor</a></td>
+<td>Module implementing the executor for the 'pytest' framework.</td>
+</tr>
+<tr>
+<td><a href="eric7.Testing.Interfaces.PytestRunner.html">PytestRunner</a></td>
+<td>Module implementing the test runner script for the 'pytest' framework.</td>
+</tr>
+<tr>
+<td><a href="eric7.Testing.Interfaces.TestExecutorBase.html">TestExecutorBase</a></td>
+<td>Module implementing the executor base class for the various testing frameworks and supporting classes.</td>
+</tr>
+<tr>
+<td><a href="eric7.Testing.Interfaces.TestFrameworkRegistry.html">TestFrameworkRegistry</a></td>
+<td>Module implementing a simple registry containing the available test framework interfaces.</td>
+</tr>
+<tr>
+<td><a href="eric7.Testing.Interfaces.UnittestExecutor.html">UnittestExecutor</a></td>
+<td>Module implementing the executor for the standard 'unittest' framework.</td>
+</tr>
+<tr>
+<td><a href="eric7.Testing.Interfaces.UnittestRunner.html">UnittestRunner</a></td>
+<td>Module implementing the test runner script for the 'unittest' framework.</td>
+</tr>
+</table>
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Documentation/Source/index-eric7.Testing.html	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric7.Testing</title>
+<meta charset="UTF-8">
+<link rel="stylesheet" href="styles.css">
+</head>
+<body>
+<h1>eric7.Testing</h1>
+
+<p>
+Package implementing testing functionality and interface to various test
+frameworks.
+</p>
+
+<h3>Packages</h3>
+<table>
+
+<tr>
+<td><a href="index-eric7.Testing.Interfaces.html">Interfaces</a></td>
+<td>Package containg the various test framework interfaces.</td>
+</tr>
+</table>
+
+<h3>Modules</h3>
+<table>
+
+<tr>
+<td><a href="eric7.Testing.TestResultsTree.html">TestResultsTree</a></td>
+<td>Module implementing a tree view and associated model to show the test result data.</td>
+</tr>
+<tr>
+<td><a href="eric7.Testing.TestingWidget.html">TestingWidget</a></td>
+<td>Module implementing a widget to orchestrate unit test execution.</td>
+</tr>
+<tr>
+<td><a href="eric7.Testing.__init__.html">Testing</a></td>
+<td>Package implementing testing functionality and interface to various test frameworks.</td>
+</tr>
+</table>
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/EricNetwork/EricJsonStreamReader.py	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a JSON based reader class.
+"""
+
+import json
+
+from PyQt6.QtCore import pyqtSignal, pyqtSlot
+from PyQt6.QtNetwork import QTcpServer, QHostAddress
+
+from EricWidgets import EricMessageBox
+
+import Preferences
+import Utilities
+
+
+class EricJsonReader(QTcpServer):
+    """
+    Class implementing a JSON based reader class.
+    
+    The reader is responsible for opening a socket to listen for writer
+    connections.
+    
+    @signal dataReceived(object) emitted after a data object was received
+    """
+    dataReceived = pyqtSignal(object)
+    
+    def __init__(self, name="", ip=None, parent=None):
+        """
+        Constructor
+        
+        @param name name of the server (used for output only)
+        @type str
+        @param ip IP address to listen at
+        @type str
+        @param parent parent object
+        @type QObject
+        """
+        super().__init__(parent)
+        
+        self.__name = name
+        self.__connection = None
+        
+        # setup the network interface
+        if ip is None:
+            networkInterface = Preferences.getDebugger("NetworkInterface")
+            if networkInterface == "all" or '.' in networkInterface:
+                # IPv4
+                self.__hostAddress = '127.0.0.1'
+            else:
+                # IPv6
+                self.__hostAddress = '::1'
+        else:
+            self.__hostAddress = ip
+        self.listen(QHostAddress(self.__hostAddress))
+
+        self.newConnection.connect(self.handleNewConnection)
+        
+        ## Note: Need the port if writer is started external in debugger.
+        print('JSON reader ({1}) listening on: {0:d}'   # __IGNORE_WARNING__
+              .format(self.serverPort(), self.__name))
+    
+    def address(self):
+        """
+        Public method to get the host address.
+        
+        @return host address
+        @rtype str
+        """
+        return self.__hostAddress
+    
+    def port(self):
+        """
+        Public method to get the port number to connect to.
+        
+        @return port number
+        @rtype int
+        """
+        return self.serverPort()
+    
+    @pyqtSlot()
+    def handleNewConnection(self):
+        """
+        Public slot for new incoming connections from a writer.
+        """
+        connection = self.nextPendingConnection()
+        if not connection.isValid():
+            return
+        
+        if self.__connection is not None:
+            self.__connection.close()
+        
+        self.__connection = connection
+        
+        connection.readyRead.connect(self.__receiveJson)
+        connection.disconnected.connect(self.__handleDisconnect)
+    
+    @pyqtSlot()
+    def __handleDisconnect(self):
+        """
+        Private slot handling a disconnect of the writer.
+        """
+        if self.__connection is not None:
+            self.__receiveJson()    # read all buffered data first
+            self.__connection.close()
+        
+        self.__connection = None
+    
+    @pyqtSlot()
+    def __receiveJson(self):
+        """
+        Private slot handling received data from the writer.
+        """
+        while self.__connection and self.__connection.canReadLine():
+            dataStr = self.__connection.readLine()
+            jsonLine = bytes(dataStr).decode("utf-8", 'backslashreplace')
+            
+            #- print("JSON Reader ({0}): {1}".format(self.__name, jsonLine))
+            #- this is for debugging only
+            
+            try:
+                data = json.loads(jsonLine.strip())
+            except (TypeError, ValueError) as err:
+                EricMessageBox.critical(
+                    None,
+                    self.tr("JSON Protocol Error"),
+                    self.tr("""<p>The data received from the writer"""
+                            """ could not be decoded. Please report"""
+                            """ this issue with the received data to the"""
+                            """ eric bugs email address.</p>"""
+                            """<p>Error: {0}</p>"""
+                            """<p>Data:<br/>{1}</p>""").format(
+                        str(err), Utilities.html_encode(jsonLine.strip())),
+                    EricMessageBox.Ok)
+                return
+            
+            self.dataReceived.emit(data)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/EricNetwork/EricJsonStreamWriter.py	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a JSON based writer class.
+"""
+
+import json
+import socket
+
+
+class EricJsonWriter:
+    """
+    Class implementing a JSON based writer class.
+    """
+    def __init__(self, host, port):
+        """
+        Constructor
+        
+        @param host IP address the reader is listening on
+        @type str
+        @param port port the reader is listening on
+        @type int
+        """
+        self.__connection = socket.create_connection((host, port))
+    
+    def write(self, data):
+        """
+        Public method to send JSON serializable data.
+        
+        @param data JSON serializable object to be sent
+        @type object
+        """
+        dataStr = json.dumps(data) + '\n'
+        self.__connection.sendall(dataStr.encode('utf8', 'backslashreplace'))
+    
+    def close(self):
+        """
+        Public method to close the stream.
+        """
+        self.__connection.close()
--- a/eric7/PyUnit/UnittestDialog.py	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1506 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2002 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Module implementing the UI to the pyunit package.
-"""
-
-import unittest
-import sys
-import time
-import re
-import os
-import contextlib
-
-from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QEvent, QFileInfo
-from PyQt6.QtGui import QColor
-from PyQt6.QtWidgets import (
-    QWidget, QDialog, QApplication, QDialogButtonBox, QListWidgetItem,
-    QComboBox, QTreeWidgetItem
-)
-
-from EricWidgets.EricApplication import ericApp
-from EricWidgets import EricMessageBox
-from EricWidgets.EricMainWindow import EricMainWindow
-from EricWidgets.EricPathPicker import EricPathPickerModes
-
-from .Ui_UnittestDialog import Ui_UnittestDialog
-
-import UI.PixmapCache
-
-import Preferences
-
-from Globals import (
-    recentNameUnittestDiscoverHistory, recentNameUnittestFileHistory,
-    recentNameUnittestTestnameHistory
-)
-
-
-class UnittestDialog(QWidget, Ui_UnittestDialog):
-    """
-    Class implementing the UI to the pyunit package.
-    
-    @signal unittestFile(str, int, bool) emitted to show the source of a
-        unittest file
-    @signal unittestStopped() emitted after a unit test was run
-    """
-    unittestFile = pyqtSignal(str, int, bool)
-    unittestStopped = pyqtSignal()
-    
-    TestCaseNameRole = Qt.ItemDataRole.UserRole
-    TestCaseFileRole = Qt.ItemDataRole.UserRole + 1
-    
-    ErrorsInfoRole = Qt.ItemDataRole.UserRole
-    
-    SkippedColorDarkTheme = QColor("#00aaff")
-    FailedExpectedColorDarkTheme = QColor("#ccaaff")
-    SucceededUnexpectedColorDarkTheme = QColor("#ff99dd")
-    SkippedColorLightTheme = QColor("#0000ff")
-    FailedExpectedColorLightTheme = QColor("#7700bb")
-    SucceededUnexpectedColorLightTheme = QColor("#ff0000")
-    
-    def __init__(self, prog=None, dbs=None, ui=None, parent=None, name=None):
-        """
-        Constructor
-        
-        @param prog filename of the program to open
-        @type str
-        @param dbs reference to the debug server object. It is an indication
-            whether we were called from within the eric IDE.
-        @type DebugServer
-        @param ui reference to the UI object
-        @type UserInterface
-        @param parent parent widget of this dialog
-        @type QWidget
-        @param name name of this dialog
-        @type str
-        """
-        super().__init__(parent)
-        if name:
-            self.setObjectName(name)
-        self.setupUi(self)
-        
-        self.clearHistoriesButton.setIcon(
-            UI.PixmapCache.getIcon("clearPrivateData"))
-        
-        self.testsuitePicker.setMode(EricPathPickerModes.OPEN_FILE_MODE)
-        self.testsuitePicker.setInsertPolicy(
-            QComboBox.InsertPolicy.InsertAtTop)
-        self.testsuitePicker.setSizeAdjustPolicy(
-            QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon)
-        
-        self.discoveryPicker.setMode(EricPathPickerModes.DIRECTORY_MODE)
-        self.discoveryPicker.setInsertPolicy(
-            QComboBox.InsertPolicy.InsertAtTop)
-        self.discoveryPicker.setSizeAdjustPolicy(
-            QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon)
-        
-        self.testComboBox.lineEdit().setClearButtonEnabled(True)
-        
-        self.discoverButton = self.buttonBox.addButton(
-            self.tr("Discover"), QDialogButtonBox.ButtonRole.ActionRole)
-        self.discoverButton.setToolTip(self.tr(
-            "Discover tests"))
-        self.discoverButton.setWhatsThis(self.tr(
-            """<b>Discover</b>"""
-            """<p>This button starts a discovery of available tests.</p>"""))
-        self.startButton = self.buttonBox.addButton(
-            self.tr("Start"), QDialogButtonBox.ButtonRole.ActionRole)
-        
-        self.startButton.setToolTip(self.tr(
-            "Start the selected testsuite"))
-        self.startButton.setWhatsThis(self.tr(
-            """<b>Start Test</b>"""
-            """<p>This button starts the selected testsuite.</p>"""))
-        
-        self.startFailedButton = self.buttonBox.addButton(
-            self.tr("Rerun Failed"), QDialogButtonBox.ButtonRole.ActionRole)
-        self.startFailedButton.setToolTip(
-            self.tr("Reruns failed tests of the selected testsuite"))
-        self.startFailedButton.setWhatsThis(self.tr(
-            """<b>Rerun Failed</b>"""
-            """<p>This button reruns all failed tests of the selected"""
-            """ testsuite.</p>"""))
-        
-        self.stopButton = self.buttonBox.addButton(
-            self.tr("Stop"), QDialogButtonBox.ButtonRole.ActionRole)
-        self.stopButton.setToolTip(self.tr("Stop the running unittest"))
-        self.stopButton.setWhatsThis(self.tr(
-            """<b>Stop Test</b>"""
-            """<p>This button stops a running unittest.</p>"""))
-        
-        self.discoverButton.setEnabled(False)
-        self.stopButton.setEnabled(False)
-        self.startButton.setDefault(True)
-        self.startFailedButton.setEnabled(False)
-        
-        self.__dbs = dbs
-        self.__forProject = False
-        
-        self.setWindowFlags(
-            self.windowFlags() |
-            Qt.WindowType.WindowContextHelpButtonHint
-        )
-        self.setWindowIcon(UI.PixmapCache.getIcon("eric"))
-        self.setWindowTitle(self.tr("Unittest"))
-        if dbs:
-            self.ui = ui
-            
-            self.debuggerCheckBox.setChecked(True)
-            
-            # virtual environment manager is only used in the integrated
-            # variant
-            self.__venvManager = ericApp().getObject("VirtualEnvManager")
-            self.__populateVenvComboBox()
-            self.__venvManager.virtualEnvironmentAdded.connect(
-                self.__populateVenvComboBox)
-            self.__venvManager.virtualEnvironmentRemoved.connect(
-                self.__populateVenvComboBox)
-            self.__venvManager.virtualEnvironmentChanged.connect(
-                self.__populateVenvComboBox)
-        else:
-            self.__venvManager = None
-            self.debuggerCheckBox.setVisible(False)
-        self.venvComboBox.setVisible(bool(self.__venvManager))
-        self.venvLabel.setVisible(bool(self.__venvManager))
-        
-        self.__setProgressColor("green")
-        self.progressLed.setDarkFactor(150)
-        self.progressLed.off()
-        
-        self.discoverHistory = []
-        self.fileHistory = []
-        self.testNameHistory = []
-        self.running = False
-        self.savedModulelist = None
-        self.savedSysPath = sys.path
-        self.savedCwd = os.getcwd()
-        
-        self.rxPatterns = [
-            self.tr("^Failure: "),
-            self.tr("^Error: "),
-            # These are for untranslated/partially translated situations
-            "^Failure: ",
-            "^Error: ",
-        ]
-        
-        self.__failedTests = set()
-        
-        # now connect the debug server signals if called from the eric IDE
-        if self.__dbs:
-            self.__dbs.utDiscovered.connect(self.__UTDiscovered)
-            self.__dbs.utPrepared.connect(self.__UTPrepared)
-            self.__dbs.utFinished.connect(self.__setStoppedMode)
-            self.__dbs.utStartTest.connect(self.testStarted)
-            self.__dbs.utStopTest.connect(self.testFinished)
-            self.__dbs.utTestFailed.connect(self.testFailed)
-            self.__dbs.utTestErrored.connect(self.testErrored)
-            self.__dbs.utTestSkipped.connect(self.testSkipped)
-            self.__dbs.utTestFailedExpected.connect(self.testFailedExpected)
-            self.__dbs.utTestSucceededUnexpected.connect(
-                self.testSucceededUnexpected)
-        
-        self.__editors = []
-        
-        self.__loadRecent()
-        
-        self.insertProg(prog)
-        self.insertTestName("")
-        
-        self.clearHistoriesButton.clicked.connect(self.clearRecent)
-    
-    def keyPressEvent(self, evt):
-        """
-        Protected slot to handle key press events.
-        
-        @param evt key press event to handle (QKeyEvent)
-        """
-        if evt.key() == Qt.Key.Key_Escape and self.__dbs:
-            self.close()
-    
-    def __populateVenvComboBox(self):
-        """
-        Private method to (re-)populate the virtual environments selector.
-        """
-        currentText = self.venvComboBox.currentText()
-        self.venvComboBox.clear()
-        self.venvComboBox.addItem("")
-        self.venvComboBox.addItems(
-            sorted(self.__venvManager.getVirtualenvNames()))
-        index = self.venvComboBox.findText(currentText)
-        if index < 0:
-            index = 0
-        self.venvComboBox.setCurrentIndex(index)
-    
-    def __setProgressColor(self, color):
-        """
-        Private method to set the color of the progress color label.
-        
-        @param color colour to be shown (string)
-        """
-        self.progressLed.setColor(QColor(color))
-    
-    def setProjectMode(self, forProject):
-        """
-        Public method to set the project mode of the dialog.
-        
-        @param forProject flag indicating to run for the open project
-        @type bool
-        """
-        self.__forProject = forProject
-        if forProject:
-            project = ericApp().getObject("Project")
-            if project.isOpen():
-                self.insertDiscovery(project.getProjectPath())
-            else:
-                self.insertDiscovery("")
-        else:
-            self.insertDiscovery("")
-        
-        self.discoveryList.clear()
-        self.tabWidget.setCurrentIndex(0)
-    
-    def insertDiscovery(self, start):
-        """
-        Public slot to insert the discovery start directory into the
-        discoveryPicker object.
-        
-        @param start start directory name to be inserted
-        @type str
-        """
-        current = self.discoveryPicker.currentText()
-        
-        # prepend the given directory to the discovery picker
-        if start is None:
-            start = ""
-        if start in self.discoverHistory:
-            self.discoverHistory.remove(start)
-        self.discoverHistory.insert(0, start)
-        self.discoveryPicker.clear()
-        self.discoveryPicker.addItems(self.discoverHistory)
-        
-        if current:
-            self.discoveryPicker.setText(current)
-    
-    def insertProg(self, prog):
-        """
-        Public slot to insert the filename prog into the testsuitePicker
-        object.
-        
-        @param prog filename to be inserted (string)
-        """
-        current = self.testsuitePicker.currentText()
-        
-        # prepend the selected file to the testsuite picker
-        if prog is None:
-            prog = ""
-        if prog in self.fileHistory:
-            self.fileHistory.remove(prog)
-        self.fileHistory.insert(0, prog)
-        self.testsuitePicker.clear()
-        self.testsuitePicker.addItems(self.fileHistory)
-        
-        if current:
-            self.testsuitePicker.setText(current)
-    
-    def insertTestName(self, testName):
-        """
-        Public slot to insert a test name into the testComboBox object.
-        
-        @param testName name of the test to be inserted (string)
-        """
-        current = self.testComboBox.currentText()
-        
-        # prepend the selected file to the testsuite combobox
-        if testName is None:
-            testName = ""
-        if testName in self.testNameHistory:
-            self.testNameHistory.remove(testName)
-        self.testNameHistory.insert(0, testName)
-        self.testComboBox.clear()
-        self.testComboBox.addItems(self.testNameHistory)
-        
-        if current:
-            self.testComboBox.setCurrentText(current)
-    
-    @pyqtSlot()
-    def on_testsuitePicker_aboutToShowPathPickerDialog(self):
-        """
-        Private slot called before the test suite selection dialog is shown.
-        """
-        if self.__dbs:
-            py3Extensions = ' '.join(
-                ["*{0}".format(ext)
-                 for ext in self.__dbs.getExtensions('Python3')]
-            )
-            fileFilter = self.tr(
-                "Python3 Files ({0});;All Files (*)"
-            ).format(py3Extensions)
-        else:
-            fileFilter = self.tr("Python Files (*.py);;All Files (*)")
-        self.testsuitePicker.setFilters(fileFilter)
-        
-        defaultDirectory = Preferences.getMultiProject("Workspace")
-        if not defaultDirectory:
-            defaultDirectory = os.path.expanduser("~")
-        if self.__dbs:
-            project = ericApp().getObject("Project")
-            if self.__forProject and project.isOpen():
-                defaultDirectory = project.getProjectPath()
-        self.testsuitePicker.setDefaultDirectory(defaultDirectory)
-    
-    @pyqtSlot(str)
-    def on_testsuitePicker_pathSelected(self, suite):
-        """
-        Private slot called after a test suite has been selected.
-        
-        @param suite file name of the test suite
-        @type str
-        """
-        self.insertProg(suite)
-    
-    @pyqtSlot(str)
-    def on_testsuitePicker_editTextChanged(self, path):
-        """
-        Private slot handling changes of the test suite path.
-        
-        @param path path of the test suite file
-        @type str
-        """
-        self.startFailedButton.setEnabled(False)
-    
-    @pyqtSlot(bool)
-    def on_discoverCheckBox_toggled(self, checked):
-        """
-        Private slot handling state changes of the 'discover' checkbox.
-        
-        @param checked state of the checkbox
-        @type bool
-        """
-        self.discoverButton.setEnabled(checked)
-        self.discoveryList.clear()
-        
-        if not bool(self.discoveryPicker.currentText()):
-            if self.__forProject:
-                project = ericApp().getObject("Project")
-                if project.isOpen():
-                    self.insertDiscovery(project.getProjectPath())
-                    return
-            
-            self.insertDiscovery(Preferences.getMultiProject("Workspace"))
-    
-    def on_buttonBox_clicked(self, button):
-        """
-        Private slot called by a button of the button box clicked.
-        
-        @param button button that was clicked (QAbstractButton)
-        """
-        if button == self.discoverButton:
-            self.__discover()
-            self.__saveRecent()
-        elif button == self.startButton:
-            self.startTests()
-            self.__saveRecent()
-        elif button == self.stopButton:
-            self.__stopTests()
-        elif button == self.startFailedButton:
-            self.startTests(failedOnly=True)
-    
-    def __loadRecent(self):
-        """
-        Private method to load the most recently used lists.
-        """
-        Preferences.Prefs.rsettings.sync()
-        
-        # 1. discovery history
-        self.discoverHistory = []
-        rs = Preferences.Prefs.rsettings.value(
-            recentNameUnittestDiscoverHistory)
-        if rs is not None:
-            recent = [f
-                      for f in Preferences.toList(rs)
-                      if QFileInfo(f).exists()]
-            self.discoverHistory = recent[
-                :Preferences.getDebugger("RecentNumber")]
-        
-        # 2. test file history
-        self.fileHistory = []
-        rs = Preferences.Prefs.rsettings.value(
-            recentNameUnittestFileHistory)
-        if rs is not None:
-            recent = [f
-                      for f in Preferences.toList(rs)
-                      if QFileInfo(f).exists()]
-            self.fileHistory = recent[
-                :Preferences.getDebugger("RecentNumber")]
-        
-        # 3. test name history
-        self.testNameHistory = []
-        rs = Preferences.Prefs.rsettings.value(
-            recentNameUnittestTestnameHistory)
-        if rs is not None:
-            recent = [n for n in Preferences.toList(rs) if n]
-            self.testNameHistory = recent[
-                :Preferences.getDebugger("RecentNumber")]
-    
-    def __saveRecent(self):
-        """
-        Private method to save the most recently used lists.
-        """
-        Preferences.Prefs.rsettings.setValue(
-            recentNameUnittestDiscoverHistory, self.discoverHistory)
-        Preferences.Prefs.rsettings.setValue(
-            recentNameUnittestFileHistory, self.fileHistory)
-        Preferences.Prefs.rsettings.setValue(
-            recentNameUnittestTestnameHistory, self.testNameHistory)
-        
-        Preferences.Prefs.rsettings.sync()
-    
-    @pyqtSlot()
-    def clearRecent(self):
-        """
-        Public slot to clear the recently used lists.
-        """
-        # clear histories
-        self.discoverHistory = []
-        self.fileHistory = []
-        self.testNameHistory = []
-        
-        # clear widgets with histories
-        self.discoveryPicker.clear()
-        self.testsuitePicker.clear()
-        self.testComboBox.clear()
-        
-        # sync histories
-        self.__saveRecent()
-    
-    @pyqtSlot()
-    def __discover(self):
-        """
-        Private slot to discover unit test but don't run them.
-        """
-        if self.running:
-            return
-        
-        self.discoveryList.clear()
-        
-        discoveryStart = self.discoveryPicker.currentText()
-        self.insertDiscovery(discoveryStart)
-        self.sbLabel.setText(self.tr("Discovering Tests"))
-        QApplication.processEvents()
-        
-        self.testName = self.tr("Unittest with auto-discovery")
-        if self.__dbs:
-            venvName = self.venvComboBox.currentText()
-            
-            # we are cooperating with the eric IDE
-            project = ericApp().getObject("Project")
-            if self.__forProject:
-                mainScript = project.getMainScript(True)
-                clientType = project.getProjectLanguage()
-                if mainScript:
-                    workdir = os.path.dirname(os.path.abspath(mainScript))
-                else:
-                    workdir = project.getProjectPath()
-                sysPath = [workdir]
-                if not discoveryStart:
-                    discoveryStart = workdir
-            else:
-                if not discoveryStart:
-                    EricMessageBox.critical(
-                        self,
-                        self.tr("Unittest"),
-                        self.tr("You must enter a start directory for"
-                                " auto-discovery."))
-                    return
-                
-                workdir = ""
-                clientType = "Python3"
-                sysPath = []
-            self.__dbs.remoteUTDiscover(clientType, self.__forProject,
-                                        venvName, sysPath, workdir,
-                                        discoveryStart)
-        else:
-            # we are running as an application
-            if not discoveryStart:
-                EricMessageBox.critical(
-                    self,
-                    self.tr("Unittest"),
-                    self.tr("You must enter a start directory for"
-                            " auto-discovery."))
-                return
-            
-            if discoveryStart:
-                sys.path = (
-                    [os.path.abspath(discoveryStart)] +
-                    self.savedSysPath
-                )
-            
-            # clean up list of imported modules to force a reimport upon
-            # running the test
-            if self.savedModulelist:
-                for modname in list(sys.modules.keys()):
-                    if modname not in self.savedModulelist:
-                        # delete it
-                        del(sys.modules[modname])
-            self.savedModulelist = sys.modules.copy()
-            
-            # now try to discover the testsuite
-            os.chdir(discoveryStart)
-            try:
-                testLoader = unittest.TestLoader()
-                test = testLoader.discover(discoveryStart)
-                if hasattr(testLoader, "errors") and bool(testLoader.errors):
-                    EricMessageBox.critical(
-                        self,
-                        self.tr("Unittest"),
-                        self.tr(
-                            "<p>Unable to discover tests.</p>"
-                            "<p>{0}</p>"
-                        ).format("<br/>".join(testLoader.errors)
-                                 .replace("\n", "<br/>"))
-                    )
-                    self.sbLabel.clear()
-                else:
-                    testsList = self.__assembleTestCasesList(
-                        test, discoveryStart)
-                    self.__populateDiscoveryResults(testsList)
-                    self.sbLabel.setText(
-                        self.tr("Discovered %n Test(s)", "",
-                                len(testsList)))
-                    self.tabWidget.setCurrentIndex(0)
-            except Exception:
-                exc_type, exc_value, exc_tb = sys.exc_info()
-                EricMessageBox.critical(
-                    self,
-                    self.tr("Unittest"),
-                    self.tr(
-                        "<p>Unable to discover tests.</p>"
-                        "<p>{0}<br/>{1}</p>")
-                    .format(str(exc_type),
-                            str(exc_value).replace("\n", "<br/>"))
-                )
-                self.sbLabel.clear()
-            
-            sys.path = self.savedSysPath
-    
-    def __assembleTestCasesList(self, suite, start):
-        """
-        Private method to assemble a list of test cases included in a test
-        suite.
-        
-        @param suite test suite to be inspected
-        @type unittest.TestSuite
-        @param start name of directory discovery was started at
-        @type str
-        @return list of tuples containing the test case ID, a short description
-            and the path of the test file name
-        @rtype list of tuples of (str, str, str)
-        """
-        testCases = []
-        for test in suite:
-            if isinstance(test, unittest.TestSuite):
-                testCases.extend(self.__assembleTestCasesList(test, start))
-            else:
-                testId = test.id()
-                if (
-                    "ModuleImportFailure" not in testId and
-                    "LoadTestsFailure" not in testId and
-                    "_FailedTest" not in testId
-                ):
-                    filename = os.path.join(
-                        start,
-                        test.__module__.replace(".", os.sep) + ".py")
-                    testCases.append(
-                        (test.id(), test.shortDescription(), filename)
-                    )
-        return testCases
-    
-    def __findDiscoveryItem(self, modulePath):
-        """
-        Private method to find an item given the module path.
-        
-        @param modulePath path of the module in dotted notation
-        @type str
-        @return reference to the item or None
-        @rtype QTreeWidgetItem or None
-        """
-        itm = self.discoveryList.topLevelItem(0)
-        while itm is not None:
-            if itm.data(0, UnittestDialog.TestCaseNameRole) == modulePath:
-                return itm
-            itm = self.discoveryList.itemBelow(itm)
-        
-        return None
-    
-    def __populateDiscoveryResults(self, tests):
-        """
-        Private method to populate the test discovery results list.
-        
-        @param tests list of tuples containing the discovery results
-        @type list of tuples of (str, str, str)
-        """
-        for test, _testDescription, filename in tests:
-            testPath = test.split(".")
-            pitm = None
-            for index in range(1, len(testPath) + 1):
-                modulePath = ".".join(testPath[:index])
-                itm = self.__findDiscoveryItem(modulePath)
-                if itm is not None:
-                    pitm = itm
-                else:
-                    if pitm is None:
-                        itm = QTreeWidgetItem(self.discoveryList,
-                                              [testPath[index - 1]])
-                    else:
-                        itm = QTreeWidgetItem(pitm,
-                                              [testPath[index - 1]])
-                        pitm.setExpanded(True)
-                    itm.setFlags(Qt.ItemFlag.ItemIsUserCheckable |
-                                 Qt.ItemFlag.ItemIsEnabled)
-                    itm.setCheckState(0, Qt.CheckState.Unchecked)
-                    itm.setData(0, UnittestDialog.TestCaseNameRole, modulePath)
-                    if (
-                        os.path.splitext(os.path.basename(filename))[0] ==
-                        itm.text(0)
-                    ):
-                        itm.setData(0, UnittestDialog.TestCaseFileRole,
-                                    filename)
-                    elif pitm:
-                        fn = pitm.data(0, UnittestDialog.TestCaseFileRole)
-                        if fn:
-                            itm.setData(0, UnittestDialog.TestCaseFileRole, fn)
-                    pitm = itm
-    
-    def __selectedTestCases(self, parent=None):
-        """
-        Private method to assemble the list of selected test cases and suites.
-        
-        @param parent reference to the parent item
-        @type QTreeWidgetItem
-        @return list of selected test cases
-        @rtype list of str
-        """
-        selectedTests = []
-        itemsList = [
-            self.discoveryList.topLevelItem(index)
-            for index in range(self.discoveryList.topLevelItemCount())
-        ] if parent is None else [
-            parent.child(index)
-            for index in range(parent.childCount())
-        ]
-        
-        for itm in itemsList:
-            if (
-                itm.checkState(0) == Qt.CheckState.Checked and
-                itm.childCount() == 0
-            ):
-                selectedTests.append(
-                    itm.data(0, UnittestDialog.TestCaseNameRole))
-            if itm.childCount():
-                # recursively check children
-                selectedTests.extend(self.__selectedTestCases(itm))
-        
-        return selectedTests
-    
-    def __UTDiscovered(self, testCases, exc_type, exc_value):
-        """
-        Private slot to handle the utDiscovered signal.
-        
-        If the unittest suite was loaded successfully, we ask the
-        client to run the test suite.
-        
-        @param testCases list of detected test cases
-        @type str
-        @param exc_type exception type occured during discovery
-        @type str
-        @param exc_value value of exception occured during discovery
-        @type str
-        """
-        if testCases:
-            self.__populateDiscoveryResults(testCases)
-            self.sbLabel.setText(
-                self.tr("Discovered %n Test(s)", "",
-                        len(testCases)))
-            self.tabWidget.setCurrentIndex(0)
-        else:
-            EricMessageBox.critical(
-                self,
-                self.tr("Unittest"),
-                self.tr("<p>Unable to discover tests.</p>"
-                        "<p>{0}<br/>{1}</p>")
-                .format(exc_type, exc_value.replace("\n", "<br/>"))
-            )
-    
-    @pyqtSlot(QTreeWidgetItem, int)
-    def on_discoveryList_itemChanged(self, item, column):
-        """
-        Private slot handling the user checking or unchecking an item.
-
-        @param item reference to the item
-        @type QTreeWidgetItem
-        @param column changed column
-        @type int
-        """
-        if column == 0:
-            for index in range(item.childCount()):
-                item.child(index).setCheckState(0, item.checkState(0))
-
-    @pyqtSlot(QTreeWidgetItem, int)
-    def on_discoveryList_itemDoubleClicked(self, item, column):
-        """
-        Private slot handling the user double clicking an item.
-        
-        @param item reference to the item
-        @type QTreeWidgetItem
-        @param column column of the double click
-        @type int
-        """
-        if item:
-            filename = item.data(0, UnittestDialog.TestCaseFileRole)
-            if filename:
-                if self.__dbs:
-                    # running as part of eric IDE
-                    self.unittestFile.emit(filename, 1, False)
-                else:
-                    self.__openEditor(filename, 1)
-    
-    @pyqtSlot()
-    def startTests(self, failedOnly=False):
-        """
-        Public slot to start the test.
-        
-        @param failedOnly flag indicating to run only failed tests (boolean)
-        """
-        if self.running:
-            return
-        
-        discover = self.discoverCheckBox.isChecked()
-        if discover:
-            discoveryStart = self.discoveryPicker.currentText()
-            testFileName = ""
-            testName = ""
-            
-            if discoveryStart:
-                self.insertDiscovery(discoveryStart)
-        else:
-            discoveryStart = ""
-            testFileName = self.testsuitePicker.currentText()
-            testName = self.testComboBox.currentText()
-            if testName:
-                self.insertTestName(testName)
-            if testFileName and not testName:
-                testName = "suite"
-        
-        if not discover and not testFileName and not testName:
-            EricMessageBox.critical(
-                self,
-                self.tr("Unittest"),
-                self.tr("You must select auto-discovery or enter a test suite"
-                        " file or a dotted test name."))
-            return
-        
-        # prepend the selected file to the testsuite combobox
-        self.insertProg(testFileName)
-        self.sbLabel.setText(self.tr("Preparing Testsuite"))
-        QApplication.processEvents()
-        
-        if discover:
-            self.testName = self.tr("Unittest with auto-discovery")
-        else:
-            # build the module name from the filename without extension
-            if testFileName:
-                self.testName = os.path.splitext(
-                    os.path.basename(testFileName))[0]
-            elif testName:
-                self.testName = testName
-            else:
-                self.testName = self.tr("<Unnamed Test>")
-        
-        if failedOnly:
-            testCases = []
-        else:
-            testCases = self.__selectedTestCases()
-        
-            if not testCases and self.discoveryList.topLevelItemCount():
-                ok = EricMessageBox.yesNo(
-                    self,
-                    self.tr("Unittest"),
-                    self.tr("""No test case has been selected. Shall all"""
-                            """ test cases be run?"""))
-                if not ok:
-                    return
-        
-        if self.__dbs:
-            venvName = self.venvComboBox.currentText()
-            
-            # we are cooperating with the eric IDE
-            project = ericApp().getObject("Project")
-            if self.__forProject:
-                mainScript = project.getMainScript(True)
-                clientType = project.getProjectLanguage()
-                if mainScript:
-                    workdir = os.path.dirname(os.path.abspath(mainScript))
-                    coverageFile = os.path.splitext(mainScript)[0]
-                else:
-                    workdir = project.getProjectPath()
-                    coverageFile = os.path.join(discoveryStart, "unittest")
-                sysPath = [workdir]
-                if discover and not discoveryStart:
-                    discoveryStart = workdir
-            else:
-                if discover:
-                    if not discoveryStart:
-                        EricMessageBox.critical(
-                            self,
-                            self.tr("Unittest"),
-                            self.tr("You must enter a start directory for"
-                                    " auto-discovery."))
-                        return
-                    
-                    coverageFile = os.path.join(discoveryStart, "unittest")
-                    workdir = ""
-                    clientType = "Python3"
-                elif testFileName:
-                    mainScript = os.path.abspath(testFileName)
-                    workdir = os.path.dirname(mainScript)
-                    clientType = "Python3"
-                    coverageFile = os.path.splitext(mainScript)[0]
-                else:
-                    coverageFile = os.path.abspath("unittest")
-                    workdir = ""
-                    clientType = "Python3"
-                sysPath = []
-            if failedOnly and self.__failedTests:
-                failed = list(self.__failedTests)
-                if discover:
-                    workdir = discoveryStart
-                    discover = False
-            else:
-                failed = []
-            self.__failedTests = set()
-            self.__dbs.remoteUTPrepare(
-                testFileName, self.testName, testName, failed,
-                self.coverageCheckBox.isChecked(), coverageFile,
-                self.coverageEraseCheckBox.isChecked(), clientType=clientType,
-                forProject=self.__forProject, workdir=workdir,
-                venvName=venvName, syspath=sysPath,
-                discover=discover, discoveryStart=discoveryStart,
-                testCases=testCases, debug=self.debuggerCheckBox.isChecked())
-        else:
-            # we are running as an application
-            if discover and not discoveryStart:
-                EricMessageBox.critical(
-                    self,
-                    self.tr("Unittest"),
-                    self.tr("You must enter a start directory for"
-                            " auto-discovery."))
-                return
-            
-            if testFileName:
-                sys.path = (
-                    [os.path.dirname(os.path.abspath(testFileName))] +
-                    self.savedSysPath
-                )
-            elif discoveryStart:
-                sys.path = (
-                    [os.path.abspath(discoveryStart)] +
-                    self.savedSysPath
-                )
-            
-            # clean up list of imported modules to force a reimport upon
-            # running the test
-            if self.savedModulelist:
-                for modname in list(sys.modules.keys()):
-                    if modname not in self.savedModulelist:
-                        # delete it
-                        del(sys.modules[modname])
-            self.savedModulelist = sys.modules.copy()
-            
-            os.chdir(self.savedCwd)
-            
-            # now try to generate the testsuite
-            try:
-                testLoader = unittest.TestLoader()
-                if failedOnly and self.__failedTests:
-                    failed = list(self.__failedTests)
-                    if discover:
-                        os.chdir(discoveryStart)
-                        discover = False
-                else:
-                    failed = []
-                if discover:
-                    if testCases:
-                        test = testLoader.loadTestsFromNames(testCases)
-                    else:
-                        test = testLoader.discover(discoveryStart)
-                else:
-                    if testFileName:
-                        module = __import__(self.testName)
-                    else:
-                        module = None
-                    if failedOnly and self.__failedTests:
-                        if module:
-                            failed = [t.split(".", 1)[1]
-                                      for t in self.__failedTests]
-                        else:
-                            failed = list(self.__failedTests)
-                        test = testLoader.loadTestsFromNames(
-                            failed, module)
-                    else:
-                        test = testLoader.loadTestsFromName(
-                            testName, module)
-            except Exception:
-                exc_type, exc_value, exc_tb = sys.exc_info()
-                EricMessageBox.critical(
-                    self,
-                    self.tr("Unittest"),
-                    self.tr(
-                        "<p>Unable to run test <b>{0}</b>.</p>"
-                        "<p>{1}<br/>{2}</p>")
-                    .format(self.testName, str(exc_type),
-                            str(exc_value).replace("\n", "<br/>"))
-                )
-                return
-                
-            # now set up the coverage stuff
-            if self.coverageCheckBox.isChecked():
-                if discover:
-                    covname = os.path.join(discoveryStart, "unittest")
-                elif testFileName:
-                    covname = os.path.splitext(
-                        os.path.abspath(testFileName))[0]
-                else:
-                    covname = "unittest"
-                
-                from DebugClients.Python.coverage import coverage
-                cover = coverage(data_file="{0}.coverage".format(covname))
-                if self.coverageEraseCheckBox.isChecked():
-                    cover.erase()
-            else:
-                cover = None
-            
-            self.testResult = QtTestResult(
-                self, self.failfastCheckBox.isChecked())
-            self.totalTests = test.countTestCases()
-            if self.totalTests == 0:
-                EricMessageBox.warning(
-                    self,
-                    self.tr("Unittest"),
-                    self.tr("""No unittest were found. Aborting..."""))
-            else:
-                self.__failedTests = set()
-                self.__setRunningMode()
-                if cover:
-                    cover.start()
-                test.run(self.testResult)
-                if cover:
-                    cover.stop()
-                    cover.save()
-                self.__setStoppedMode()
-                sys.path = self.savedSysPath
-    
-    def __UTPrepared(self, nrTests, exc_type, exc_value):
-        """
-        Private slot to handle the utPrepared signal.
-        
-        If the unittest suite was loaded successfully, we ask the
-        client to run the test suite.
-        
-        @param nrTests number of tests contained in the test suite (integer)
-        @param exc_type type of exception occured during preparation (string)
-        @param exc_value value of exception occured during preparation (string)
-        """
-        if nrTests == 0:
-            EricMessageBox.critical(
-                self,
-                self.tr("Unittest"),
-                self.tr(
-                    "<p>Unable to run test <b>{0}</b>.</p>"
-                    "<p>{1}<br/>{2}</p>")
-                .format(self.testName, exc_type,
-                        exc_value.replace("\n", "<br/>"))
-            )
-            return
-        
-        self.totalTests = nrTests
-        self.__setRunningMode()
-        self.__dbs.remoteUTRun(debug=self.debuggerCheckBox.isChecked(),
-                               failfast=self.failfastCheckBox.isChecked())
-    
-    @pyqtSlot()
-    def __stopTests(self):
-        """
-        Private slot to stop the test.
-        """
-        if self.__dbs:
-            self.__dbs.remoteUTStop()
-        elif self.testResult:
-            self.testResult.stop()
-    
-    def on_errorsListWidget_currentTextChanged(self, text):
-        """
-        Private slot to handle the highlighted signal.
-        
-        @param text current text (string)
-        """
-        if text:
-            for pattern in self.rxPatterns:
-                text = re.sub(pattern, "", text)
-            
-            foundItems = self.testsListWidget.findItems(
-                text, Qt.MatchFlag.MatchExactly)
-            if len(foundItems) > 0:
-                itm = foundItems[0]
-                self.testsListWidget.setCurrentItem(itm)
-                self.testsListWidget.scrollToItem(itm)
-    
-    def __setRunningMode(self):
-        """
-        Private method to set the GUI in running mode.
-        """
-        self.running = True
-        self.tabWidget.setCurrentIndex(1)
-        
-        # reset counters and error infos
-        self.runCount = 0
-        self.failCount = 0
-        self.errorCount = 0
-        self.skippedCount = 0
-        self.expectedFailureCount = 0
-        self.unexpectedSuccessCount = 0
-        self.remainingCount = self.totalTests
-        
-        # reset the GUI
-        self.progressCounterRunCount.setText(str(self.runCount))
-        self.progressCounterRemCount.setText(str(self.remainingCount))
-        self.progressCounterFailureCount.setText(str(self.failCount))
-        self.progressCounterErrorCount.setText(str(self.errorCount))
-        self.progressCounterSkippedCount.setText(str(self.skippedCount))
-        self.progressCounterExpectedFailureCount.setText(
-            str(self.expectedFailureCount))
-        self.progressCounterUnexpectedSuccessCount.setText(
-            str(self.unexpectedSuccessCount))
-        
-        self.errorsListWidget.clear()
-        self.testsListWidget.clear()
-        
-        self.progressProgressBar.setRange(0, self.totalTests)
-        self.__setProgressColor("green")
-        self.progressProgressBar.reset()
-        
-        self.stopButton.setEnabled(True)
-        self.startButton.setEnabled(False)
-        self.startFailedButton.setEnabled(False)
-        self.stopButton.setDefault(True)
-        
-        self.sbLabel.setText(self.tr("Running"))
-        self.progressLed.on()
-        QApplication.processEvents()
-        
-        self.startTime = time.time()
-    
-    def __setStoppedMode(self):
-        """
-        Private method to set the GUI in stopped mode.
-        """
-        self.stopTime = time.time()
-        self.timeTaken = float(self.stopTime - self.startTime)
-        self.running = False
-        
-        failedAvailable = bool(self.__failedTests)
-        self.startButton.setEnabled(True)
-        self.startFailedButton.setEnabled(failedAvailable)
-        self.stopButton.setEnabled(False)
-        if failedAvailable:
-            self.startFailedButton.setDefault(True)
-            self.startButton.setDefault(False)
-        else:
-            self.startFailedButton.setDefault(False)
-            self.startButton.setDefault(True)
-        self.sbLabel.setText(
-            self.tr("Ran %n test(s) in {0:.3f}s", "", self.runCount)
-            .format(self.timeTaken))
-        self.progressLed.off()
-        
-        self.unittestStopped.emit()
-        
-        self.raise_()
-        self.activateWindow()
-    
-    def testFailed(self, test, exc, testId):
-        """
-        Public method called if a test fails.
-        
-        @param test name of the test (string)
-        @param exc string representation of the exception (string)
-        @param testId id of the test (string)
-        """
-        self.failCount += 1
-        self.progressCounterFailureCount.setText(str(self.failCount))
-        itm = QListWidgetItem(self.tr("Failure: {0}").format(test))
-        itm.setData(UnittestDialog.ErrorsInfoRole, (test, exc))
-        self.errorsListWidget.insertItem(0, itm)
-        self.__failedTests.add(testId)
-    
-    def testErrored(self, test, exc, testId):
-        """
-        Public method called if a test errors.
-        
-        @param test name of the test (string)
-        @param exc string representation of the exception (string)
-        @param testId id of the test (string)
-        """
-        self.errorCount += 1
-        self.progressCounterErrorCount.setText(str(self.errorCount))
-        itm = QListWidgetItem(self.tr("Error: {0}").format(test))
-        itm.setData(UnittestDialog.ErrorsInfoRole, (test, exc))
-        self.errorsListWidget.insertItem(0, itm)
-        self.__failedTests.add(testId)
-    
-    def testSkipped(self, test, reason, testId):
-        """
-        Public method called if a test was skipped.
-        
-        @param test name of the test (string)
-        @param reason reason for skipping the test (string)
-        @param testId id of the test (string)
-        """
-        self.skippedCount += 1
-        self.progressCounterSkippedCount.setText(str(self.skippedCount))
-        itm = QListWidgetItem(self.tr("    Skipped: {0}").format(reason))
-        if ericApp().usesDarkPalette():
-            itm.setForeground(self.SkippedColorDarkTheme)
-        else:
-            itm.setForeground(self.SkippedColorLightTheme)
-        self.testsListWidget.insertItem(1, itm)
-    
-    def testFailedExpected(self, test, exc, testId):
-        """
-        Public method called if a test fails as expected.
-        
-        @param test name of the test (string)
-        @param exc string representation of the exception (string)
-        @param testId id of the test (string)
-        """
-        self.expectedFailureCount += 1
-        self.progressCounterExpectedFailureCount.setText(
-            str(self.expectedFailureCount))
-        itm = QListWidgetItem(self.tr("    Expected Failure"))
-        if ericApp().usesDarkPalette():
-            itm.setForeground(self.FailedExpectedColorDarkTheme)
-        else:
-            itm.setForeground(self.FailedExpectedColorLightTheme)
-        self.testsListWidget.insertItem(1, itm)
-    
-    def testSucceededUnexpected(self, test, testId):
-        """
-        Public method called if a test succeeds unexpectedly.
-        
-        @param test name of the test (string)
-        @param testId id of the test (string)
-        """
-        self.unexpectedSuccessCount += 1
-        self.progressCounterUnexpectedSuccessCount.setText(
-            str(self.unexpectedSuccessCount))
-        itm = QListWidgetItem(self.tr("    Unexpected Success"))
-        if ericApp().usesDarkPalette():
-            itm.setForeground(self.SucceededUnexpectedColorDarkTheme)
-        else:
-            itm.setForeground(self.SucceededUnexpectedColorLightTheme)
-        self.testsListWidget.insertItem(1, itm)
-    
-    def testStarted(self, test, doc):
-        """
-        Public method called if a test is about to be run.
-        
-        @param test name of the started test (string)
-        @param doc documentation of the started test (string)
-        """
-        if doc:
-            self.testsListWidget.insertItem(0, "    {0}".format(doc))
-        self.testsListWidget.insertItem(0, test)
-        if self.__dbs is None:
-            QApplication.processEvents()
-    
-    def testFinished(self):
-        """
-        Public method called if a test has finished.
-        
-        <b>Note</b>: It is also called if it has already failed or errored.
-        """
-        # update the counters
-        self.remainingCount -= 1
-        self.runCount += 1
-        self.progressCounterRunCount.setText(str(self.runCount))
-        self.progressCounterRemCount.setText(str(self.remainingCount))
-        
-        # update the progressbar
-        if self.errorCount:
-            self.__setProgressColor("red")
-        elif self.failCount:
-            self.__setProgressColor("orange")
-        self.progressProgressBar.setValue(self.runCount)
-    
-    def on_errorsListWidget_itemDoubleClicked(self, lbitem):
-        """
-        Private slot called by doubleclicking an errorlist entry.
-        
-        It will popup a dialog showing the stacktrace.
-        If called from eric, an additional button is displayed
-        to show the python source in an eric source viewer (in
-        erics main window.
-        
-        @param lbitem the listbox item that was double clicked
-        """
-        self.errListIndex = self.errorsListWidget.row(lbitem)
-        text = lbitem.text()
-        self.on_errorsListWidget_currentTextChanged(text)
-        
-        # get the error info
-        test, tracebackText = lbitem.data(UnittestDialog.ErrorsInfoRole)
-        
-        # now build the dialog
-        from .Ui_UnittestStacktraceDialog import Ui_UnittestStacktraceDialog
-        self.dlg = QDialog(self)
-        ui = Ui_UnittestStacktraceDialog()
-        ui.setupUi(self.dlg)
-        self.dlg.traceback = ui.traceback
-        
-        ui.showButton = ui.buttonBox.addButton(
-            self.tr("Show Source"), QDialogButtonBox.ButtonRole.ActionRole)
-        ui.showButton.clicked.connect(self.__showSource)
-        
-        ui.buttonBox.button(
-            QDialogButtonBox.StandardButton.Close).setDefault(True)
-        
-        self.dlg.setWindowTitle(text)
-        ui.testLabel.setText(test)
-        ui.traceback.setPlainText(tracebackText)
-        
-        # and now fire it up
-        self.dlg.show()
-        self.dlg.exec()
-    
-    def __showSource(self):
-        """
-        Private slot to show the source of a traceback in an eric editor.
-        """
-        # get the error info
-        tracebackLines = self.dlg.traceback.toPlainText().splitlines()
-        # find the last entry matching the pattern
-        for index in range(len(tracebackLines) - 1, -1, -1):
-            fmatch = re.search(r'File "(.*?)", line (\d*?),.*',
-                               tracebackLines[index])
-            if fmatch:
-                break
-        if fmatch:
-            fn, ln = fmatch.group(1, 2)
-            if self.__dbs:
-                # running as part of eric IDE
-                self.unittestFile.emit(fn, int(ln), True)
-            else:
-                self.__openEditor(fn, int(ln))
-    
-    def hasFailedTests(self):
-        """
-        Public method to check, if there are failed tests from the last run.
-        
-        @return flag indicating the presence of failed tests (boolean)
-        """
-        return bool(self.__failedTests)
-    
-    def __openEditor(self, filename, linenumber):
-        """
-        Private method to open an editor window for the given file.
-        
-        Note: This method opens an editor window when the unittest dialog
-        is called as a standalone application.
-        
-        @param filename path of the file to be opened
-        @type str
-        @param linenumber line number to place the cursor at
-        @type int
-        """
-        from QScintilla.MiniEditor import MiniEditor
-        editor = MiniEditor(filename, "Python3", self)
-        editor.gotoLine(linenumber)
-        editor.show()
-        
-        self.__editors.append(editor)
-    
-    def closeEvent(self, event):
-        """
-        Protected method to handle the close event.
-        
-        @param event close event
-        @type QCloseEvent
-        """
-        event.accept()
-        
-        for editor in self.__editors:
-            with contextlib.suppress(Exception):
-                editor.close()
-
-
-class QtTestResult(unittest.TestResult):
-    """
-    A TestResult derivative to work with a graphical GUI.
-    
-    For more details see pyunit.py of the standard Python distribution.
-    """
-    def __init__(self, parent, failfast):
-        """
-        Constructor
-        
-        @param parent reference to the parent widget
-        @type UnittestDialog
-        @param failfast flag indicating to stop at the first error
-        @type bool
-        """
-        super().__init__()
-        self.parent = parent
-        self.failfast = failfast
-    
-    def addFailure(self, test, err):
-        """
-        Public method called if a test failed.
-        
-        @param test reference to the test object
-        @param err error traceback
-        """
-        super().addFailure(test, err)
-        tracebackLines = self._exc_info_to_string(err, test)
-        self.parent.testFailed(str(test), tracebackLines, test.id())
-    
-    def addError(self, test, err):
-        """
-        Public method called if a test errored.
-        
-        @param test reference to the test object
-        @param err error traceback
-        """
-        super().addError(test, err)
-        tracebackLines = self._exc_info_to_string(err, test)
-        self.parent.testErrored(str(test), tracebackLines, test.id())
-    
-    def addSubTest(self, test, subtest, err):
-        """
-        Public method called for each subtest to record its result.
-        
-        @param test reference to the test object
-        @param subtest reference to the subtest object
-        @param err error traceback
-        """
-        if err is not None:
-            super().addSubTest(test, subtest, err)
-            tracebackLines = self._exc_info_to_string(err, test)
-            if issubclass(err[0], test.failureException):
-                self.parent.testFailed(
-                    str(subtest), tracebackLines, test.id())
-            else:
-                self.parent.testErrored(
-                    str(subtest), tracebackLines, test.id())
-    
-    def addSkip(self, test, reason):
-        """
-        Public method called if a test was skipped.
-        
-        @param test reference to the test object
-        @param reason reason for skipping the test (string)
-        """
-        super().addSkip(test, reason)
-        self.parent.testSkipped(str(test), reason, test.id())
-    
-    def addExpectedFailure(self, test, err):
-        """
-        Public method called if a test failed expected.
-        
-        @param test reference to the test object
-        @param err error traceback
-        """
-        super().addExpectedFailure(test, err)
-        tracebackLines = self._exc_info_to_string(err, test)
-        self.parent.testFailedExpected(str(test), tracebackLines, test.id())
-    
-    def addUnexpectedSuccess(self, test):
-        """
-        Public method called if a test succeeded expectedly.
-        
-        @param test reference to the test object
-        """
-        super().addUnexpectedSuccess(test)
-        self.parent.testSucceededUnexpected(str(test), test.id())
-    
-    def startTest(self, test):
-        """
-        Public method called at the start of a test.
-        
-        @param test Reference to the test object
-        """
-        super().startTest(test)
-        self.parent.testStarted(str(test), test.shortDescription())
-
-    def stopTest(self, test):
-        """
-        Public method called at the end of a test.
-        
-        @param test Reference to the test object
-        """
-        super().stopTest(test)
-        self.parent.testFinished()
-
-
-class UnittestWindow(EricMainWindow):
-    """
-    Main window class for the standalone dialog.
-    """
-    def __init__(self, prog=None, parent=None):
-        """
-        Constructor
-        
-        @param prog filename of the program to open
-        @param parent reference to the parent widget (QWidget)
-        """
-        super().__init__(parent)
-        self.cw = UnittestDialog(prog, parent=self)
-        self.cw.installEventFilter(self)
-        size = self.cw.size()
-        self.setCentralWidget(self.cw)
-        self.resize(size)
-        
-        self.setStyle(Preferences.getUI("Style"),
-                      Preferences.getUI("StyleSheet"))
-        
-        self.cw.buttonBox.accepted.connect(self.close)
-        self.cw.buttonBox.rejected.connect(self.close)
-    
-    def eventFilter(self, obj, event):
-        """
-        Public method to filter events.
-        
-        @param obj reference to the object the event is meant for (QObject)
-        @param event reference to the event object (QEvent)
-        @return flag indicating, whether the event was handled (boolean)
-        """
-        if event.type() == QEvent.Type.Close:
-            QApplication.exit()
-            return True
-        
-        return False
-
-
-def clearSavedHistories(self):
-    """
-    Function to clear the saved history lists.
-    """
-    Preferences.Prefs.rsettings.setValue(
-        recentNameUnittestDiscoverHistory, [])
-    Preferences.Prefs.rsettings.setValue(
-        recentNameUnittestFileHistory, [])
-    Preferences.Prefs.rsettings.setValue(
-        recentNameUnittestTestnameHistory, [])
-    
-    Preferences.Prefs.rsettings.sync()
--- a/eric7/PyUnit/UnittestDialog.ui	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,694 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>UnittestDialog</class>
- <widget class="QWidget" name="UnittestDialog">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>650</width>
-    <height>700</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>Unittest</string>
-  </property>
-  <layout class="QVBoxLayout" name="verticalLayout_5">
-   <item>
-    <widget class="QTabWidget" name="tabWidget">
-     <property name="currentIndex">
-      <number>0</number>
-     </property>
-     <widget class="QWidget" name="parametersTab">
-      <attribute name="title">
-       <string>Parameters</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_6">
-       <item>
-        <widget class="QGroupBox" name="groupBox">
-         <property name="title">
-          <string>Test Parameters</string>
-         </property>
-         <layout class="QGridLayout" name="gridLayout">
-          <item row="0" column="0" colspan="2">
-           <layout class="QHBoxLayout" name="horizontalLayout_4">
-            <item>
-             <widget class="QCheckBox" name="discoverCheckBox">
-              <property name="sizePolicy">
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-                <horstretch>0</horstretch>
-                <verstretch>0</verstretch>
-               </sizepolicy>
-              </property>
-              <property name="toolTip">
-               <string>Select to discover tests automatically</string>
-              </property>
-              <property name="text">
-               <string>&amp;Discover tests (test modules must be importable)</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QToolButton" name="clearHistoriesButton">
-              <property name="toolTip">
-               <string>Press to clear the various histories</string>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </item>
-          <item row="1" column="0">
-           <widget class="QLabel" name="label_3">
-            <property name="text">
-             <string>Discovery &amp;Start:</string>
-            </property>
-            <property name="buddy">
-             <cstring>discoveryPicker</cstring>
-            </property>
-           </widget>
-          </item>
-          <item row="1" column="1">
-           <widget class="EricComboPathPicker" name="discoveryPicker" native="true">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-            <property name="sizePolicy">
-             <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-              <horstretch>0</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="focusPolicy">
-             <enum>Qt::WheelFocus</enum>
-            </property>
-            <property name="toolTip">
-             <string>Enter name of the directory at which to start the test file discovery</string>
-            </property>
-            <property name="whatsThis">
-             <string>&lt;b&gt;Discovery Start&lt;/b&gt;
-&lt;p&gt;Enter name of the directory at which to start the test file discovery.
-Note that all test modules must be importable from this directory.&lt;/p&gt;</string>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="0">
-           <widget class="QLabel" name="testsuiteLabel">
-            <property name="text">
-             <string>Test &amp;Filename:</string>
-            </property>
-            <property name="buddy">
-             <cstring>testsuitePicker</cstring>
-            </property>
-           </widget>
-          </item>
-          <item row="2" column="1">
-           <widget class="EricComboPathPicker" name="testsuitePicker" native="true">
-            <property name="sizePolicy">
-             <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
-              <horstretch>0</horstretch>
-              <verstretch>0</verstretch>
-             </sizepolicy>
-            </property>
-            <property name="focusPolicy">
-             <enum>Qt::WheelFocus</enum>
-            </property>
-            <property name="toolTip">
-             <string>Enter name of file defining the testsuite</string>
-            </property>
-            <property name="whatsThis">
-             <string>&lt;b&gt;Testsuite&lt;/b&gt;
-&lt;p&gt;Enter the name of the file defining the testsuite.
-It should have a method with a name given below. If no name is given, the suite() method will be tried. If no such method can be
-found, the module will be inspected for proper test
-cases.&lt;/p&gt;</string>
-            </property>
-           </widget>
-          </item>
-          <item row="3" column="0">
-           <widget class="QLabel" name="label">
-            <property name="text">
-             <string>&amp;Test Name:</string>
-            </property>
-            <property name="buddy">
-             <cstring>testComboBox</cstring>
-            </property>
-           </widget>
-          </item>
-          <item row="3" column="1">
-           <widget class="QComboBox" name="testComboBox">
-            <property name="toolTip">
-             <string>Enter the test name. Leave empty to use the default name &quot;suite&quot;.</string>
-            </property>
-            <property name="whatsThis">
-             <string>&lt;b&gt;Testname&lt;/b&gt;&lt;p&gt;Enter the name of the test to be performed. This name must follow the rules given by Python's unittest module. If this field is empty, the default name of &quot;suite&quot; will be used.&lt;/p&gt;</string>
-            </property>
-            <property name="editable">
-             <bool>true</bool>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </widget>
-       </item>
-       <item>
-        <widget class="QGroupBox" name="optionsGroup">
-         <property name="title">
-          <string>Run Parameters</string>
-         </property>
-         <layout class="QVBoxLayout" name="verticalLayout_2">
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_3">
-            <item>
-             <widget class="QLabel" name="venvLabel">
-              <property name="text">
-               <string>&amp;Virtual Environment:</string>
-              </property>
-              <property name="buddy">
-               <cstring>venvComboBox</cstring>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QComboBox" name="venvComboBox">
-              <property name="sizePolicy">
-               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
-                <horstretch>0</horstretch>
-                <verstretch>0</verstretch>
-               </sizepolicy>
-              </property>
-              <property name="toolTip">
-               <string>Select the virtual environment to be used</string>
-              </property>
-              <property name="whatsThis">
-               <string>&lt;b&gt;Virtual Environment&lt;/b&gt;\n&lt;p&gt;Enter the virtual environment to be used. Leave it empty to use the default environment, i.e. the one configured globally or per project.&lt;/p&gt;</string>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QGridLayout" name="gridLayout_2">
-            <item row="0" column="0">
-             <widget class="QCheckBox" name="coverageCheckBox">
-              <property name="toolTip">
-               <string>Select whether coverage data should be collected</string>
-              </property>
-              <property name="text">
-               <string>C&amp;ollect coverage data</string>
-              </property>
-             </widget>
-            </item>
-            <item row="0" column="1">
-             <widget class="QCheckBox" name="coverageEraseCheckBox">
-              <property name="enabled">
-               <bool>false</bool>
-              </property>
-              <property name="toolTip">
-               <string>Select whether old coverage data should be erased</string>
-              </property>
-              <property name="text">
-               <string>&amp;Erase coverage data</string>
-              </property>
-             </widget>
-            </item>
-            <item row="1" column="0">
-             <widget class="QCheckBox" name="failfastCheckBox">
-              <property name="toolTip">
-               <string>Select to stop the test run on the first error or failure</string>
-              </property>
-              <property name="text">
-               <string>Stop on First Error or Failure</string>
-              </property>
-             </widget>
-            </item>
-            <item row="1" column="1">
-             <widget class="QCheckBox" name="debuggerCheckBox">
-              <property name="toolTip">
-               <string>Select to run the unittest with debugger support enabled</string>
-              </property>
-              <property name="text">
-               <string>Run with Debugger</string>
-              </property>
-             </widget>
-            </item>
-           </layout>
-          </item>
-         </layout>
-        </widget>
-       </item>
-       <item>
-        <widget class="QGroupBox" name="discoveryGroup">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="title">
-          <string>Discovery Results</string>
-         </property>
-         <layout class="QVBoxLayout" name="verticalLayout_3">
-          <item>
-           <widget class="QTreeWidget" name="discoveryList">
-            <property name="alternatingRowColors">
-             <bool>true</bool>
-            </property>
-            <property name="sortingEnabled">
-             <bool>true</bool>
-            </property>
-            <property name="headerHidden">
-             <bool>true</bool>
-            </property>
-            <property name="expandsOnDoubleClick">
-             <bool>false</bool>
-            </property>
-            <column>
-             <property name="text">
-              <string notr="true">1</string>
-             </property>
-            </column>
-           </widget>
-          </item>
-         </layout>
-        </widget>
-       </item>
-      </layout>
-     </widget>
-     <widget class="QWidget" name="resultsTab">
-      <attribute name="title">
-       <string>Results</string>
-      </attribute>
-      <layout class="QVBoxLayout" name="verticalLayout_4">
-       <item>
-        <widget class="QGroupBox" name="progressGroupBox">
-         <property name="title">
-          <string>Progress</string>
-         </property>
-         <layout class="QVBoxLayout" name="verticalLayout">
-          <item>
-           <layout class="QHBoxLayout" name="_8">
-            <item>
-             <widget class="QLabel" name="progressTextLabel">
-              <property name="text">
-               <string>Progress:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <spacer>
-              <property name="orientation">
-               <enum>Qt::Horizontal</enum>
-              </property>
-              <property name="sizeHint" stdset="0">
-               <size>
-                <width>371</width>
-                <height>20</height>
-               </size>
-              </property>
-             </spacer>
-            </item>
-            <item>
-             <widget class="EricLed" name="progressLed"/>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <widget class="QProgressBar" name="progressProgressBar">
-            <property name="value">
-             <number>0</number>
-            </property>
-            <property name="orientation">
-             <enum>Qt::Horizontal</enum>
-            </property>
-            <property name="format">
-             <string>%v/%m Tests</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout_2">
-            <item>
-             <widget class="QLabel" name="progressCounterRunLabel">
-              <property name="text">
-               <string>Run:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterRunCount">
-              <property name="toolTip">
-               <string>Number of tests run</string>
-              </property>
-              <property name="text">
-               <string notr="true">0</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterRemLabel">
-              <property name="text">
-               <string>Remaining:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterRemCount">
-              <property name="toolTip">
-               <string>Number of tests to be run</string>
-              </property>
-              <property name="text">
-               <string notr="true">0</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <spacer name="horizontalSpacer">
-              <property name="orientation">
-               <enum>Qt::Horizontal</enum>
-              </property>
-              <property name="sizeHint" stdset="0">
-               <size>
-                <width>40</width>
-                <height>20</height>
-               </size>
-              </property>
-             </spacer>
-            </item>
-           </layout>
-          </item>
-          <item>
-           <layout class="QHBoxLayout" name="horizontalLayout">
-            <item>
-             <widget class="QLabel" name="progressCounterFailureLabel">
-              <property name="text">
-               <string>Failures:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterFailureCount">
-              <property name="toolTip">
-               <string>Number of test failures</string>
-              </property>
-              <property name="text">
-               <string notr="true">0</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterErrorLabel">
-              <property name="text">
-               <string>Errors:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterErrorCount">
-              <property name="toolTip">
-               <string>Number of test errors</string>
-              </property>
-              <property name="text">
-               <string notr="true">0</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterSkippedLabel">
-              <property name="text">
-               <string>Skipped:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterSkippedCount">
-              <property name="toolTip">
-               <string>Number of tests skipped</string>
-              </property>
-              <property name="text">
-               <string notr="true">0</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterExpectedFailureLabel">
-              <property name="text">
-               <string>Expected Failures:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterExpectedFailureCount">
-              <property name="toolTip">
-               <string>Number of tests with expected failure</string>
-              </property>
-              <property name="text">
-               <string notr="true">0</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterUnexpectedSuccessLabel">
-              <property name="text">
-               <string>Unexpected Successes:</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <widget class="QLabel" name="progressCounterUnexpectedSuccessCount">
-              <property name="toolTip">
-               <string>Number of tests with unexpected success</string>
-              </property>
-              <property name="text">
-               <string notr="true">0</string>
-              </property>
-             </widget>
-            </item>
-            <item>
-             <spacer>
-              <property name="orientation">
-               <enum>Qt::Horizontal</enum>
-              </property>
-              <property name="sizeType">
-               <enum>QSizePolicy::Expanding</enum>
-              </property>
-              <property name="sizeHint" stdset="0">
-               <size>
-                <width>20</width>
-                <height>20</height>
-               </size>
-              </property>
-             </spacer>
-            </item>
-           </layout>
-          </item>
-         </layout>
-        </widget>
-       </item>
-       <item>
-        <widget class="QLabel" name="textLabel1">
-         <property name="text">
-          <string>Tests performed:</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QListWidget" name="testsListWidget"/>
-       </item>
-       <item>
-        <widget class="QLabel" name="listboxLabel">
-         <property name="text">
-          <string>Failures and errors:</string>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QListWidget" name="errorsListWidget">
-         <property name="toolTip">
-          <string>Failures and Errors list</string>
-         </property>
-         <property name="whatsThis">
-          <string>&lt;b&gt;Failures and Errors list&lt;/b&gt;
-&lt;p&gt;This list shows all failed and errored tests.
-Double clicking on an entry will show the respective traceback.&lt;/p&gt;</string>
-         </property>
-        </widget>
-       </item>
-      </layout>
-     </widget>
-    </widget>
-   </item>
-   <item>
-    <widget class="QDialogButtonBox" name="buttonBox">
-     <property name="orientation">
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="standardButtons">
-      <set>QDialogButtonBox::Close</set>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <layout class="QHBoxLayout" name="_3">
-     <item>
-      <widget class="QLabel" name="sbLabel">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="text">
-        <string>Idle</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <spacer>
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeType">
-        <enum>QSizePolicy::Expanding</enum>
-       </property>
-       <property name="sizeHint" stdset="0">
-        <size>
-         <width>20</width>
-         <height>20</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-    </layout>
-   </item>
-  </layout>
- </widget>
- <customwidgets>
-  <customwidget>
-   <class>EricComboPathPicker</class>
-   <extends>QWidget</extends>
-   <header>EricWidgets/EricPathPicker.h</header>
-   <container>1</container>
-  </customwidget>
-  <customwidget>
-   <class>EricLed</class>
-   <extends>QFrame</extends>
-   <header>EricWidgets/EricLed.h</header>
-   <container>1</container>
-  </customwidget>
- </customwidgets>
- <tabstops>
-  <tabstop>tabWidget</tabstop>
-  <tabstop>discoverCheckBox</tabstop>
-  <tabstop>clearHistoriesButton</tabstop>
-  <tabstop>discoveryPicker</tabstop>
-  <tabstop>testsuitePicker</tabstop>
-  <tabstop>testComboBox</tabstop>
-  <tabstop>venvComboBox</tabstop>
-  <tabstop>coverageCheckBox</tabstop>
-  <tabstop>coverageEraseCheckBox</tabstop>
-  <tabstop>failfastCheckBox</tabstop>
-  <tabstop>debuggerCheckBox</tabstop>
-  <tabstop>discoveryList</tabstop>
-  <tabstop>testsListWidget</tabstop>
-  <tabstop>errorsListWidget</tabstop>
- </tabstops>
- <resources/>
- <connections>
-  <connection>
-   <sender>coverageCheckBox</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>coverageEraseCheckBox</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>321</x>
-     <y>294</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>616</x>
-     <y>294</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>accepted()</signal>
-   <receiver>UnittestDialog</receiver>
-   <slot>close()</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>67</x>
-     <y>662</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>72</x>
-     <y>667</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>rejected()</signal>
-   <receiver>UnittestDialog</receiver>
-   <slot>close()</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>157</x>
-     <y>662</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>148</x>
-     <y>668</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>discoverCheckBox</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>discoveryPicker</receiver>
-   <slot>setEnabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>209</x>
-     <y>93</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>209</x>
-     <y>120</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>discoverCheckBox</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>testsuitePicker</receiver>
-   <slot>setDisabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>96</x>
-     <y>93</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>150</x>
-     <y>143</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>discoverCheckBox</sender>
-   <signal>toggled(bool)</signal>
-   <receiver>testComboBox</receiver>
-   <slot>setDisabled(bool)</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>321</x>
-     <y>97</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>327</x>
-     <y>166</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
-</ui>
--- a/eric7/PyUnit/UnittestStacktraceDialog.ui	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-<ui version="4.0" >
- <class>UnittestStacktraceDialog</class>
- <widget class="QDialog" name="UnittestStacktraceDialog" >
-  <property name="geometry" >
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>600</width>
-    <height>250</height>
-   </rect>
-  </property>
-  <layout class="QVBoxLayout" >
-   <item>
-    <widget class="QLabel" name="testLabel" />
-   </item>
-   <item>
-    <widget class="QTextEdit" name="traceback" >
-     <property name="readOnly" >
-      <bool>true</bool>
-     </property>
-     <property name="acceptRichText" >
-      <bool>false</bool>
-     </property>
-    </widget>
-   </item>
-   <item>
-    <widget class="QDialogButtonBox" name="buttonBox" >
-     <property name="orientation" >
-      <enum>Qt::Horizontal</enum>
-     </property>
-     <property name="standardButtons" >
-      <set>QDialogButtonBox::Close</set>
-     </property>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <resources/>
- <connections>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>accepted()</signal>
-   <receiver>UnittestStacktraceDialog</receiver>
-   <slot>accept()</slot>
-   <hints>
-    <hint type="sourcelabel" >
-     <x>33</x>
-     <y>235</y>
-    </hint>
-    <hint type="destinationlabel" >
-     <x>33</x>
-     <y>249</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>rejected()</signal>
-   <receiver>UnittestStacktraceDialog</receiver>
-   <slot>reject()</slot>
-   <hints>
-    <hint type="sourcelabel" >
-     <x>94</x>
-     <y>226</y>
-    </hint>
-    <hint type="destinationlabel" >
-     <x>95</x>
-     <y>249</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
-</ui>
--- a/eric7/PyUnit/__init__.py	Wed Jun 01 13:49:13 2022 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2002 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
-#
-
-"""
-Package implementing an interface to the pyunit unittest package.
-
-The package consist of a single dialog, which may be called as a
-standalone version using the eric7_unittest script or from within the eric
-IDE. If it is called from within eric, it has the additional function to
-open a source file that failed a test.
-"""
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Testing/Interfaces/PytestExecutor.py	Sun Jun 05 17:17:44 2022 +0200
@@ -0,0 +1,310 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2022 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the executor for the 'pytest' framework.
+"""
+
+import contextlib
+import json
+import os
+
+from PyQt6.QtCore import pyqtSlot, QProcess
+
+from EricNetwork.EricJsonStreamReader import EricJsonReader
+
+from .TestExecutorBase import TestExecutorBase, TestResult, TestResultCategory
+
+
+class PytestExecutor(TestExecutorBase):
+    """
+    Class implementing the executor for the 'pytest' framework.
+    """
+    module = "pytest"
+    name = "pytest"
+    
+    runner = os.path.join(os.path.dirname(__file__), "PytestRunner.py")
+    
+    def __init__(self, testWidget):
+        """
+        Constructor
+        
+        @param testWidget reference to the unit test widget
+        @type TestingWidget
+        """
+        super().__init__(testWidget)
+        
+        self.__statusDisplayMapping = {
+            "failed": self.tr("Failure"),
+            "skipped": self.tr("Skipped"),
+            "xfailed": self.tr("Expected Failure"),
+            "xpassed": self.tr("Unexpected Success"),
+            "passed": self.tr("Success"),
+        }
+        
+        self.__config = None
+    
+    def getVersions(self, interpreter):
+        """
+        Public method to get the test framework version and version information
+        of its installed plugins.
+        
+        @param interpreter interpreter to be used for the test
+        @type str
+        @return dictionary containing the framework name and version and the
+            list of available plugins with name and version each
+        @rtype dict
+        """
+        proc = QProcess()
+        proc.start(interpreter, [PytestExecutor.runner, "versions"])
+        if proc.waitForFinished(3000):
+            exitCode = proc.exitCode()
+            if exitCode == 0:
+                outputLines = self.readAllOutput(proc).splitlines()
+                for line in outputLines:
+                    if line.startswith("{") and line.endswith("}"):
+                        with contextlib.suppress(json.JSONDecodeError):
+                            return json.loads(line)
+        
+        return {}
+    
+    def hasCoverage(self, interpreter):
+        """
+        Public method to get the test framework version and version information
+        of its installed plugins.
+        
+        @param interpreter interpreter to be used for the test
+        @type str
+        @return flag indicating the availability of coverage functionality
+        @rtype bool
+        """
+        versions = self.getVersions(interpreter)
+        if "plugins" in versions:
+            return any(plugin["name"] == "pytest-cov"
+                       for plugin in versions["plugins"])
+        
+        return False
+    
+    def createArguments(self, config):
+        """
+        Public method to create the arguments needed to start the test process.
+        
+        @param config configuration for the test execution
+        @type TestConfig
+        @return list of process arguments
+        @rtype list of str
+        """
+        #
+        # collectCoverage: --cov= + --cov-report= to suppress report generation
+        # eraseCoverage: --cov-append if eraseCoverage is False
+        # coverageFile
+        args = [
+            PytestExecutor.runner,
+            "runtest",
+            self.reader.address(),
+            str(self.reader.port()),
+            "--quiet",
+        ]
+        
+        if config.failFast:
+            args.append("--exitfirst")
+        
+        if config.failedOnly:
+            args.append("--last-failed")
+        else:
+            args.append("--cache-clear")
+        
+        if config.collectCoverage:
+            args.extend([
+                "--cov=.",
+                "--cov-report="
+            ])
+            if not config.eraseCoverage:
+                args.append("--cov-append")
+        
+        if config.testFilename:
+            if config.testName:
+                args.append("{0}::{1}".format(
+                    config.testFilename,
+                    config.testName.replace(".", "::")
+                ))
+            else:
+                args.append(config.testFilename)
+        
+        return args
+    
+    def start(self, config, pythonpath):
+        """
+        Public method to start the testing process.
+        
+        @param config configuration for the test execution
+        @type TestConfig
+        @param pythonpath list of directories to be added to the Python path
+        @type list of str
+        """
+        self.reader = EricJsonReader(name="Unittest Reader", parent=self)
+        self.reader.dataReceived.connect(self.__processData)
+        
+        self.__config = config
+        
+        if config.discoveryStart:
+            pythonpath.insert(0, os.path.abspath(config.discoveryStart))
+        elif config.testFilename:
+            pythonpath.insert(
+                0, os.path.abspath(os.path.dirname(config.testFilename)))
+        
+        if config.discover:
+            self.__rootdir = config.discoveryStart
+        elif config.testFilename:
+            self.__rootdir = os.path.dirname(config.testFilename)
+        else:
+            self.__rootdir = ""
+        
+        super().start(config, pythonpath)
+    
+    def finished(self):
+        """
+        Public method handling the unit test process been finished.
+        
+        This method should read the results (if necessary) and emit the signal
+        testFinished.
+        """
+        if self.__config.collectCoverage:
+            self.coverageDataSaved.emit(
+                os.path.join(self.__rootdir, ".coverage"))
+        
+        self.__config = None
+        
+        self.reader.close()
+        
+        output = self.readAllOutput()
+        self.testFinished.emit([], output)
+    
+    @pyqtSlot(object)
+    def __processData(self, data):
+        """
+        Private slot to process the received data.
+        
+        @param data data object received
+        @type dict
+        """
+        # test configuration
+        if data["event"] == "config":
+            self.__rootdir = data["root"]
+        
+        # error collecting tests
+        elif data["event"] == "collecterror":
+            name = self.__normalizeModuleName(data["nodeid"])
+            self.collectError.emit([(name, data["report"])])
+        
+        # tests collected
+        elif data["event"] == "collected":
+            self.collected.emit([
+                (data["nodeid"],
+                 self.__nodeid2testname(data["nodeid"]),
+                 "")
+            ])
+        
+        # test started
+        elif data["event"] == "starttest":
+            self.startTest.emit(
+                (data["nodeid"],
+                 self.__nodeid2testname(data["nodeid"]),
+                 "")
+            )
+        
+        # test result
+        elif data["event"] == "result":
+            if data["status"] in ("failed", "xpassed") or data["with_error"]:
+                category = TestResultCategory.FAIL
+            elif data["status"] in ("passed", "xfailed"):
+                category = TestResultCategory.OK
+            else:
+                category = TestResultCategory.SKIP
+            
+            status = (
+                self.tr("Error")
+                if data["with_error"] else
+                self.__statusDisplayMapping[data["status"]]
+            )
+            
+            message = data.get("message", "")
+            extraText = data.get("report", "")
+            reportPhase = data.get("report_phase")
+            if reportPhase in ("setup", "teardown"):
+                message = (
+                    self.tr("ERROR at {0}: {1}", "phase, message")
+                    .format(reportPhase, message)
+                )
+                extraText = (
+                    self.tr("ERROR at {0}: {1}", "phase, extra text")
+                    .format(reportPhase, extraText)
+                )
+            sections = data.get("sections", [])
+            if sections:
+                extraText += "\n"
+                for heading, text in sections:
+                    extraText += "----- {0} -----\n{1}".format(heading, text)
+            
+            duration = data.get("duration_s", None)
+            if duration:
+                # convert to ms
+                duration *= 1000
+            
+            filename = data["filename"]
+            if self.__rootdir:
+                filename = os.path.join(self.__rootdir, filename)
+            
+            self.testResult.emit(TestResult(
+