基于PyQt5和Pywinauto自动化测试客户端

效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


前言

一、什么是pywinauto?

中文官方文档
pywinauto是一组用于自动化Microsoft Windows GUI的python模块。 最简单的是,它允许您将鼠标和键盘操作发送到窗口对话框和控件。

二、使用步骤

1.安装

pip install pywinauto

2.启动客户端

代码如下(示例):

 self.app_path = "D:/package/DingDing/main/current/DingTalk.exe"
 app = Application(backend="uia").start(self.app_path) 

三、什么是PyQt5?

官方文档
PyQt5 是Digia的一套Qt5应用框架与python的结合,同时支持2.x和3.x。本教程使用的是3.x。Qt库由Riverbank Computing开发,是最强大的GUI库之一。

四、使用步骤

1.安装

pip install PyQt5
pip install pyqt5-tools 

2.配置QtDesigner

参考如何配置
代码如下(示例):

1.设计界面
在PyCharm中创建一个项目,然后点击“Tools”–“External Tools”–“QTDesinger”打开QT Desinger
在这里插入图片描述
2. 设计如下
在这里插入图片描述
保存,生成如下UI代码。
ui_mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>807</width>
    <height>676</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Check Account</string>
  </property>
  <property name="styleSheet">
   <string notr="true"/>
  </property>
  <property name="unifiedTitleAndToolBarOnMac">
   <bool>false</bool>
  </property>
  <widget class="QWidget" name="centralwidget">
   <property name="styleSheet">
    <string notr="true"/>
   </property>
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <widget class="QTabWidget" name="tabWidget">
      <property name="font">
       <font>
        <family>Arial</family>
        <pointsize>10</pointsize>
       </font>
      </property>
      <property name="styleSheet">
       <string notr="true"/>
      </property>
      <property name="currentIndex">
       <number>2</number>
      </property>
      <property name="iconSize">
       <size>
        <width>16</width>
        <height>16</height>
       </size>
      </property>
      <widget class="QWidget" name="tab_3">
       <property name="font">
        <font>
         <family>Arial</family>
         <pointsize>10</pointsize>
         <weight>50</weight>
         <bold>false</bold>
        </font>
       </property>
       <attribute name="title">
        <string>Tool</string>
       </attribute>
       <widget class="QPushButton" name="pushButton_6">
        <property name="geometry">
         <rect>
          <x>340</x>
          <y>170</y>
          <width>71</width>
          <height>31</height>
         </rect>
        </property>
        <property name="text">
         <string>RunButton</string>
        </property>
       </widget>
       <widget class="QTextEdit" name="textEdit_11">
        <property name="geometry">
         <rect>
          <x>70</x>
          <y>20</y>
          <width>641</width>
          <height>131</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>9</pointsize>
          <weight>50</weight>
          <bold>false</bold>
         </font>
        </property>
       </widget>
       <widget class="QTextEdit" name="textEdit_12">
        <property name="geometry">
         <rect>
          <x>70</x>
          <y>220</y>
          <width>641</width>
          <height>341</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>9</pointsize>
          <weight>50</weight>
          <bold>false</bold>
         </font>
        </property>
       </widget>
       <widget class="QLabel" name="label_15">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>10</y>
          <width>51</width>
          <height>51</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
          <weight>50</weight>
          <bold>false</bold>
         </font>
        </property>
        <property name="text">
         <string>Account</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_16">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>220</y>
          <width>41</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
          <weight>50</weight>
          <bold>false</bold>
         </font>
        </property>
        <property name="text">
         <string>Logs</string>
        </property>
       </widget>
      </widget>
      <widget class="QWidget" name="tab">
       <property name="tabletTracking">
        <bool>false</bool>
       </property>
       <attribute name="icon">
        <iconset theme="dsa">
         <normaloff>.</normaloff>.</iconset>
       </attribute>
       <attribute name="title">
        <string>Multiple</string>
       </attribute>
       <widget class="QLabel" name="label">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>20</y>
          <width>51</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Excel</string>
        </property>
       </widget>
       <widget class="QPushButton" name="pushButton">
        <property name="geometry">
         <rect>
          <x>510</x>
          <y>20</y>
          <width>75</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Select</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_2">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>120</y>
          <width>51</width>
          <height>51</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Account</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_3">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>330</y>
          <width>41</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Logs</string>
        </property>
       </widget>
       <widget class="QPushButton" name="pushButton_2">
        <property name="geometry">
         <rect>
          <x>360</x>
          <y>280</y>
          <width>81</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <property name="text">
         <string>RunButton</string>
        </property>
       </widget>
       <widget class="QTextEdit" name="textEdit_6">
        <property name="geometry">
         <rect>
          <x>70</x>
          <y>130</y>
          <width>641</width>
          <height>131</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>9</pointsize>
         </font>
        </property>
       </widget>
       <widget class="QTextEdit" name="textEdit_8">
        <property name="geometry">
         <rect>
          <x>70</x>
          <y>330</y>
          <width>641</width>
          <height>231</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>9</pointsize>
         </font>
        </property>
       </widget>
       <widget class="QLabel" name="label_14">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>70</y>
          <width>51</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Zoom</string>
        </property>
       </widget>
       <widget class="QPushButton" name="pushButton_5">
        <property name="geometry">
         <rect>
          <x>510</x>
          <y>70</y>
          <width>75</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Select</string>
        </property>
       </widget>
       <widget class="QLineEdit" name="lineEdit">
        <property name="geometry">
         <rect>
          <x>70</x>
          <y>19</y>
          <width>411</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>9</pointsize>
         </font>
        </property>
       </widget>
       <widget class="QLineEdit" name="lineEdit_2">
        <property name="geometry">
         <rect>
          <x>70</x>
          <y>70</y>
          <width>411</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>9</pointsize>
         </font>
        </property>
       </widget>
       <zorder>label</zorder>
       <zorder>label_2</zorder>
       <zorder>label_3</zorder>
       <zorder>pushButton_2</zorder>
       <zorder>pushButton</zorder>
       <zorder>textEdit_6</zorder>
       <zorder>textEdit_8</zorder>
       <zorder>label_14</zorder>
       <zorder>pushButton_5</zorder>
       <zorder>lineEdit</zorder>
       <zorder>lineEdit_2</zorder>
      </widget>
      <widget class="QWidget" name="tab_2">
       <attribute name="title">
        <string>Single</string>
       </attribute>
       <widget class="QLabel" name="label_4">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>70</y>
          <width>61</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Username</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_5">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>120</y>
          <width>61</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Password</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_6">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>171</y>
          <width>121</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Buy A License</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_7">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>220</y>
          <width>91</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>AccountType</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_8">
        <property name="geometry">
         <rect>
          <x>400</x>
          <y>70</y>
          <width>54</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Role</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_9">
        <property name="geometry">
         <rect>
          <x>400</x>
          <y>110</y>
          <width>71</width>
          <height>51</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>UserType</string>
        </property>
       </widget>
       <widget class="QLabel" name="label_10">
        <property name="geometry">
         <rect>
          <x>400</x>
          <y>160</y>
          <width>54</width>
          <height>51</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>K12(Y/N)</string>
        </property>
       </widget>
       <widget class="QPushButton" name="pushButton_3">
        <property name="geometry">
         <rect>
          <x>600</x>
          <y>271</y>
          <width>91</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <property name="text">
         <string>RunButton</string>
        </property>
       </widget>
       <widget class="QRadioButton" name="radioButton">
        <property name="geometry">
         <rect>
          <x>270</x>
          <y>171</y>
          <width>81</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <property name="text">
         <string>No</string>
        </property>
       </widget>
       <widget class="QRadioButton" name="radioButton_2">
        <property name="geometry">
         <rect>
          <x>150</x>
          <y>171</y>
          <width>71</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Yes</string>
        </property>
        <property name="checked">
         <bool>true</bool>
        </property>
        <property name="autoRepeat">
         <bool>false</bool>
        </property>
       </widget>
       <widget class="QComboBox" name="comboBox">
        <property name="geometry">
         <rect>
          <x>100</x>
          <y>221</y>
          <width>231</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <property name="cursor">
         <cursorShape>ArrowCursor</cursorShape>
        </property>
        <item>
         <property name="text">
          <string/>
         </property>
        </item>
        <item>
         <property name="text">
          <string>enterprise-activehost</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>Education</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>biz-enterprise</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>Single Pro (Named Host)</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>single pro+webinar</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>free with cc</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>free without cc</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>freetrail</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>ZR</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>pro(license&gt;1)</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>biz(license&lt;100)</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>API</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>free with CC (Free-type2)</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>free with CC (EDU - K12)</string>
         </property>
        </item>
       </widget>
       <widget class="QComboBox" name="comboBox_2">
        <property name="geometry">
         <rect>
          <x>480</x>
          <y>120</y>
          <width>211</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <item>
         <property name="text">
          <string/>
         </property>
        </item>
        <item>
         <property name="text">
          <string>License</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>Basic</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>On-Prem</string>
         </property>
        </item>
       </widget>
       <widget class="QLabel" name="label_12">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>330</y>
          <width>54</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Logs</string>
        </property>
       </widget>
       <widget class="QTextEdit" name="textEdit_4">
        <property name="geometry">
         <rect>
          <x>100</x>
          <y>330</y>
          <width>591</width>
          <height>211</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <property name="styleSheet">
         <string notr="true"/>
        </property>
       </widget>
       <widget class="QComboBox" name="comboBox_3">
        <property name="geometry">
         <rect>
          <x>480</x>
          <y>70</y>
          <width>211</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <item>
         <property name="text">
          <string/>
         </property>
        </item>
        <item>
         <property name="text">
          <string>owner</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>member</string>
         </property>
        </item>
       </widget>
       <widget class="QComboBox" name="comboBox_4">
        <property name="geometry">
         <rect>
          <x>480</x>
          <y>170</y>
          <width>211</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <item>
         <property name="text">
          <string/>
         </property>
        </item>
        <item>
         <property name="text">
          <string>Yes</string>
         </property>
        </item>
        <item>
         <property name="text">
          <string>No</string>
         </property>
        </item>
       </widget>
       <widget class="QLabel" name="label_13">
        <property name="geometry">
         <rect>
          <x>10</x>
          <y>20</y>
          <width>71</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>9</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Zoom Path</string>
        </property>
       </widget>
       <widget class="QPushButton" name="pushButton_4">
        <property name="geometry">
         <rect>
          <x>600</x>
          <y>20</y>
          <width>91</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Arial</family>
          <pointsize>10</pointsize>
         </font>
        </property>
        <property name="text">
         <string>Select</string>
        </property>
       </widget>
       <widget class="QLineEdit" name="lineEdit_3">
        <property name="geometry">
         <rect>
          <x>100</x>
          <y>20</y>
          <width>381</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>10</pointsize>
         </font>
        </property>
       </widget>
       <widget class="QLineEdit" name="lineEdit_4">
        <property name="geometry">
         <rect>
          <x>100</x>
          <y>70</y>
          <width>271</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>10</pointsize>
         </font>
        </property>
       </widget>
       <widget class="QLineEdit" name="lineEdit_5">
        <property name="geometry">
         <rect>
          <x>100</x>
          <y>120</y>
          <width>271</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <family>Times New Roman</family>
          <pointsize>10</pointsize>
         </font>
        </property>
       </widget>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>807</width>
     <height>23</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

转换为python代码
ui_mainwindow.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'ui_mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(807, 676)
        MainWindow.setStyleSheet("")
        MainWindow.setUnifiedTitleAndToolBarOnMac(False)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setStyleSheet("")
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        self.tabWidget.setFont(font)
        self.tabWidget.setStyleSheet("")
        self.tabWidget.setIconSize(QtCore.QSize(16, 16))
        self.tabWidget.setObjectName("tabWidget")
        self.tab_3 = QtWidgets.QWidget()
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        font.setBold(False)
        font.setWeight(50)
        self.tab_3.setFont(font)
        self.tab_3.setObjectName("tab_3")
        self.pushButton_6 = QtWidgets.QPushButton(self.tab_3)
        self.pushButton_6.setGeometry(QtCore.QRect(340, 170, 71, 31))
        self.pushButton_6.setObjectName("pushButton_6")
        self.textEdit_11 = QtWidgets.QTextEdit(self.tab_3)
        self.textEdit_11.setGeometry(QtCore.QRect(70, 20, 641, 131))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.textEdit_11.setFont(font)
        self.textEdit_11.setObjectName("textEdit_11")
        self.textEdit_12 = QtWidgets.QTextEdit(self.tab_3)
        self.textEdit_12.setGeometry(QtCore.QRect(70, 220, 641, 341))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.textEdit_12.setFont(font)
        self.textEdit_12.setObjectName("textEdit_12")
        self.label_15 = QtWidgets.QLabel(self.tab_3)
        self.label_15.setGeometry(QtCore.QRect(10, 10, 51, 51))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.label_15.setFont(font)
        self.label_15.setObjectName("label_15")
        self.label_16 = QtWidgets.QLabel(self.tab_3)
        self.label_16.setGeometry(QtCore.QRect(10, 220, 41, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.label_16.setFont(font)
        self.label_16.setObjectName("label_16")
        self.tabWidget.addTab(self.tab_3, "")
        self.tab = QtWidgets.QWidget()
        self.tab.setTabletTracking(False)
        self.tab.setObjectName("tab")
        self.label = QtWidgets.QLabel(self.tab)
        self.label.setGeometry(QtCore.QRect(10, 20, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(self.tab)
        self.pushButton.setGeometry(QtCore.QRect(510, 20, 75, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.label_2 = QtWidgets.QLabel(self.tab)
        self.label_2.setGeometry(QtCore.QRect(10, 120, 51, 51))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(self.tab)
        self.label_3.setGeometry(QtCore.QRect(10, 330, 41, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.pushButton_2 = QtWidgets.QPushButton(self.tab)
        self.pushButton_2.setGeometry(QtCore.QRect(360, 280, 81, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        self.pushButton_2.setFont(font)
        self.pushButton_2.setObjectName("pushButton_2")
        self.textEdit_6 = QtWidgets.QTextEdit(self.tab)
        self.textEdit_6.setGeometry(QtCore.QRect(70, 130, 641, 131))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(9)
        self.textEdit_6.setFont(font)
        self.textEdit_6.setObjectName("textEdit_6")
        self.textEdit_8 = QtWidgets.QTextEdit(self.tab)
        self.textEdit_8.setGeometry(QtCore.QRect(70, 330, 641, 231))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(9)
        self.textEdit_8.setFont(font)
        self.textEdit_8.setObjectName("textEdit_8")
        self.label_14 = QtWidgets.QLabel(self.tab)
        self.label_14.setGeometry(QtCore.QRect(10, 70, 51, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_14.setFont(font)
        self.label_14.setObjectName("label_14")
        self.pushButton_5 = QtWidgets.QPushButton(self.tab)
        self.pushButton_5.setGeometry(QtCore.QRect(510, 70, 75, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        self.pushButton_5.setFont(font)
        self.pushButton_5.setObjectName("pushButton_5")
        self.lineEdit = QtWidgets.QLineEdit(self.tab)
        self.lineEdit.setGeometry(QtCore.QRect(70, 19, 411, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(9)
        self.lineEdit.setFont(font)
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit_2 = QtWidgets.QLineEdit(self.tab)
        self.lineEdit_2.setGeometry(QtCore.QRect(70, 70, 411, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(9)
        self.lineEdit_2.setFont(font)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.label.raise_()
        self.label_2.raise_()
        self.label_3.raise_()
        self.pushButton_2.raise_()
        self.pushButton.raise_()
        self.textEdit_6.raise_()
        self.textEdit_8.raise_()
        self.label_14.raise_()
        self.pushButton_5.raise_()
        self.lineEdit.raise_()
        self.lineEdit_2.raise_()
        icon = QtGui.QIcon.fromTheme("dsa")
        self.tabWidget.addTab(self.tab, icon, "")
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.label_4 = QtWidgets.QLabel(self.tab_2)
        self.label_4.setGeometry(QtCore.QRect(10, 70, 61, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.label_5 = QtWidgets.QLabel(self.tab_2)
        self.label_5.setGeometry(QtCore.QRect(10, 120, 61, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.label_6 = QtWidgets.QLabel(self.tab_2)
        self.label_6.setGeometry(QtCore.QRect(10, 171, 121, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_6.setFont(font)
        self.label_6.setObjectName("label_6")
        self.label_7 = QtWidgets.QLabel(self.tab_2)
        self.label_7.setGeometry(QtCore.QRect(10, 220, 91, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_7.setFont(font)
        self.label_7.setObjectName("label_7")
        self.label_8 = QtWidgets.QLabel(self.tab_2)
        self.label_8.setGeometry(QtCore.QRect(400, 70, 54, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_8.setFont(font)
        self.label_8.setObjectName("label_8")
        self.label_9 = QtWidgets.QLabel(self.tab_2)
        self.label_9.setGeometry(QtCore.QRect(400, 110, 71, 51))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_9.setFont(font)
        self.label_9.setObjectName("label_9")
        self.label_10 = QtWidgets.QLabel(self.tab_2)
        self.label_10.setGeometry(QtCore.QRect(400, 160, 54, 51))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_10.setFont(font)
        self.label_10.setObjectName("label_10")
        self.pushButton_3 = QtWidgets.QPushButton(self.tab_2)
        self.pushButton_3.setGeometry(QtCore.QRect(600, 271, 91, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        self.pushButton_3.setFont(font)
        self.pushButton_3.setObjectName("pushButton_3")
        self.radioButton = QtWidgets.QRadioButton(self.tab_2)
        self.radioButton.setGeometry(QtCore.QRect(270, 171, 81, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        self.radioButton.setFont(font)
        self.radioButton.setObjectName("radioButton")
        self.radioButton_2 = QtWidgets.QRadioButton(self.tab_2)
        self.radioButton_2.setGeometry(QtCore.QRect(150, 171, 71, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        self.radioButton_2.setFont(font)
        self.radioButton_2.setChecked(True)
        self.radioButton_2.setAutoRepeat(False)
        self.radioButton_2.setObjectName("radioButton_2")
        self.comboBox = QtWidgets.QComboBox(self.tab_2)
        self.comboBox.setGeometry(QtCore.QRect(100, 221, 231, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(10)
        self.comboBox.setFont(font)
        self.comboBox.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.setItemText(0, "")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox_2 = QtWidgets.QComboBox(self.tab_2)
        self.comboBox_2.setGeometry(QtCore.QRect(480, 120, 211, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(10)
        self.comboBox_2.setFont(font)
        self.comboBox_2.setObjectName("comboBox_2")
        self.comboBox_2.addItem("")
        self.comboBox_2.setItemText(0, "")
        self.comboBox_2.addItem("")
        self.comboBox_2.addItem("")
        self.comboBox_2.addItem("")
        self.label_12 = QtWidgets.QLabel(self.tab_2)
        self.label_12.setGeometry(QtCore.QRect(10, 330, 54, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_12.setFont(font)
        self.label_12.setObjectName("label_12")
        self.textEdit_4 = QtWidgets.QTextEdit(self.tab_2)
        self.textEdit_4.setGeometry(QtCore.QRect(100, 330, 591, 211))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(10)
        self.textEdit_4.setFont(font)
        self.textEdit_4.setStyleSheet("")
        self.textEdit_4.setObjectName("textEdit_4")
        self.comboBox_3 = QtWidgets.QComboBox(self.tab_2)
        self.comboBox_3.setGeometry(QtCore.QRect(480, 70, 211, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(10)
        self.comboBox_3.setFont(font)
        self.comboBox_3.setObjectName("comboBox_3")
        self.comboBox_3.addItem("")
        self.comboBox_3.setItemText(0, "")
        self.comboBox_3.addItem("")
        self.comboBox_3.addItem("")
        self.comboBox_4 = QtWidgets.QComboBox(self.tab_2)
        self.comboBox_4.setGeometry(QtCore.QRect(480, 170, 211, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(10)
        self.comboBox_4.setFont(font)
        self.comboBox_4.setObjectName("comboBox_4")
        self.comboBox_4.addItem("")
        self.comboBox_4.setItemText(0, "")
        self.comboBox_4.addItem("")
        self.comboBox_4.addItem("")
        self.label_13 = QtWidgets.QLabel(self.tab_2)
        self.label_13.setGeometry(QtCore.QRect(10, 20, 71, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(9)
        self.label_13.setFont(font)
        self.label_13.setObjectName("label_13")
        self.pushButton_4 = QtWidgets.QPushButton(self.tab_2)
        self.pushButton_4.setGeometry(QtCore.QRect(600, 20, 91, 31))
        font = QtGui.QFont()
        font.setFamily("Arial")
        font.setPointSize(10)
        self.pushButton_4.setFont(font)
        self.pushButton_4.setObjectName("pushButton_4")
        self.lineEdit_3 = QtWidgets.QLineEdit(self.tab_2)
        self.lineEdit_3.setGeometry(QtCore.QRect(100, 20, 381, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(10)
        self.lineEdit_3.setFont(font)
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.lineEdit_4 = QtWidgets.QLineEdit(self.tab_2)
        self.lineEdit_4.setGeometry(QtCore.QRect(100, 70, 271, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(10)
        self.lineEdit_4.setFont(font)
        self.lineEdit_4.setObjectName("lineEdit_4")
        self.lineEdit_5 = QtWidgets.QLineEdit(self.tab_2)
        self.lineEdit_5.setGeometry(QtCore.QRect(100, 120, 271, 31))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(10)
        self.lineEdit_5.setFont(font)
        self.lineEdit_5.setObjectName("lineEdit_5")
        self.tabWidget.addTab(self.tab_2, "")
        self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 807, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(2)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Check Account"))
        self.pushButton_6.setText(_translate("MainWindow", "RunButton"))
        self.label_15.setText(_translate("MainWindow", "Account"))
        self.label_16.setText(_translate("MainWindow", "Logs"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "Tool"))
        self.label.setText(_translate("MainWindow", "Excel"))
        self.pushButton.setText(_translate("MainWindow", "Select"))
        self.label_2.setText(_translate("MainWindow", "Account"))
        self.label_3.setText(_translate("MainWindow", "Logs"))
        self.pushButton_2.setText(_translate("MainWindow", "RunButton"))
        self.label_14.setText(_translate("MainWindow", "Zoom"))
        self.pushButton_5.setText(_translate("MainWindow", "Select"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Multiple"))
        self.label_4.setText(_translate("MainWindow", "Username"))
        self.label_5.setText(_translate("MainWindow", "Password"))
        self.label_6.setText(_translate("MainWindow", "Buy A License"))
        self.label_7.setText(_translate("MainWindow", "AccountType"))
        self.label_8.setText(_translate("MainWindow", "Role"))
        self.label_9.setText(_translate("MainWindow", "UserType"))
        self.label_10.setText(_translate("MainWindow", "K12(Y/N)"))
        self.pushButton_3.setText(_translate("MainWindow", "RunButton"))
        self.radioButton.setText(_translate("MainWindow", "No"))
        self.radioButton_2.setText(_translate("MainWindow", "Yes"))
        self.comboBox.setItemText(1, _translate("MainWindow", "Enterprise-activehost"))
        self.comboBox.setItemText(2, _translate("MainWindow", "Education"))
        self.comboBox.setItemText(3, _translate("MainWindow", "Biz-enterprise"))
        self.comboBox.setItemText(4, _translate("MainWindow", "Single Pro (Named Host)"))
        self.comboBox.setItemText(5, _translate("MainWindow", "Single Pro+webinar"))
        self.comboBox.setItemText(6, _translate("MainWindow", "Free with cc"))
        self.comboBox.setItemText(7, _translate("MainWindow", "Free without cc"))
        self.comboBox.setItemText(8, _translate("MainWindow", "Freetrail"))
        self.comboBox.setItemText(9, _translate("MainWindow", "ZR"))
        self.comboBox.setItemText(10, _translate("MainWindow", "Pro(license>1)"))
        self.comboBox.setItemText(11, _translate("MainWindow", "Biz(license<100)"))
        self.comboBox.setItemText(12, _translate("MainWindow", "API"))
        self.comboBox.setItemText(13, _translate("MainWindow", "Free with CC (Free-type2)"))
        self.comboBox.setItemText(14, _translate("MainWindow", "Free with CC (EDU-K12)"))
        self.comboBox_2.setItemText(1, _translate("MainWindow", "License"))
        self.comboBox_2.setItemText(2, _translate("MainWindow", "Basic"))
        self.comboBox_2.setItemText(3, _translate("MainWindow", "On-Prem"))
        self.label_12.setText(_translate("MainWindow", "Logs"))
        self.comboBox_3.setItemText(1, _translate("MainWindow", "Owner"))
        self.comboBox_3.setItemText(2, _translate("MainWindow", "Member"))
        self.comboBox_4.setItemText(1, _translate("MainWindow", "Yes"))
        self.comboBox_4.setItemText(2, _translate("MainWindow", "No"))
        self.label_13.setText(_translate("MainWindow", "Zoom Path"))
        self.pushButton_4.setText(_translate("MainWindow", "Select"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Single"))

项目代码

在这里插入图片描述
main.py

# -*- coding: utf-8 -*-
import os
import sys
import time
import threading

from mainwindow import MainWindow
from PyQt5.QtWidgets import QApplication

parent_path = os.path.dirname(os.path.abspath(__file__))
sys.path.append(parent_path)


class RunGUI(object):
    """运行GUI界面"""

    def gui_start(self):
        """启动gui界面"""
        app = QApplication(sys.argv)  # QApplication采用事件循环机制,当QApplication初始化后,就进入应用程序的主循环
        main_window = MainWindow()  # 打开主界面
        main_window.show()  # 显示主界面
        sys.exit(app.exec_())  # sys.exit()函数可以结束一个应用程序,使应用程序在主循环中退出。

    def create_thread(self, func, *args):
        """将函数放入线程中执行"""
        t = threading.Thread(target=func, args=args)  # 创建线程
        t.setDaemon(True)  # 守护线程
        t.start()  # 启动线程

    def run(self):
        self.create_thread(self.gui_start)  # 将GUI界面放到守护线程中运行
        while True:
            time.sleep(1)
            print(len(threading.enumerate()))
            if len(threading.enumerate()) < 2:  # 当只剩下1个线程时,即GUI线程关闭,主线程退出
                break


if __name__ == '__main__':
    r = RunGUI()
    r.run()

mainwindow.py

# coding: utf-8
import os
import xlrd
from PyQt5 import QtWidgets
from PyQt5.QtGui import QTextCursor

from thread_work import WorkThread
from ui_mainwindow import Ui_MainWindow
from PyQt5.QtWidgets import QMessageBox, QWidget, QMainWindow


class MainWindow(QMainWindow, Ui_MainWindow):
    """GUI主界面操作"""

    def __init__(self):
        """初始化"""
        super(MainWindow, self).__init__()  # super().__init__()继承父类的init方法
        self.setupUi(self)  # 初始化窗口

        self.app_path = None  # app路径

        self.account_lists = []  # 账号list
        self.account_path = None  # 账号路径

        self.thread = None  # 初始化线程

        self.log_msg = ""  # 简单界面log日志

        # 绑定多账号按钮点击事件
        self.pushButton.clicked.connect(self.get_multiple_file_path)  # 绑定账号文件选择按钮点击事件
        self.pushButton_5.clicked.connect(self.get_multiple_app_path)  # 绑定app选择按钮点击事件
        self.pushButton_2.clicked.connect(self.multiple_run_button)  # 绑定运行按钮点击事件

        # 绑定单账号按钮点击事件
        self.pushButton_3.clicked.connect(self.single_run_button)  # 绑定运行按钮点击事件
        self.pushButton_4.clicked.connect(self.get_single_app_path)  # 绑定app选择按钮点击事件

        # 绑定多账号简单界面按钮点击事件
        self.pushButton_6.clicked.connect(self.simple_run_button)  # 绑定app选择按钮点击事件

    def simple_run_button(self):
        """多账号简单界面点击运行按钮"""
        self.pushButton_6.setEnabled(False)
        app_path = os.getenv("APPDATA") + "\\Zoom\\bin\\Zoom.exe"  # 获取app路径
        self.account_path = os.getcwd() + "\\Zoom.xlsx"  # 获取账号文件路径
        self.get_account()

        self.thread = WorkThread()  # 初始化一条线程
        self.thread.account_lists = self.account_lists  # 将账号list传给线程
        self.thread.app_path = app_path  # 将 app path 传给线程
        if app_path:
            self.thread.sinOut.connect(self.simple_output)  # 绑定信号槽,获取信号
            self.thread.complete_sinOut.connect(self.simple_complete_sinOut)
            self.thread.start()  # 开启线程
        else:
            w = QWidget()
            QMessageBox.about(w, 'Error', 'Failed to get Zoom.exe path')
            self.pushButton_6.setEnabled(True)

    def simple_complete_sinOut(self, msg):
        """多账号简单界面完成信号槽信息"""
        w = QWidget()
        QMessageBox.about(w, 'Success', 'All account test completed')
        self.pushButton_6.setEnabled(True)

    def simple_output(self, msg):
        """多账号简单界面信号槽信息"""
        res = self.account_msg(msg[0])  # 拼接账号信息显示框展示内容
        self.textEdit_11.setText(res)

        log = self.logs_msg(msg[1])  # 拼接账号信息显示框展示内容
        self.log_msg += log
        self.textEdit_12.setText(self.log_msg)

        self.move_cursor(self.textEdit_12)  # 移动光标到文档最后

        self.pushButton_6.setEnabled(False)

    def get_multiple_file_path(self):
        """多账号界面获取账号文件信息"""
        account_path, file_type = QtWidgets.QFileDialog.getOpenFileName(None, "选取账号文件",
                                                                        os.getcwd() + "\\Zoom.xlsx", )  # 打开文件选择框
        if str(account_path).strip() == "" or str(account_path).split(".")[-1] != "xlsx":
            w = QWidget()
            QMessageBox.about(w, 'Error', 'The file is not xlsx')  # 提示框
            self.account_path = ''
            self.lineEdit.setText(self.account_path)  # 设置输入框value
        else:
            self.account_path = account_path
            self.lineEdit.setText(self.account_path)

    def get_multiple_app_path(self):
        """多账号界面获取app路径"""
        if self.account_path:
            self.get_account()  # 调用读取账号文件函数获取所有账号list
            app_path, file_type = QtWidgets.QFileDialog.getOpenFileName(None, "选取Zoom软件", os.getenv(
                "APPDATA") + "\\Zoom\\bin\\Zoom.exe", )  # 路径
            if str(app_path).strip() == "" or app_path.split("/")[-1] != "Zoom.exe":
                w = QWidget()
                QMessageBox.about(w, 'Error', 'The file is not Zoom.exe')
                self.app_path = ''
                self.lineEdit_2.setText(self.app_path)
            else:
                self.lineEdit_2.setText(app_path)
                self.app_path = app_path
        else:
            w = QWidget()
            QMessageBox.about(w, 'Error', 'Please select the account path')
            self.pushButton_2.setEnabled(True)  # 设置按钮可点击状态

    def multiple_run_button(self):
        """多账号界面点击运行按钮"""
        self.pushButton_2.setEnabled(False)
        self.thread = WorkThread()  # 初始化一条线程
        self.thread.account_lists = self.account_lists  # 将账号list传给线程
        self.thread.app_path = self.app_path  # 将 app path 传给线程
        if self.app_path:
            self.thread.sinOut.connect(self.multiple_output)  # 绑定信号槽,获取信号
            self.thread.complete_sinOut.connect(self.multiple_complete_sinOut)
            self.thread.start()  # 开启线程
        else:
            w = QWidget()
            QMessageBox.about(w, 'Error', 'Please select the Zoom.exe path')
            self.pushButton_2.setEnabled(True)

    def multiple_complete_sinOut(self, msg):
        """多账号界面完成信号槽信息"""
        w = QWidget()
        QMessageBox.about(w, 'Success', 'All account test completed')
        self.pushButton_2.setEnabled(True)

    def multiple_output(self, msg):
        """多账号界面信号槽信息"""
        res = self.account_msg(msg[0])  # 拼接账号信息显示框展示内容
        self.textEdit_6.setText(res)

        log = self.logs_msg(msg[1])  # 拼接账号信息显示框展示内容
        self.log_msg += log
        self.textEdit_8.setText(self.log_msg)

        self.move_cursor(self.textEdit_8)  # 移动光标到文档最后

        self.pushButton_2.setEnabled(False)

    def get_single_app_path(self):
        """单账号界面获取app路径"""
        app_path, file_type = QtWidgets.QFileDialog.getOpenFileName(None, "选取Zoom软件",
                                                                    os.getenv("APPDATA") + "\\Zoom\\bin\\Zoom.exe", )
        if str(app_path).strip() == "" or app_path.split("/")[-1] != "Zoom.exe":
            w = QWidget()
            QMessageBox.about(w, 'Error', 'The file is not Zoom.exe')
            self.app_path = ''
            self.lineEdit_3.setText(self.app_path)
        else:
            self.lineEdit_3.setText(app_path)
            self.app_path = app_path

    def single_run_button(self):
        """单账号界面点击运行按钮"""
        if self.app_path:
            self.pushButton_3.setEnabled(False)
            account_dict = {}
            username = self.lineEdit_4.text().replace(' ', '')  # 获取输入框信息
            password = self.lineEdit_5.text().replace(' ', '')
            buy_a_license_yes = self.radioButton_2.isChecked()  # 获取单选框是否被选择
            account_type = self.comboBox.currentText()  # 获取复选框当前选择信息
            user_type = self.comboBox_2.currentText()
            role = self.comboBox_3.currentText()
            k12 = self.comboBox_4.currentText()
            if buy_a_license_yes:
                buy_a_license = "Yes"
            else:
                buy_a_license = "No"
            if self.check_value(username, "Username") and self.check_value(password, "Password") and self.check_value(
                    account_type, "AccountType") and self.check_value(user_type, "UserType") and \
                    self.check_value(role, "Role") and self.check_value(k12, "K12"):  # 判断所有信息是否都填写完毕
                account_dict["AccountType"] = account_type
                account_dict["Role"] = role
                account_dict["UserType"] = user_type
                account_dict["K12"] = k12
                account_dict["UserName"] = username
                account_dict["PassWord"] = password
                account_dict["BuySign"] = buy_a_license
                self.account_lists.append(account_dict)
                self.thread = WorkThread()
                self.thread.account_lists = self.account_lists
                self.thread.app_path = self.app_path
                self.thread.sinOut.connect(self.single_output)
                self.thread.start()
        else:
            w = QWidget()
            QMessageBox.about(w, 'Error', 'Please select the Zoom.exe path')
            self.pushButton_3.setEnabled(True)

    def single_output(self, msg):
        """单账号界面信号槽信息"""
        log = self.logs_msg(msg[1])  # 拼接账号信息显示框展示内容
        self.log_msg += log
        self.textEdit_4.setText(self.log_msg)
        self.pushButton_3.setEnabled(True)

    def check_value(self, msg, name):
        """校验单账号界面,输入框、单选框、多选框等信息是否填写"""
        if msg.strip() == "":
            w = QWidget()
            QMessageBox.about(w, 'Error', 'Please input the %s' % name)
            self.pushButton_3.setEnabled(True)
            return False
        else:
            return True

    def get_account(self):
        """获取账号信息"""
        try:
            wb = xlrd.open_workbook(self.account_path)  # 打开excel文件
            table = wb.sheets()[0]  # 获取第一个sheet
            rows = table.nrows  # 总行数
            for i in range(1, rows):
                account_dict = {}
                row_values = table.row_values(i)
                account_type = row_values[0]
                role = row_values[1]
                user_type = row_values[2]
                k12 = row_values[3]
                username = row_values[4]
                password = row_values[5]
                buy_sign = row_values[6]
                account_dict["UserName"] = str(username).replace(' ', '')
                account_dict["PassWord"] = str(password).replace(' ', '')
                account_dict["BuySign"] = str(buy_sign).strip()
                account_dict["AccountType"] = str(account_type).strip()
                account_dict["Role"] = str(role).strip()
                account_dict["UserType"] = str(user_type).strip()
                account_dict["K12"] = str(k12).strip()
                self.account_lists.append(account_dict)
            return True
        except Exception as e:
            w = QWidget()  # 没有父类的widget将被作为窗口使用
            QMessageBox.about(w, 'Error', 'Failed to read account information in excel!')
            return False

    def account_msg(self, msg):
        """拼接账号信息显示框展示内容"""
        res = ""
        for k, v in msg.items():
            res += "<font color='black' size='3' style='line-height:2'><red><strong>" + str(
                k) + ":" + "</strong></font>" + \
                   "<font color='black' size='3' style='line-height:2'><red>" + str(v) + "</font>" + "<br>"
        return res

    def logs_msg(self, m):
        """装饰日志框展示内容"""
        if str(m).__contains__("Fail") or str(m).__contains__("Error"):
            msg = "<font color='red' size='4' style='line-height:2'><red>" + str(m) + "</font>" + "<br>"
        else:
            msg = "<font color='black' size='3' style='line-height:2'><red>" + str(m) + "</font>" + "<br>"
        return msg

    def move_cursor(self, edit):
        """移动光标到文档最后"""
        edit.setText(self.log_msg)
        cursor = edit.textCursor()  # 获取logs框鼠标光标
        cursor.movePosition(QTextCursor.End)  # 光标移动到文档末尾
        edit.setTextCursor(cursor)  # 设置文档光标

thread_work.py

# -*- coding: utf-8 -*-
import time

from PyQt5.QtCore import QThread, pyqtSignal

from check_a_license import ZoomClientAutoTest


class WorkThread(QThread):
    """工作线程"""
    sinOut = pyqtSignal(list)  # 信号槽:和UI主线程通讯, 数据类型str、int、list等
    complete_sinOut = pyqtSignal(str)  # 测试完成信号槽

    def __init__(self):
        """初始化"""
        super(WorkThread, self).__init__()

    def run(self):
        """线程运行"""
        for account_dict in self.account_lists:
            time.sleep(1)
            sin_out_list = []
            username = account_dict["UserName"]
            password = account_dict["PassWord"]
            buy_sign = account_dict["BuySign"]
            account_type = account_dict["AccountType"]
            user_type = account_dict["UserType"]
            k12 = account_dict["K12"]
            role = account_dict["Role"]
            sin_out_list.append(account_dict)
            try:
                z = ZoomClientAutoTest(self.app_path, account_type, role, user_type, k12, username, password, buy_sign)
                res = z.run()
                sin_out_list.append(str(res))
            except Exception as e:
                sin_out_list.append(" %s: Error" % username)
            self.sinOut.emit(sin_out_list)  # 发射信号到主界面
        self.complete_sinOut.emit("True")

check_a_license.py

# coding: utf-8
import pytesseract
import os, re, sys, time
import cv2, psutil
from PIL import ImageGrab
from log_module import LogClass
from pywinauto import keyboard, mouse
from pywinauto.application import Application

parent_path = os.path.dirname(os.path.abspath(__file__))
sys.path.append(parent_path)


class ZoomClientAutoTest(LogClass):
    """ZoomClientAutoTest"""

    def __init__(self, app_path, account_type, role, user_type, k12, username, password, buy_sign):
        """__init__"""
        LogClass.__init__(self, logName='ZoomClientAutoTest')

        self.setTimedRotatingFileHandler(fileName='ZoomClientAutoTest')  # 日志

        self.app_path = app_path  # zoom客户端路径

        self.img_path = parent_path + "\\IMG\\"  # 截图路径

        self.account_type = account_type
        self.role = role
        self.user_type = user_type  # 账号信息
        self.k12 = k12
        self.username = username
        self.password = password
        self.buy_sign = buy_sign

    def start_app(self):
        """start_app"""
        app = Application(backend="uia").start(self.app_path)  # 启动程序
        return app

    def get_PID(self, pName):
        """获取 zoom.exe PID"""
        p = psutil.process_iter()
        for r in p:
            aa = str(r)
            f = re.compile(pName)
            if f.search(aa):
                PID = aa.split('pid=')[1].split(',')[0]
                return PID
            else:
                return None

    def connect_app(self):
        """根据 zoom PID 绑定程序"""
        PID = self.get_PID("Zoom.exe")
        # app = Application().connect(path=self.app_path)  # 程序路径绑定,常用方法
        app = Application().connect(process=PID)  # 用于连接已经启动的程序,注意会改变
        # app = Application().connect(handle=0x100A6E)  # 应用程序的窗口句柄,注意会改变
        # app = Application().connect(title_re="Zoom*", class_name="ZPFTEWndClass")  # 标题、类型等匹配
        return app

    def click_before_login_sign_in(self, app):
        """click_before_login_sign_in"""
        dlg_spec = app.window(class_name='ZPFTEWndClass')  # 定位窗口
        dlg_spec.wait("exists ready", timeout=5, retry_interval=3)  # 等到窗口真的开着
        time.sleep(1)
        dlg_spec.window(title=r'Sign In', control_type="Button").click()  # 点击Button控件,进入登录界面

        return dlg_spec

    def login_app(self, dlg_spec, username, password):
        """login_app"""
        dlg_spec.wait("exists ready", timeout=5, retry_interval=3)  # 等到窗户真的开着
        time.sleep(1)
        keyboard.send_keys('^a^c')  # 全选并剪贴
        keyboard.send_keys(username)  # 输入用户名
        time.sleep(1)
        keyboard.send_keys('{VK_TAB}')  # 跳转输入框下一行
        keyboard.send_keys('^a^c')
        keyboard.send_keys(password)
        time.sleep(1)
        dlg_spec.window(title=r'Sign In', control_type="Button").click()

    def main_operation_zoom_interface(self, app, account_type, role, user_type, k12, username, password, buy_sign):
        zoom = app.window(class_name=r'ZPPTMainFrmWndClassEx')
        zoom.wait("exists ready", timeout=5, retry_interval=3)  # 等到窗户真的开着
        # zoom.print_control_identifiers()  # 打印详细的窗口信息

        zoom.window(title=r'最大化', control_type="Button").click()  # 注意定位到多个相同title,用control_type区分
        time.sleep(2)
        mouse.click(coords=(1895, 52))  # 鼠标点击头像  TODO:先写死
        time.sleep(2)

        coord = (1680, 585, 1885, 605)  # 截图  TODO:先写死
        im = ImageGrab.grab(coord)
        if os.path.exists(self.img_path) is False:
            os.makedirs(self.img_path)
        im.save(self.img_path + username + ".jpg")

        pytesseract.pytesseract.tesseract_cmd = parent_path + '\\Tesseract-OCR\\tesseract.exe'
        im = cv2.imread(self.img_path + username + ".jpg")
        im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)  # 灰度处理图片

        CONFIG = ("-l eng --oem 2 --psm 4")
        content = pytesseract.image_to_string(im_gray, config=CONFIG)  # 识别图片字母
        if str(buy_sign).lower().strip() == "no":
            if content == "":
                self.logger.info("AccountType:%s | Role:%s | UserType:%s | K12:%s | Username:%s | Password:%s |"
                                 " HaveBuyALicense?:%s | Content:%s | TestResult:%s" % (
                                     account_type, role, user_type, k12, username, password, buy_sign, content, "No"))
                result = " %s: Success" % username
            else:
                self.logger.error("AccountType:%s | Role:%s | UserType:%s | K12:%s | Username:%s | Password:%s |"
                                  " HaveBuyALicense?:%s | Content:%s | TestResult:%s" % (
                                      account_type, role, user_type, k12, username, password, buy_sign, content, "Yes"))
                result = " %s: Fail" % username
        else:
            if content == "":
                self.logger.error("AccountType:%s | Role:%s | UserType:%s | K12:%s | Username:%s | Password:%s |"
                                  " HaveBuyALicense?:%s | Content:%s | TestResult:%s" % (
                                      account_type, role, user_type, k12, username, password, buy_sign, content, "No"))
                result = " %s: Fail" % username
            else:
                self.logger.info("AccountType:%s | Role:%s | UserType:%s | K12:%s | Username:%s | Password:%s |"
                                 " HaveBuyALicense?:%s | Content:%s | TestResult:%s" % (
                                     account_type, role, user_type, k12, username, password, buy_sign, content, "Yes"))
                result = " %s: Success" % username
        time.sleep(2)
        mouse.click(coords=(1895, 520))  # switch account TODO:To be optimized
        time.sleep(2)
        app.kill()
        return result

    def run(self):
        s_app = self.start_app()  # 注意:如果软件未启动,启动程序之前将账号退出登录并关闭窗口
        # self.connect_app() # 如果软件已启动,连接已经启动的程序 TODO:连接失败,暂不用
        dlg_spec = self.click_before_login_sign_in(s_app)

        self.login_app(dlg_spec, self.username, self.password)  # 登录客户端
        res = self.main_operation_zoom_interface(s_app, self.account_type, self.role, self.user_type, self.k12,
                                                 self.username, self.password, self.buy_sign)

        return res

log_module.py

# coding: utf-8
import os
import sys
import datetime
import logging
from logging import handlers

parent_path = os.path.dirname(os.path.abspath(__file__))
sys.path.append(parent_path)


class LogClass(object):

    def __init__(self, logName="ete"):
        self.logName = logName
        self.logger = logging.getLogger(self.logName)
        self.logger.setLevel(logging.DEBUG)
        self.now = datetime.datetime.strftime(datetime.datetime.now(), "%Y-%m-%d")

    def setTimedRotatingFileHandler(self, path=parent_path + "\\logs", fileName="ete"):
        if os.path.exists(path) is False:
            os.makedirs(path)
        self.fileFullPath = os.path.join(path, self.now + '_' + fileName + ".log")
        self.Handlers = handlers.TimedRotatingFileHandler(self.fileFullPath, when='midnight', interval=1,
                                                          backupCount=30)
        self.Handlers.setLevel(logging.DEBUG)

        self.formatter = logging.Formatter(
            '[%(asctime)s][%(filename)s][%(lineno)s][%(levelname)s] - [%(message)s]', "%Y-%m-%d %H:%M:%S")
        self.Handlers.setFormatter(self.formatter)

        self.logger.addHandler(self.Handlers)

        return self.logger

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
pyQT和pytest可以结合使用来进行自动化测试。pyQT是一个用于创建图形用户界面的Python库,而pytest是一个用于编写和运行测试的Python框架。 结合pyQT和pytest进行自动化测试的步骤如下: 1. 安装pyQT和pytest库: ```shell pip install pyqt5 pytest ``` 2. 创建一个pyQT应用程序,并在其中添加需要测试的界面元素和功能。 3. 使用pytest编写测试用例,测试pyQT应用程序的各个功能和界面元素。可以使用pytest的各种插件来增强测试功能,例如pytest-html插件可以生成漂亮的测试报告,pytest-xdist插件可以实现并行测试等。 4. 运行pytest测试: ```shell pytest ``` pytest会自动搜索当前目录及其子目录中的测试文件,并执行其中的测试用例。测试结果会以详细的报告形式显示在终端上。 以下是一个示例的pytest测试用例: ```python import pytest from PyQt5.QtWidgets import QApplication, QPushButton @pytest.fixture def app(): app = QApplication([]) yield app app.quit() def test_button_click(app): button = QPushButton("Click me") button.click() assert button.text() == "Clicked" def test_button_disabled(app): button = QPushButton("Disabled") button.setEnabled(False) assert not button.isEnabled() ``` 运行pytest命令后,pytest会自动执行这两个测试用例,并输出测试结果。 注意:在编写测试用例时,可以使用pyQT提供的测试工具和方法来模拟用户交互和界面操作,例如使用QTest类来模拟按钮点击、文本输入等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值