面试问题整理之python测试
1.下列哪个语句在Python中是非法的?
A、x = y = z =1 B、x = (y = z + 1)
C、x, y = y, x D、x += y
答案:B
2.关于Python内存管理,下列说法错误的是
A、变量不必事先声明 B、变量无须先创建和赋值而直接使用
C、变量无须指定类型 D、可以使用del释放资源
答案:B. (不先赋值会报错,is not defined)
3、下面哪个不是Python合法的标识符
A、int32 B、40XL C、self D、name
答案:B(合法的标识符不能以数字开头)
4、下列哪种说法是错误的
A、除字典类型外,所有标准对象均可以用于布尔测试
B、空字符串的布尔值是False
C、空列表对象的布尔值是False
D、值为0的任何数字对象的布尔值是False
答案:D (a=0,0, bool(a)为True)
5、下列表达式的值为True的是
A、5+4j >2-3j B、3>2>2
C、(3,2)<(‘a’,‘b’) D、’abc’ > ‘xyz’
答案:C (在Py2.x版本中正确,在Py3.x运行错误)
6、Python不支持的数据类型有
A、char B、int C、float D、list
答案:A(python里无char型数据,有string字符串类型;但C语言中有char数据类型)
7、关于Python中的复数,下列说法错误的是
A、表示复数的语法是real + imagej B、实部和虚部都是浮点数
C、虚部必须后缀j,且必须是小写 D、方法conjugate返回复数的共轭复数
答案:C(复数虚部的后缀也可以是大写的J)
8、关于字符串下列说法错误的是
A、字符应该视为长度为1的字符串
B、字符串以\0标志字符串的结束
C、既可以用单引号,也可以用双引号创建字符串
D、在三引号字符串中可以包含换行回车等特殊字符
答案:B(python因为字符串有长度限制,到了长度就标志字符串的结束)
9、以下不能创建一个字典的语句是
A、dict1 = {} B、dict2 = { 3 : 5 }
C、dict3 ={[1,2,3]: “uestc”} D、dict4 = {(1,2,3): “uestc”}
答案:C(字典的键必须是不变的,而列表是可变的)
10、下列Python语句正确的是:
A、min = x if x< y = y
B、max = x > y ?x:y
C、if (x >y) print x
D、while True :pass
答案:D
python常见的命令行交互自动化模块有哪些?
答案:a)Import module
b) Import module1,module2
c) From module import *
d) Frommodule import m1,m2,m3
e) From module import logger asmodule_logger
12.python的底层网络交互模块有哪些?
答案:socket, urllib,urllib3 , requests, grab, pycurl
13.python网络交互时,二进制打包解包的模块有哪些
打包:pack(), 解包:upk()
14.python的测试框架有哪些?试列出常用的3个或更多
答案:unittest, nose,unittest2, doctest, pytest
15.一行把[1,2,3,1,2,3] 中的重复元素剔除。
答案:list(set([1,2,3,1,2,3]))
16.现在要你使用pyDes(DES加密)和标准库中的namedtuple,假设你之前没有接触过,你如何快速上手?
答案:仔细阅读官方文档中namedtuple库和pyDes的使用。下载pyDes和namedtuple库,借鉴网上的使用教程,摸索实践。
17.Python到底是什么样的语言?你可以比较其他技术或者语言来回答你的问题。
这里是一些关键点:Python是解释型语言。这意味着不像C和其他语言,Python运行前不需要编译。其他解释型语言包括PHP和Ruby。
Python是动态类型的,这意味着你不需要在声明变量时指定类型。你可以先定义x=111,然后 x=”I’m a string”,一点问题也不会有。
Python是面向对象语言,所有允许定义类并且可以继承和组合。Python没有访问访问标识如在C++中的public, private, 这就非常信任程序员的素质,相信每个程序员都是“成人”了~
在Python中,函数是一等公民。这就意味着它们可以被赋值,从其他函数返回值,并且传递函数对象。类不是一等公民。
写Python代码很快,但是跑起来会比编译型语言慢。幸运的是,Python允许使用C扩展写程序,所以瓶颈可以得到处理。Numpy库就是一个很好例子,因为很多代码不是Python直接写的,所以运行很快。
Python使用场景很多 – web应用开发,自动化,科学建模,大数据应用,等等。它也经常被看做“胶水”语言,使得不同语言间可以衔接上。
Python能够简化工作 ,使得程序员能够关心如何重写代码而不是详细看一遍底层实现。
18.Python和多线程,是不是个好主意?列举你觉得可以让Python代码并行运行的方法?
Python实际上不允许多线程。它有一个threading包但是如果你想加快代码运行速度,或者想并行运行,这不是一个好主意。Python有一个机制叫全局解释器锁(GIL)。GIL保证每次只有一个线程在解释器中跑。一个线程获得GIL,之后再交给下一个线程。所以,看起来是多个线程在同时跑,但是实际上每个时刻只有CPU核在跑一个线程,没有真正利用多个CPU核跑多个线程。就是说,多个线程在抢着跑一个CPU核。
但是还是有使用threading包的情况的。比如你真的想跑一个可以线程间抢占的程序,看起来是并行的。或者有很长时间的IO等待线程,这个包就会有用。但是threading包不会使用多核去跑代码。
真正的多核多线程可以通过多进程,一些外部库如Spark和Hadoop,或者用Python代码去调用C方法等等来实现
19.你怎么对你的代码进行跟踪,协同写代码?
使用版本控制:git
20.下面这段代码的输出是什么
def f(x,l=[]):
for i in range(x):
l.append(i*i)
print(l)
f(2)
f(3,[3,2,1])
f(3)
1
2
3
4
5
6
7
8
[0, 1]
[3, 2, 1, 0, 1, 4]
[0, 1, 0, 1, 4]
因为Python内存还是存了第一次残留的l值,所以它以0和1开头。
21.猴子补丁是什么?它是不是一个好主意?
猴子补丁是在一个函数或者对象已经存在的基础上,改变它的行为。比如:
import datetime
datetime.datetime.now = lambda: datetime.datetime(2012, 12, 12)
1
2
大多数时候这不是一个好主意 – 如果早就设计好,不是更好?一个可以使用猴子补丁的地方是做测试,著名的包mock,就是一个很好的例子。
22.*args, **kwargs是什么东西? 我们为什么会用它?
我们用 args 当我们不知道要有多少个参数传给函数,或者我们想把一个列表或者tuple存起来以后传给函数。我们用**kwargs当我们不知道有多少个关键字参数要传给函数,或者我们想把字典存起来以后传给函数。args 和 kwargs的名字是以前遗留下来的,你用bob 和**billy也没关系但是这样不太好,嘿嘿。
23.@classmethod, @staticmethod, @property都是什么意思?
修饰器的概念要懂。拿到一个函数,返回一个函数,或者拿到一个类,返回另一个类。
@my_decorator
def my_func(stuff):
do_things
1
2
3
以上代码相当于:
def my_func(stuff):
do_things
my_func = my_decorator(my_func)
1
2
3
你可以在这里找到修饰器的一般用法。
@classmethod, @staticmethod 和 @property修饰器是使用在类中的。
24.简介地描述下Python的垃圾回收机制
这里可以说许多东西,有几个重点你可以提到:
Python在内存中维护对象的引用次数。如果一个对象的引用次数变为0,垃圾回收机制会回收这个对象作为他用。
有时候会有“引用循环”的事情发生。垃圾回收器定期检查回收内存。一个例子是,如果你有两个对象 o1 和 o2,并且o1.x == o2 and o2.x == o1. 如果 o1 和 o2 都没有被其他对象使用,那么它们都不应该存在。但是它们的应用次数都是1,垃圾回收不会起作用。
一些启发算法可以用来加速垃圾回收。比如,最近创建的对象更可能是无用的。用创建时间来度量对象的生命时长,生命越长,越可能是更有用的对象。
CPython的说明文档中有相关解释。
25.python中有哪些基础类型
有5个标准数据库类型:Numbers(数字) String(字符串) List(列表) Tuple(元组) Dictionary(字典)
26.python里面的深拷贝,浅拷贝
在Python中对象的赋值其实就是对象的引用。当创建一个对象,把它赋值给另一个变量的时候,python并没有拷贝这个对象,只是拷贝了这个对象的引用而已。
浅拷贝:拷贝了最外围的对象本身,内部的元素都只是拷贝了一个引用而已。也就是,把对象复制一遍,但是该对象中引用的其他对象我不复制
深拷贝:外围和内部元素都进行了拷贝对象本身,而不是引用。也就是,把对象复制一遍,并且该对象中引用的其他对象我也复制。
1,深浅拷贝都是对源对象的复制,占用不同的内存空间。
2,不可变类型的对象,对于深浅拷贝毫无影响,最终的地址值和值都是相等的。
3,可变类型:
=浅拷贝: 值相等,地址相等
copy浅拷贝:值相等,地址不相等
deepcopy深拷贝:值相等,地址不相等
27.实现一个字典数据结果的深拷贝
copy浅拷贝
deepcopy深拷贝
from copy import deepcopy
深拷贝和浅拷贝的例子:
data = {'user':'admin','num':[1,2,3]}
data2 = data.copy()
data3 = deepcopy(data)
1
2
3
查看结果
data['user']='root'
data['num'].remove(1)
print(data)
print(data2)
print(data3)
5
输出结果为:
{'user': 'root', 'num': [2, 3]}
{'user': 'admin', 'num': [2, 3]}
{'user': 'admin', 'num': [1, 2, 3]}
1
2
3
总结:
如果源拷贝对象只有一级目录的话,源做任何改动,不影响深浅拷贝对象
如果源拷贝对象不止一级目录的话,源对一级目录的子目录做任何改动,都会影响浅拷贝,但不影响深拷贝
28.循环 迭代 遍历 递归
循环 指的是在满足条件的情况下,重复执行同一段代码。比如,while语句。
[ 循环则技能对应集合,列表,数组等,也能对执行代码进行操作。
迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项。比如,for语句。
[迭代只能对应集合,列表,数组等。不能对执行代码进行迭代。]
遍历(traversal),指的是按照一定的规则访问树形结构中的每个节点,而且每个节点都只访问一次。
[遍历同迭代一样,也不能对执行代码进行遍历。]
递归(recursion),指的是一个函数不断调用自身的行为。比如,以编程方式输出著名的斐波纳契数列。
[线性递归和尾递归。]
29.异常处理机制
捕捉异常可以使用try/except 语句。
try/except 语句用来检测try语句块中的错误,从而让except 语句捕获异常信息并处理。
如果你不想在异常发生时结束你的程序,只需要try 捕获里捕获它。
使用以下语法:
try …except …else 的语法
try:
<语句> #运行别的代码
except <名字>:
<语句> #如果在try部份引发了’name’异常
except <名字>,<数据>:
<语句> #如果引发了’name’异常,获得附加的数据
else:
<语句> #如果没有异常发生
try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。
如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印缺省的出错信息)。
如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句
30.class类中(self)指的是什么
self 指的是类本身。
31.range 函数的使用,其中有那两个参数
函数语法:
range(start, stop[,step])
参数说明:
start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5);
stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5
step:步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)
我们可以从以下几个方面来提高速度:
一,减少操作步骤,如经过三四步才能打开我们要测试的页面的话,我们就可以直接通过网址来打开,减少不必要的操作。
二,中断页面加载,如果页面加载的内容过多,我们可以查看一下加载慢的原因,如果加载的内容不影响我们测试,就设置超时时间,中断页面加载。
三,在设置等待时间的时候,可以sleep固定的时间,也可以检测某个元素出现后中断等待也可以提高速度。
四,配置testNG实现多线程。在编写测试用例的时候,一定要实现松耦合,然后在服务器允许的情况下,尽量设置多线程运行,提高执行速度。
一,网速问题:有的时候网页加载的比较慢,在程序执行的时候要操作的元素没有显示出来。这种情况比较常见,运行一次网速好的时候通过了,再运行一次,页面没有打开,就不通过了。为了提高稳定性,我们只能牺牲运行时间了,在经常检测失败的元素前加上等待时间,等要操作的元素出现之后再执行下面的操作。
二,Selelnium的原因:Selenium1.0和2.0还是有区别的,有些儿函数在2.0下运行确实有时而有效,时面无效。如果mouseover()函数,就是这种情况, 我们需要避免使用这类的函数。
三,多线程的时候,测试用例间相互影响。虽然多线程的时候运行速度比较快,但是如果用例之间的耦合性没有设计好,也会影响的,如果用例A先于用例B执行的时候,就会影响到用例B;反之则没有问题。这种情况,如果你的自动化测试工程打算多线程的时候,提前就要把测试用例测试的耦合度比较松,尽量没有任何关系,因为多线程的执行顺序是不受控制的。
一,自动化测试用例是用来监控的,在此目的下,我们就把自动化测试用例设置成定时执行的,如果每五分钟或是一个小时执行一次,在jenkins上创建一个定时任务即可。
二,必须回归的用例。有些儿测试用例,如BVT测试用例,我们在公司产品任何变动上线之前都需要回归执行。那我们就把测试用例设置成触发式执行,在jenkins上将我们的自动化测试任务绑定到开发的build任务上。当开发人员在仿真环境上部代码的时候,我们的自动化测试用例就会被触发执行。
三,不需要经常执行的测试用例。像全量测试用例,我们没有必要一直回归执行,必竟还是有时间消耗的,有些非主要业务线也不需要时时回归。这类测试用例我们就采用人工执行,在jenkins创建一个任务,需要执行的时候人工去构建即可。
通过研究selenium-webdriver的源码,笔者发现其实webdriver的实现原理并不高深莫测无法揣度。在这里以webdriver ruby binding的firefox-webdriver实现为例,简单介绍一下webdriver的工作原理。
-
当测试脚本启动firefox的时候,selenium-webdriver 会首先在新线程中启动firefox浏览器。如果测试脚本指定了firefox的profile,那么就以该profile启动,否则的话就新启1个profile,并启动firefox;
-
firefox一般是以-no-remote的方法启动,启动后selenium-webdriver会将firefox绑定到特定的端口,绑定完成后该firefox实例便作为webdriver的remote server存在;
-
客户端(也就是测试脚本)创建1个session,在该session中通过http请求向remote server发送restful的请求,remote server解析请求,完成相应操作并返回response;
-
客户端接受response,并分析其返回值以决定是转到第3步还是结束脚本;
这就是webdriver的工作流程,看起来很复杂实际上当了解了webdriver的实现原理后,理解上述问题应该比较简单。
webdriver是按照server – client的经典设计模式设计的。
server端就是remote server,可以是任意的浏览器。当我们的脚本启动浏览器后,该浏览器就是remote server,它的职责就是等待client发送请求并做出相应;
client端简单说来就是我们的测试代码,我们测试代码中的一些行为,比如打开浏览器,转跳到特定的url等操作是以http请求的方式发送给被 测试浏览器,也就是remote server;remote server接受请求,并执行相应操作,并在response中返回执行状态、返回值等信息;
28、get和post 的区别?(感觉可能答案不对)
-因为使用GET请求不会产生什么动作。不会产生动作意味着GET的HTTP请求不会在服务器上产生任何结果。但是安全方法并不是什么动作都不产生,这里的安全方法仅仅指不会修改信息。POST可能会修改服务器上的资源的请求。比如CSDN的博客,用户提交一篇文章或者一个读者提交评论是通过POST请求来实现的,因为再提交文章或者评论提交后资源(即某个页面)不同了,或者说资源被修改了。
两种请求方式的区别:
1、GET请求,请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。URL的编码格式采用的是ASCII编码,而不是uniclde,即是说所有的非ASCII字符都要编码之后再传输。
POST请求:POST请求会把请求的数据放置在HTTP请求包的包体中。上面的item=bandsaw就是实际的传输数据。因此,GET请求的数据会暴露在地址栏中,而POST请求则不会。
2、传输数据的大小
在HTTP规范中,没有对URL的长度和传输的数据大小进行限制。但是在实际开发过程中,对于GET,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制。
对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对POST提交数据大小进行限制,Apache、IIS都有各自的配置。
3、安全性
POST的安全性比GET的高
29、公司内一直在使用的测试系统(B/S架构)突然不能访问了,需要你进行排查并恢复,说出你的检查方法
答:一、网站输入域名直接无法访问,网站之前还正常,突然就无法访问