PyQt的一个UI单元测试框架思路-程序员宅基地

專 欄


丁果,Python中文社区作者。对 django、pyqt、opencv、tornado感兴趣。
GitHub:https://github.com/lidingke

一、思路

PyQt是个 相当灵活的UI框架,不过,这个Qt的Python版本一直没有一个好用的针对UI的单元测试工具。

PyQt里的逻辑层都是采用信号槽的方式连接的,我们可以通过拦截并重建信号槽的方式,动态生成一个单元测试的脚本。按这个思路写了一个单元测试的工具。如果需要的人多的话,我就把这个模块做成一个单元测试的框架。

二、demo

一个好用的工具应该是非侵入式的,接口合理且命名规范,符合大多数人使用习惯的,我认为这样一个PyQt的单元测试用例应该长这样子。

主要的动作就是,按照源代码中按钮的信号槽连接的调用链,触发按钮的点击实践,执行点击按钮后的逻辑。

在上述代码中,首先单元测试的入口是启动界面的代码,也就是test_start_main_ui函数,这段代码是最简单的一个PyQt的界面启动代码,其中不一样的是启动了一个线程用于执行单元测试。

而单元测试的函数是这样的,首先初始化一个参数为view的实例的类,这个类用于拦截信号槽,并执行信号动作,我把这个类命名为Knife。

接下来就是执行view下面的target_button的点击事件,这一系列的成员函数是根据原始view里面的信号槽连接代码动态生成的,后面会讲具体方法。

触发点击事件后,结果显示在一个label上,assert一下这个结果是否正确就行了。

GIF是一个演示实例,QLineEdit里面输入一个数,按一下-1s的按钮(QPushButton),会在最右的label上将该数减一之后显示,Demo GUI部分的代码看这里。

三、Qt与PyQt

Qt中信号槽是个不可或缺的概念,和元对象系统之类的东西组成了Qt的基础组件。但对于起源于上古时代的Qt,这些东西很多是为了弥补当时C++的不足,对于Python这种强类型的语言来说并不是那么不可或缺,比如信号槽本质上就是观察者模式,完全可以自己实现一个,我自己的实现可以看这里。

而Qt的元对象系统是一个代码生成框架,给C++提供了自省的能力,但Python这种动态语言在语言层面上就有强大的自省功能,所以我平时用PyQt的时候一般就把它当一个UI库用,其他的东西比如线程、信号槽、串口等都用Python版本的。

四、拦截的实现

在PyQt中,信号槽连接的写法一般是这样的。

signal_instance.connect(slot_name)

所以,我这个版本的拦截信号槽的功能的实现思路就是用正则匹配源代码,从符合这一模式的

语句中解析出信号的发送端和槽函数,将槽函数重新添加进新的生成的自定义信号槽中。

信号槽重连接

之前说Python的自省能力强大,现在有个非常实际的例子就是,在Python中可以动态的获取源代码。这个功能用到的Python 标准库中的inpect库,示例如下。import inspect

print inspect.getsource(inspect.isclass)

这段代码的功能是将inspect库中的isclass函数的源代码打印出来。inspect模块是个很神奇的模块,如果你对闭包和协程不理解的话也可以调用该模块中的相应代码看看。

在程序中还用到了code.co_names这个东西,用来高效的查看函数的源代码里有没有"connect"字符串。

五、程序结构

这里是部分程序源代码,省略了代码细节,源代码可以看这个git仓库

这里用一个叫Knife的类来实现,在重建新的信号函数的时候我希望信号函数的调用方式和程序源代码里的调用方式保持一致,这里就得采用动态的生成方式。而涉及到类成员的动态生成,采取一种不一样的写法比较好,比如把生成的时间从init方法中提前到new方法中。

widget_instance就是包含信号槽的类,因为我写GUI都是采用MVC的方式,需要导出并拦截的信号槽都在一个类里面,这个类传入的时候已经是个实例了。动态解析该实例源代码,并动态生成新的信号去装载信号槽。

其中,还有个问题,有些调用可能嵌套的好几层,比如像这样。

self.mother.father.son.dog.clicked()

这样的操作需要用递归生成,就像这样。

调用链中自定义生成的节点类为SubNode,槽函数如果动态获取不到时,会返回一个自定义异常FailAttr。

具体的请看Github

六、知识点详解

这一栏列出一些特殊的知识点。

1、getattr,setattr,hasattr:动态的获取对象的方法,给一个对象动态的添加方法,判断一个对象是否含有某方法。

2、__new__魔法方法:这个方法在__init__之前,是真正的类初始化函数。要注意的是new方法需要返回的是类实例,就像源代码中的写法。而在__new__方法中是使用不了实例方法的,得用staticmethod和classmethod装饰器去修饰。

3、staticmethod,classmethod:都是类方法的装饰器,只不过classmethod装饰过的成员方法第一个参数是cls,staticmethod装饰过的东西不引入这个参数,相当于一个纯函数,叫做静态方法。这里的两个函数都可以用classmethod装饰,不过parser_slots函数中用不到cls,我就用staticmethod装饰了。

4、用类方法去区别一些特殊操作,这一方式最常见的就是Django的ORM,将数据库操作和表单的定义分为类方法和成员方法。所以大家理解不了类方法和元类的时候可以去研究下Django的ORM。

5、列表生成式和正则表达式之类的就不解释了。

感觉篇幅有点长,其他的细节如果有需要的话在下一篇文章里解释。如果大家真需要,可以考虑专门搞成一个开源项目。


长按扫描关注Python中文社区,

获取更多技术干货!

    

Python 中 文 社 区

Python中文开发者的精神家园

合作、投稿请联系微信:

pythonpost

— 人生苦短,我用Python —
1MEwnaxmMz7BPTYzBdj751DPyHWikNoeFS



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/BF02jgtRS00XKtCx/article/details/78614477

智能推荐

浏览器工作原理及页面加载的优化建议_b端加载页-程序员宅基地

文章浏览阅读1.4k次。B/S架构,B端的大部分载体是浏览器,浏览器的主要功能是把用户请求的web资源呈现出来,它请求服务器资源,并将其显示在浏览器窗口,资源的格式通常有HTML,PDF,及其他格式。浏览器的主要构成High Level Structure浏览器的主要组件包括:1. 用户界面- 包括地址栏、后退/前进按钮、书签目录等,也就是你所看到的除了用来显示你所请求页面的主窗口之外的其他部分2_b端加载页

他破解了iPhone和PS3 引发了黑客战争-程序员宅基地

文章浏览阅读188次。2007年夏季,世界上的第一台iPhone闪亮登场。但在它问世没多久后,就被天才小子——乔治·霍兹(George Hotz)破解了。苹果公司在发布iPhone的时候,是以AT&T合约机的形式发布的,也就是说iPhone的用户只能使用AT&T公司的网络服务,而霍兹是T-mobile的用户,他想对手上的iPhone进行改装,让其也能够在T-mobile的网络下使用。没有什么能够难倒我们...

金三银四,想拿高薪?你该如何制作一份令人满意的简历?-程序员宅基地

文章浏览阅读83次。经历过秋招的同学一定知道竞争有多激烈,春招的竞争激烈程度并不亚于秋招。因为国考、考研失利的部分同学会成为竞争者中的一员,已经拿到offer的同学也会因为想得到更好的机会而参加。除了竞争人数多以外,作为补招,职位也没有秋招丰富,难免出现僧多粥少的局面。说了这么多,如何才能在春招里突出重围呢?今天乐字节fafa给大家支招,从工作的敲门砖——简历入手,教大家如何制作出一份令人满意的简历。1.简历定位简历定位就是要按照与以上岗位要求相关的内容来开始给自己画一个像,做个定位,履历内容紧贴定位。面试人力资源,就

计算机毕业设计ssm智能旅游线路规划系统设计与实现9xwhi9(附源码)新手必备_规划算法毕业设计-程序员宅基地

文章浏览阅读675次。选题背景:随着人们生活水平的提高和旅游需求的增加,旅游业蓬勃发展。然而,传统的旅游线路规划方式存在一些问题,如信息不全面、规划不科学等。因此,设计与实现一个智能旅游线路规划系统具有重要意义。该系统旨在利用人工智能技术,通过对用户的个性化需求和旅游资源的分析,自动生成最优的旅游线路规划方案,为旅游者提供便捷、高效的旅行体验。意义:智能旅游线路规划系统的设计与实现具有重要的意义。首先,该系统可以提供个性化的旅游线路规划服务。传统的旅游线路规划方式往往只能提供一些常规的旅游线路,无法满足旅游者个性化的_规划算法毕业设计

[面试题][数学与概率]设计随机数生成器_随机数生成器 面试题-程序员宅基地

文章浏览阅读2.9k次,点赞4次,收藏5次。假设你已经有一个随机数生成器,能够以概率p生成0,概率1-p生成1,请问如何设计算法以概率q等概率地生成0-6这七个数字中的一个?即每个数字的概率均为q,q<1/7.我们先从简单的情况开始考虑,假设需要生成0和1,二者概率均为q。那么我们可以让已有的随机数生成器产生两个数字,那么产生的数字及概率是: Number Prob 00 p2p2p^2..._随机数生成器 面试题

最详尽的4K技术科普_x5200w 升级固件-程序员宅基地

文章浏览阅读5.7k次。什么是4K?4K是一个分辨率的范畴,即4096×2160的像素分辨率,一般用于专业设备居多,目前家庭用的设备,如4K电视、4K显示器、4K投影仪甚至是4K蓝光碟等分辨率则为3840x2160。2K分辨率则是2048x1080的像素分辨率,高清电视机、高清显示器、投影仪以及蓝光的分辨率基本上都是1920x1080的像素分辨率。高清 1080p 能够显示的有效像素为2,073,600(19..._x5200w 升级固件

随便推点

前端部署实战(阿里云服务器+nginx)_阿里云 nginx-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏14次。获得自己的服务器后,打开云服务器ECS控制台,在实例中找到自己服务器,点击远程连接,选择通过WorkBench远程连接。开始之间需要安装xshell用于连接服务器,安装xftp用于上传文件,安装完毕后打开xshell,新建一个会话,主机填服务器的公网地址,可在阿里云实例页面查看,填好后点击确定。qiankundemo的主应用和子应用均部署在同一个服务器上,主应用中子应用的配置如下,entry设置为环境变量,开发和部署时分别指向不同的入口,打开服务器公网地址,出现以下页面,说明nginx启动成功。_阿里云 nginx

Python DataFrame时间序列数据(Pandas篇-22)-程序员宅基地

文章浏览阅读1.1k次,点赞33次,收藏18次。Python Pandas 时间序列数据。

篇章结构类型、层次及分析模式研究-程序员宅基地

文章浏览阅读1w次,点赞4次,收藏6次。这篇是何继红、张德禄一篇发表在《外语与外语教学》上的一篇论文,本文是其个人读后感和一些想法。1. 摘要这篇文章中,主要针对的是语篇结构和类型、层级性和分析模式的研究,着重对于语篇的结构类型进行了相关的探讨。我也主要是注重其语篇的结构方面进行相关的思考。2. 语篇、话语与篇章语篇(text)和话语(discourse)、篇章(discourse)之间有着一定的联系。在系统功能语言学中,语篇和话语没有什_篇章结构

linux下flowable流程图乱码或图片中文乱码问题_flowjo界面错乱-程序员宅基地

文章浏览阅读1.5k次。将缺少的字体(如simhei.ttf、simsun.ttc)上传到jdk目录/usr/local/jdk8/jdk1.8.0_201/jre/lib/fonts和/usr/share/fonts 文件夹下_flowjo界面错乱

VUE+ElementUI使用日期选择器时间少8小时_表格导出来的时间与平台相差8小时-程序员宅基地

文章浏览阅读2.5k次,点赞3次,收藏7次。VUE+ElementUI使用日期选择器时间少8小时_表格导出来的时间与平台相差8小时

推荐文章

热门文章

相关标签