面试常用(python测试)

1. XPath

    即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。

    XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力

2.Appium工作原理(Android)

  • client端也就是我们 test script是我们的webdriver测试脚本。
  • 中间是appium服务端
  • appium服务端接收到webdriver客户端的标准rest,解析请求内容为响应指令。(rest:表述性状态转移:是一组架构约束条件和原则)
  • 转发给服务端的中间件Bootstrap.jar ,安装在手机上.Bootstrap监听4724端口并接收appium 的命令,通过调⽤用UiAutomator的命令来实现。
  • 执行完相应指令之后、Bootstrap将执行的结果返回给appium server。
  • appium server再将结果返回给 appium client。

3.selenium 原理

我们写的自动化程序 需要使用一个Selenium组织提供的 客户端库

我们程序的自动化请求都是通过使用这个库的接口对象完成的。 比如调用某个元素对象的click方法, 就会发送点击这个元素的请求给 下方的浏览器驱动

这个自动化程序的请求是通过客户端库,构建出相应的HTTP请求,发送给浏览器驱动的。

浏览器驱动 也是一个独立的程序,是由浏览器厂商提供的, 不同的浏览器需要不同的浏览器驱动。 比如 Chrome浏览器和 火狐浏览器有 各自不同的驱动程序。

浏览器驱动接收到我们的自动化程序发送过来的界面操作请求后,会转发请求给浏览器, 让浏览器去执行对应的自动化操作。

浏览器执行完操作后,会将自动化的结果返回给浏览器驱动, 浏览器驱动再通过http响应的消息返回给我们的自动化程序的客户端库。

自动化程序的客户端库 接收到响应后,将结果转化为 数据对象 返回给我的自动化程序代码。我们的程序就可以知道这次自动化操作的结果如何了。

4.python数据类型

python Number,string list set dict tupple ,不可变:number,string tupple,可变:list,set,tupple

5.浏览器输入地址到返回结果流程

https://blog.csdn.net/xiaoyi52/article/details/88356079?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare

dns域名解析,三次握手建立连接,发送请求,服务器处理请求返回结果,浏览器收到结果进行渲染处理。

6.jenkins执行流程

1.基础配置:设置项目名称,节点机器等信息,2.配置源码管理工具3.配置定时构建4.设置构建方式,进行构建,5.构建后操作,报告展示,邮件发送等

7.Python中filter()、map()和reduce()的区别
 

2.1、概述:

filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。

map() 会根据提供的函数对指定序列做映射

reduce() 函数会对参数序列中元素进行累积。

2.2、详细描述:

filter()函数

1.语法:

filter(function, iterable)

该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回

True 或 False,最后将返回 True 的元素放到新列表中。

2.案例: 得到列表中的奇数

def is_odd(n):

return n % 2 == 1

newlist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

for n in newlist:

print(n)
map函数:

1.语法:

map(function, iterable, ...)

第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。

2. 案例: 提供了两个列表,对相同位置的列表数据进行相加

result = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])

print(result)# [3, 7, 11, 15, 19]

将后面两个列表中的分别一一对应取出之后传递给x,y.
reduce()函数:

1.语法:

reduce(function, iterable[, initializer])

函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参

数)先对集合中的第 1、2 个元素 进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

python3中将 reduce 放在functools模块中了

2. 案例: 提供了两个列表,对相同位置的列表数据进行相加

from functools import reduce

result = reduce(lambda x, y: x+y, [1,2,3,4,5])

print(result)#15

2.3、应用场景:

面试题: 分别使用map,reduce,filter函数完成下面的任务

1、计算1-100的和

from functools import reduce

result = reduce(lambda x, y: x + y, range(1, 101))

print(result)

2、1-10,对每个数字的平方

result = map(lambda x:x**2,range(1,11))for n in result:print(n)

8.python垃圾回收机制

引用计数为主,标记清除和分代回收为辅

  • 从基本原理上,当Python的某个对象的引用计数降为0时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。但是,垃圾回收时,Python不能进行其它的任务。频繁的垃圾回收将大大降低Python的工作效率。如果内存中的对象不多,就没有必要总启动垃圾回收。所以,Python只会在特定条件下,自动启动垃圾回收。当Python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数。当两者的差值高于某个阈值时,垃圾回收才会启动。

  • 我们可以通过gc模块的get_threshold()方法,查看该阈值:

    import gc
    print(gc.get_threshold())
    

    返回(700, 10, 10),后面的两个10是与分代回收相关的阈值,后面可以看到。700即是垃圾回收启动的阈值。可以通过gc中的set_threshold()方法重新设置。我们也可以手动启动垃圾回收,即使用gc.collect()。

  • 分代回收: python同时采用了分代(generation)回收的策略。这一策略的基本假设是,存活时间越久的对象,越不可能在后面的程序中变成垃圾。我们的程序往往会产生大量的对象,许多对象很快产生和消失,但也有一些对象长期被使用。出于信任和效率,对于这样一些“长寿”对象,我们相信它们的用处,所以减少在垃圾回收中扫描它们的频率。python将所有的对象分为0,1,2三代。所有的新建对象都是0代对象。当某一代对象经历过垃圾回收,依然存活,那么它就被归入下一代对象。垃圾回收启动时,一定会扫描所有的0代对象。如果0代经过一定次数垃圾回收,那么就启动对0代和1代的扫描清理。当1代也经历了一定次数的垃圾回收后,那么会启动对0,1,2,即对所有对象进行扫描。这两个次数即上面get_threshold()返回的(700, 10, 10)返回的两个10。也就是说,每10次0代垃圾回收,会配合1次1代的垃圾回收;而每10次1代的垃圾回收,才会有1次的2代垃圾回收。同样可以用set_threshold()来调整,比如对2代对象进行更频繁的扫描。

  • 孤立的引用环: 引用环的存在会给上面的垃圾回收机制带来很大的困难。这些引用环可能构成无法使用,但引用计数不为0的一些对象。比如我们创建了两个表对象,并引用对方,构成一个引用环。删除了a,b引用之后,这两个对象不可能再从程序中调用,就没有什么用处了。但是由于引用环的存在,这两个对象的引用计数都没有降到0,不会被垃圾回收。

    a = []
    b = [a]
    a.append(b)
    
    del a
    del b
    

    为了回收这样的引用环,python复制每个对象的引用计数,可以记为gc_ref。假设,每个对象i,该计数为gc_ref_i。python会遍历所有的对象i。对于每个对象i引用的对象j,将相应的gc_ref_j减1。在结束遍历后,gc_ref不为0的对象,和这些对象引用的对象,以及继续更下游引用的对象,需要被保留。而其它的对象则被垃圾回收。

9.冒泡排序

def bubbleSort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n - i - 1):

            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

10.取出列表中的所有奇数

a = [1, 2, 3, 4]
b = [i for i in a if i % 2 == 1]
print(b)

11.打印99乘法表


for x in range(1, 10):
    for y in range(1, x + 1):
        print("%s*%s=%s" % (y, x, x * y), end=" ")
    print("")

12.二分法排序

def twofind(n,l):
    min = 0
    max = len(l)
    if n in l:
        while True:
            mid = int((max + min) / 2)
            if n > l[mid]:
                min = mid
            elif n < l[mid]:
                max = mid
            else:
                if n == l[mid-1]:
                    return (mid - 1)
                else:
                    return (mid)
    else:
        return -1

13.将 alist 中的元素按照 age 从大到小排序。

alist=[{"name":"a", "age":20}, {"name":"b", "age":30}, {"name":"c", "age":25}]
alist.sort(key=lambda x:x['age'],reverse=True)
print(alist)

14。将a,b he为字典

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
# 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
a = ['a','b','c','d','e']
b = [1,2,3,4,5]
c = dict(zip(a,b))
print(c)

15.简介selenium中难点

#selenium 中难点介绍:1.多级frame,2.元素等待,使用WebDriverWait和expected_conditions 进行循环等待查找元素,超时就退出。3.下载框不属于浏览器的需要用
# PyuserInput中的pykeyboard进行处理4.selenium 无法处理的一些操作使用execute_js执行js操作来进行滚动条等操作

16.常用linux命令

ls cd pwd mv cp touch mkdir cat wc su rm -rf kill -9 ifconfig top chmod

17.说出下列结果(生成器应用)

def add(n, i):
    return n + i

def test():
    for i in range(4):
        yield i

g = test()

for n in [1, 10, 5]:
    g = (add(n, i) for i in g)
    print("===========")
print(list(g))

解析:

# 所有的结果都是生成器表达式,不调用它,不从里面取值就不会取值
# 当n=1时,g=(add(1, i) for i in g),其中g=test()即g =(add(1, i) for i in test()) 结果是1,2,3,4
# 当n=10时,括号里边的g是上一次循环结束时的g,即括号中的g g =(add(1, i) for i in test()),
# 括号外的g=(add(10, i) for i in (add(10, i) for i in test()))

n = 1
g = (add(n, i) for i in test())
print(next(g))
# print(list(g)) # [1, 2, 3, 4]

n = 10

g = (add(n, i) for i in (add(n, i) for i in test()))

# print(list(g)) # [20, 21, 22, 23]
n = 5

g = (add(n, i) for i in (add(n, i) for i in (add(n, i) for i in test())))

g = (add(n, i) for i in (add(n, i) for i in (5, 6, 7, 8)))

g = (add(n, i) for i in (10, 11, 12, 13))

18.python命令和python -m命令在执行脚本时的区别?

命令行执行.py文件时有两种加载方式:
python xxx.pypython -m xxx
这是两种加载py文件的方式:
前者叫做直接运行,此时脚本的__name__'main'
后者把模块当作脚本来启动,相当于import,此时脚本的__name__'xxx'。这种启动方式时最好不要带后缀.py

不同的加载py文件的方式,主要是影响sys.path这个属性。sys.path是一个list,是当前Python解析器运行的环境,Python解析器会在这些目录下去寻找依赖库。python导入文件或模块时默认会先在sys.path里找其的路径。

https://blog.csdn.net/djw931017/article/details/88981481?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.compare

19.python中深拷贝与浅拷贝

在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去,而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。

https://www.cnblogs.com/zuanzuan/p/10185075.html

20.python中多进程、多线程、协程

https://www.cnblogs.com/jcjc/p/11588933.html

21.迭代器与生成器

 

22.登录页面怎么测?


答:用例设计参考:
功能测试:

    1>输入正确的用户名密码,点击提交按钮,验证能否正确登录

    2> 输入错误的用户名或者密码,点击提交按钮,验证登录失败,提示相应的错误信息

    3 >登录成功后能否跳转到正确的页面

    4>账号名或者密码长度过长或者过短,应该怎么处理(安全性,密码太短是否有提示)

    5>账号和密码有特殊字符(空格),是否做了过滤

    6>密码是否加密显示

    7>输入密码 ,大写键盘开启的时候要有提示信息

    8>什么都不输入,直接点击提交(非空检查)

    9>登录失败后,不能记住密码的功能

   10>登录页面中忘记密码等等链接跳转是否正确

   11>牵扯到验证码,还要考虑文字是否扭曲过度导致辨认难度大

UI测试:

    1>布局是否合理,两个textbox和一个按钮是否对齐

    2>textbox的长度和高度是否符合要求

    3>界面设计风格和UI设计风格是否一致

    4>界面中的文字简洁易懂,没有错别字

性能测试:

     1>打开登录界面,需要几秒

     2>输入正确的用户名和密码,登录成功跳转到新页面,需要几秒

安全性测试:

      1>登录成功后的cookie是否有HttpOnly(降低脚本风险)

      2>账号和密码是否通过加密的方式,发送给web服务器

      3>账号和密码的验证,应该是用服务器验证,而不单单是在客户端用javaScript验证

      4>账号和密码的输入框,应该屏蔽SQL注入攻击

      5>账号和密码的输入框,应该禁止输入脚本(防止XSS攻击)

      6>错误登录的次数限制(防止暴力破解)

      7>是否支持多用户在同一台机器上登录

      8>一用户在多台机器上登录

可用性测试:

      1>输入框是否可以用tab键切换

      2>输入账号,密码后按回车,是否可以登录

      3>是否可用全用键盘操作,是否有快捷键

兼容性测试:

       1>主流的浏览器下能否显示正常已经功能正常

       2>不同的平台是否能正常工作,eg:windows,mac

       3>移动设备上是否正常工作,比如iphone,android

       4>不同的分辨率

23.搜索框怎么测试?

答:测试搜索框,需从以下几个方面进行考虑:

一、功能实现
输入字符,有匹配的就展示出来,没有匹配的,会进行处理
1.对输入进行测试
正常输入存在的内容,查看搜索结果展示的数据是否完整
正常输入不存在的内容,查看搜索返回的结果
输入为空
超长输入
特殊符号,包含空格,特别要注意英文单引号
各种字符,如数字、字母、中文
反复输入相同的数据,如5次以上,看处理是否正确
输入正则表达式
验证搜索框的功能是否与需求一致,如模糊搜索或完全搜索
是否有忽略空格的功能,忽略前置空格和忽略后置空格,但是不能忽略中间空格
2.快捷键:
 在输入结束后,按回车键,看系统如何处理
使用Tab键 ,ctrl+c /v/xz
3.光标和鼠标:
在光标停留的地方进行输入,看光标和输入的字符位置是否正确,会否跳转到别的地方
在输入框中,左键单击鼠标,双击鼠标,三击鼠标,如百度输入框,单击是插入,双击选中两个字符,三击选中输入的所有字符
输入框中,鼠标右键,会否有菜单栏,菜单栏下是否有常用的项,并且各项可用
4.其它功能
如百度的即搜即得,随着用户的输入,下面会列出好多实时变化的选项,类似于智能搜索
二、用户友好与易用性
三、不同平台的兼容性
浏览器,操作系统,分辨率

24.在执行脚本过程,如何实现当前元素高亮显示?

这个其实就是利用javaScript去修改当前元素的边框样式来到达高亮显示的效果

exectue_script('js脚本', 参数1,参数2,参数3...),在JavaScript脚本字符串中使用arguments[n]来表示匹配第几个参数。

示例代码如下:

Copy
from selenium import webdriver
from time import sleep

STYLE = "background: green; border: 2px solid red;"  # 高亮的样式

def find(driver, by, expr):
    element = driver.find_element(by, expr)
    driver.execute_script("arguments[0].setAttribute('style', arguments[1]);",element, STYLE)  
    return element

driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')

find(driver, 'id', 'kw').send_keys("博客园 韩志超")
find(driver, 'id', 'su').click()

sleep(3)
driver.quit()

以上代码中,
by只定位方式,支持'id','xpath', 'name', 'class name', 'link text', 'partial link text', 'css selector', expr为元素对应的定位表达式。
driver.execute_script("arguments[0].setAttribute('style', arguments[1]);",element, STYLE)
将定位到的元素替换到arguments[0], 样式STYLE替换arguments[1],及为该元素添加高亮杨样式。

25.自动化测试框架

自动化框架主要的核心框架就是分层+PO模式:分别为:基础封装层BasePage,PO页面对象层,TestCase测试用例层。然后再加上日志处理模块,ini配置文件读取模块,unittest+ddt数据驱动模块,jenkins持续集成模式组成。

26.括号匹配问题

使用栈这种数据结构进行,后进先出,左括号入栈,是右括号就判断是否与栈顶匹配,匹配返回true,否则返回False

    给定一个字符串,里边可能包含“()”、"{}"、“[]”三种括号,请编写程序检查该字符串的括号是否成对出现。

    输出:

    true:代表括号成对出现并且嵌套正确,或字符串无括号字符。

    false:未正确使用括号字符。



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

BRANKETS = {'}':'{',']':'[',')':'('}
BRANKETS_LEFT, BRANKETS_RIGHT = BRANKETS.values(), BRANKETS.keys()

def bracket_check(string):
    """括号匹配检测函数"""
    stack = []
    for char in string:
        # 如果是左括号
        if char in BRANKETS_LEFT:
            # 入栈
            stack.append(char)
        # 右括号
        elif char in BRANKETS_RIGHT:
            # stack不为空,并且括号匹配成功
            if stack and stack[-1] == BRANKETS[char]:
                # 出栈
                stack.pop()
            # 匹配成功
            else:
                return False

    return not stack

def main():
    print(bracket_check('{brace*&^[square(round)]end}'))
    print(bracket_check('{brace*&^[square(round])end}'))

if __name__ == '__main__':
    main()

count(str[,start][,end])
判断字符串中,从start开始的下标到字符串的结尾end中出现了多少个str (给定字符)
如果 start到end 没写 默认 从头到尾字符串中出现str出现的次数

27.sql中where和having的区别
 

用的地方不一样

   where可以用于select、update、delete和insert into values(select * from table where ..)语句中。

   having只能用于select语句中
执行的顺序不一样

   where的搜索条件是在执行语句进行分组之前应用

   having的搜索条件是在分组条件后执行的

   即如果where和having一起用时,where会先执行,having后执行
子句有区别

   where子句中的条件表达式having都可以跟,而having子句中的有些表达式where不可以跟;
having子句可以用集合函数(sum、count、avg、max和min),而where子句不可以。
总结

 1.WHERE 子句用来筛选 FROM 子句中指定的操作所产生的行。
2.GROUP BY 子句用来分组 WHERE 子句的输出。
3.HAVING 子句用来从分组的结果中筛选行

28.查找一个路径下的所有文件

def get_all_path(open_file_path):
    rootdir = open_file_path
    path_list = []
    list = os.listdir(rootdir)  # 列出文件夹下所有的目录与文件
    for i in range(0, len(list)):
        com_path = os.path.join(rootdir, list[i])
        #print(com_path)
        if os.path.isfile(com_path):
            path_list.append(com_path)
        if os.path.isdir(com_path):
            path_list.extend(get_all_path(com_path))
    #print(path_list)
    return path_list

29.十进制与二进制互相转换

def ten_to_bin(num):
    '''
    十进制转二进制,取余数,然后余数到过来
    :param num:
    :return:
    '''
    result = ''
    while num != 0:
        yu = num % 2
        num = num // 2
        print(num, yu)
        result = str(yu) + result
    return result


def bin_to_ten(num):
    '''
    二进制转十进制,对应位置数字乘以2的(n-i-1)次方,n为数字长度
    :param num:
    :return:
    '''
    n = len(str(num))
    result = 0
    for i in range(n):
        result = result + int(2 ** (n - i - 1)) * int(str(num)[i])
    return result

 

 

 

 

 

 

 

 

https://blog.csdn.net/yuelai_217/article/details/100210918

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值