单例设计模式
工厂模式
PO设计模式
数据驱动模式
面向接口编程设计模式
断言 Assert 用于在代码中验证实际结果是不是符合预期结果,
如果测试用例执行失败会抛出异常并提供断言日志
Web自动化测试是从UI (用户界面)层面进行的自动化测试,
测试人员通过编程自动化程序(测试用例脚本)来打开浏览器测试网站的业务逻辑。
Selenium是一个开源的web自动化测试框架,支持多种编程语言开发自动化测试脚本,支持跨浏览器平台进行测试
WebDriver、InternetExplorerDriver、 FirefoxDriver、 ChromeDriver、 WebElement、WebDriverWait、 By
import logging # Python日志包,用来记录日志 from selenium.webdriver.remote.webdriver import WebDriver # 通过向远程服务器发送命令来控制浏览器。此服务器应运行WebDriver wire协议 from selenium.webdriver.support.wait import WebDriverWait # 构造函数,以秒为单位获取WebDriver实例和超时。 from selenium.webdriver.support import expected_conditions as EC # 在webdriver中通常有用的“预期条件” import datetime # 日期时间 import time # “时间”模块的存根文件 import os # 获取文件路径 from selenium.webdriver.common.by import By # 支持的定位器策略集
By类一共有8种元素定位方式,它们都是静态方法:
By.id():
By.name():
By.tagName():
By.className():
By.cssSelector():
By linkText():
By partialLinkText():
By.xpath():
它是查找 web 页面元素的一种方式,相当于元素在 dom 中间的一个路径,可以采用绝对路径和相对路径的方式进行定位
它对于定义动态的页面元素有很大的帮助,同时也需要谨慎使用,因为如果页面结构发生变化,那么定位信息也可能需要变化。
两个都是查找页面元素的方法
findElement():查找一个页面元素,只会返回一个WebElement对象
findElements() :查找页面上所有符合匹配的元素,返回元素集合
还可以使用 submit() 方法,前提是 input 元素的 type 为 submit
如果系统支持可以使用键盘操作
优化等待时间:使用 WebDriverWait 智能等待来代替线程(强制)等待 sleep 和 隐式等待 implicityWait(译:音谱乐色第)
减少不必要的操作:如直接进入某页面代替经过一系列自动化操作进入某页面在服务器允许的情况下,使用多线程实现并发执行测试用例.
1) :图像识别,技术难度大,效果不佳,不推荐
2) :屏蔽验证码,邀请开发处理,但在预生产环境或者生产环境不推荐
3) :万能验证码,使用一个复杂的其他人无法猜到的验证码;我也研究过验证码的处理,比如滑动验证码滑块和缺口的位置鼠标进行操作,图片验证网上的打码工具来验证;
可以使用元素的 isSelected() (译:一色类戴特)方法,如果返回的是 true 则说明被选中,否则表明未被选中
处理 alert 弹窗首先需要先跳转到 alert 上,然后在点击确定或者取消按钮,
Alert alert = driver.switchTo().alert();//切换到alert
alert.accept0; //确定
alert.dismiss0; //取消
如果下拉菜单是 select 标签,使用方法:selectByValue() 或者 selectByIndex() 或者 selectByVisibleText() 即可
如果这个下拉菜单不是通过 select 标签创建,则直接通过 xpath 定位元素然后去点击选择
driver.navigate().back()://后退
driver. navigate().forward()://前进
driver.navigate0.efresh()://刷新
String url = driver.getCurrentUrl(); # (译:给特珂润特.URL)
close() (译:可篓子)方法只是关闭当前正在操作的窗口
quit() :(译:快特)是关闭了所有已经打开的窗口
成本比较大,而成效可能并不高
适合自动化测试的功能有限
某些功能操作相对复杂,比如验证码
维护成本高,一旦项目需求变更,自动化测试脚本和用例就需要改进
如果是 input 类型,可以直接输入路径的,直接调 send_ keys (译:森德K子)输入路径
与 windows 窗口进行交互,,可以使用 pywin32 库,通过识别对话框句柄来实现。
这两个库:
import win32gui
import win32con
xpath定位:直接//d1 [@class="inf_bar clearfx"]
css定位: d1.inf_bar.clearfix
使用 switch_ to.frame 切换进 iframe 当中后 ,再去定位其中的元素并操作
iframe(译:哎服润么)切换,两种方式,七中方法
方式一:支持三种方法;switch_to.frame(切换方法) (译:思维吃.服润么)
切换三种方法切换:下标切换、name名字属性切换、webelement对象切换
方式二:更加稳定,支持四种
骚操作:EC条件 - 条件:等待iframe有效并切换到iframe当中。
EC(译:一科四盘课题的.肯迪深思)模块中的 frame_to_be_available_and_switch_to_it(译:福软木.图.比.额为类bou.按得.思维吃.图.易特)判断方法
支持四种方法切换:下标切换、name名字属性切换、webelement对象切换、元素定位元组
先获取所有窗口句柄,然后使用 switch_ to.window() 切换到指定窗口
先修改关闭 readonly 属性,然后再操作元素。
a = [1, 6, 7, 4, 4, 5, 4, 5, 4, 5, 5, 6, 7, 8, 5, 6, 7, 3, 4, 2, 2, 1, 4, 8, 9, 4, 5, 6] def get_datas(a): result = [] data_dict = {} # 键值对:键:数字,值:在列表中的次数 for item in set(a): data_dict[str(item)] = a.count(item) print(data_dict) # 将键值对按值(数字出现的次数)排序 ---从高到低排序 res = sorted(data_dict.values(),reverse=True) for num in res: for key,value in data_dict.items(): # 如果值在列表中不存在,则添加到结果列表中 if num == value and key not in result: result.append(key) return result a1 = get_datas(a)
执行结果:
1、设计一个登陆程序,不同的用户名和对应密码存在一个字典里面,输入正确的用户和密码去登陆,
2、首先输入用户名,如果用户名不存在或者为空,则一直提示输入正确的用户名
3、 当用户名正确的时候,提示去输入密码,如果密码跟用户名不对应,则提示密码错误请重新输入。
4、如果密码输入错误超过三次,中断程序运行。
5、当输入密码错误时,提示还有几次机会
6、用户名和密码都输入成功的时候, 提示登陆成功!
users = {"admin": "123456", "user1": " 123456"} count = 0 def login(): global count username = input("请输入用户名:") if username == None or username == "": login() if username not in users.keys(): print("用户名输入不正确,请重新输入用户名:") login() while (count < 3): passwd = input("请输入密码:") if passwd == users[username]: print("登录成功!!") count = 3 else: count += 1 print("密码输入错误,您还有{0}次机会。".format(3 - count)) login()
1、能在当前目录以及当前目录的所有子目录下查找文件名包含指定字符串的文件;
2、并打印出相对路径。
import os paths = [] def get_paths(dir, relate_dir=None, search_str=None): global paths if search_str == None: return os.listdir(dir) for item in os.listdir(dir): if relate_dir == None: relate_dir == os.curdir if os.path.isfile(os.path.join(dir, item)): if item.find(search_str) != -1: paths.append(os.path.join(relate_dir, item)) elif os.path.isdir(os.path.join(dir, item)): paths = get_paths(os.path.join(dir, item), os.path.join(relate_dir, item), search_str) return paths dir = os.getcwd() search_str = "fun" print(get_paths(dir, search_str=search_str))
def f(str1, *args, **kwargs): print(str1, args, kwargs) l = [1, 2, 3] t = [4, 5, 6] d = {"a": 7, "b": 8, "c": 9} f(1, 2) f(1, 2, 3, "python") f("python", l, d) f("python", *t) f("python", *l, **d) f("python", q="winning", **d)
执行结果:
1 (2,) {} 1 (2, 3, 'python') {} python ([1, 2, 3], {'a': 7, 'b': 8, 'c': 9}) {} python (4, 5, 6) {} python (1, 2, 3) {'a': 7, 'b': 8, 'c': 9} python () {'q': 'winning', 'a': 7, 'b': 8, 'c': 9}
import copy a = [1, 2, 3, 4, ["a", "b"]] b = a c = copy.copy(a) d = copy.copy(a) a.append(5) a[4].append("c") # 请根据以上规则填写一下输出内容 print('a=', b) print('b=', b) print('c=', c) print('d=', d)
执行结果:
a= [1, 2, 3, 4, ['a', 'b', 'c'], 5] b= [1, 2, 3, 4, ['a', 'b', 'c'], 5] c= [1, 2, 3, 4, ['a', 'b', 'c']] d= [1, 2, 3, 4, ['a', 'b', 'c']]
keys = ["A", "B", "C"] values = ["1", "2", "3"] print(dict(zip(keys, [int(x) for x in values])))
list_1 = ["a", "b", "c", "1", "A", "winning"] list_2 = ["a", "python", "string"] print(set(list_1 + list_2)) # 执行结果:{'c', 'winning', '1', 'string', 'b', 'a', 'python', 'A'}
a = [{"x": 1, "y": 2}, {"x": 2, "y": 3}, {"x": 3, "y": 4}] aa1 = sorted(a, key=lambda item: item["x"], reverse=True) print(aa1) # 执行结果:[{'x': 3, 'y': 4}, {'x': 2, 'y': 3}, {'x': 1, 'y': 2}]
两行量列的表格 -- - - -
print("\"let's go\",she said")
import random fs = open("num.txt", "a") list1 = [] for index in range(10): num = random.randint(0, 10) list1.append(str(num)) print(list1) fs.write(",".join(list1)) fs.close()
执行结果:
a = 1 def fun(a): a = 2 fun(a) print(a) # 执行结果:1
===============
b = [] def fun(b): b.append(1) fun(b) print(b) 执行结果:[1]
A,UI自动化
B,接口自动化
C, Web自动化
D,终端自动化
所谓会话就是 session ,而 session 是一种服务器的缓存技术,由服务器端创建,
用户登录了系统,一般就会把登录用户的信息保存到这个 session 对象中,然后把此会话对应的id ( JSESSIONID )返回,
因此大部分系统都会用到 session 机制来实现鉴权。Session 保存数据方式也是以key-value的形式。
所谓 token 其实就是服务器端返回的一个字符串(有点类似于: xys73494954sdhcdr83435这么一串),这个数据是基于什么算法生成的需要找开发确认,一般这个数据是唯一的,服务器每次返回的token都会不一样。
Token 之所以可以用来做鉴权,原理如下:
用户 a 调用了登录接口 ---》登录了系统b ---》服务器端生成了一个唯一的 token 信息(假设为c) ,
然后会拿用户的编号id(假设为d)做了一个映射:c - d,
然后将这样的映射关系存到数据库或 redis 等缓存中,
然后再返回这个token给客户端 ---》客户端再调用其他需要鉴权的接口时,
只需要将缓存起来的这个 token 带过去验证 --》服务器根据此token检查是否有登录用户信息来判断此请求是否是一个已登录授权的用户。( 这里客户端怎么取到这个token ,怎么存,再次请求时怎么带过去,上面接口鉴权部分已解释)。
Mysql ,可以通过 jdbc 来实现数据库的增删查改等操作。
用过, junit (不熟的话就可以不用说) , testng ,这些测试框架都支持我们去定义测试套件,达到管理我们测试用例代码的作用,同时这些测试框架提供的一些丰富注解不仅能很方便的控制测试用例的执行顺序来控制整个测试流程,还能为各种测试场景的实现提供支撑。
常用注解:
@Test ,用来标记测试方法
@BeforeSuite ,适合套件的全局初始化,在整个套件执行前先执行
@BeforeTest ,适合Test测试集的初始化,在测试集执行前先执行
@BeforeClass ,适合Class测试类的初始化,在测试类被调用时执行
@BeforeMethod ,适合测试方法执行前的初始化,在测试方法前先执行
@After... ,对比上面的来回答, 执行顺序跟上面的刚好相反,作用适合做一些回收资源。
@Parameters :参数化注解,方便实现参数化
@DataProvider :数据提供者,可以用来提供测试用的批量测试数据
接口是服务,是功能点实现,是数据传递的通道,也是服务器端的一个实现了某种协议(比如http协议.. )和映射机制(当访问一个url 时就会通过服务器端的映射处理机制解析后,落到对应的处理函数)的函数,接口参数就是函数的参数,接口的响应数据就是函数的返回值。
做过(即时你之前没有用过可视化工具做过接口测试,但你现在学了接口自动化测试就算有经验了)。
熟悉的工具:
可视化工具比如:jmeter,postman , soapui等(用过哪些说哪些)
代码: httpclient 发包技术来实现接口测试。
工具做自动化测试 依赖 和 局限性 很强,有些工具提供了断言方法和表达式,但是上手成本高,而且已经提供的现有的断言表达式可能无法满足某些特殊规则的数据验证,而代码的话就相当灵活更多,断言方式可以随便按照自己的想法去设计。
Get :
a.一般对于从服务器取数据的请求可以设置为get方式
b.Get 方式在传递参数的时候,一般都会把参数直接拼接在url上(例如:http://xxx?id=1&type=2 )
c.Get 请求方法可以传递的参数数据量是有限的(因为一般参数是拼接在url上,而浏览器对于url的长度是有限制的)
d.Get 请求因为是直接将数据拼接在url上,所以安全性不如post强(相对) , 但是get的执行效率要快于post
Post :
a.一般往服务器提交数据的请求会设置为post方式
b.Post 方式传递参数一般都会把参数放在请求体,而不会拼接在url
c.Post 请求方法可以提交的数据量不受限制
d.Post 请求传参相对于 get 要安全(相对不是绝对) , 但是 post 的执行效率不如get。
强制等待:
也叫线程等待, 通过线程休眠的方式完成的等待,如等待5秒: Thread sleep(5000),
隐式等待:
通过implicitly Wait完成的延时等待,注意这种是针对全局设置的等待,如设置超时时间为10秒,使用了implicitlyWait后,如果第一次没有找到元素,会在10秒之内不断循环去找元素,如果超过10秒还没有找到,则抛出异常
显式等待:
也称为智能等待,针对指定元素定位指定等待时间,在指定时间范围内进行元素查找,找到元素则直接返回,如果在超时还没有找到元素,则抛出异常
def f(x, l=[]): for i in range(x): l.append(i * i) print(l) f(2) f(3, [3, 2, 1]) f(3) 结果: [0] [0, 1] [3, 2, 1, 0] [3, 2, 1, 0, 1] [3, 2, 1, 0, 1, 4] [0, 1, 0] [0, 1, 0, 1] [0, 1, 0, 1, 4]
参考答案:会根据接口文档设计接口用例,然后利用 python 的 requests 库实现接口请求,利用excel来管理测试数据。并在代码当中利用 unittest 测试框架实现接口用例的断言处理。
使用 ActionChains 类
ac= ActionChains(driver);
ac.context _click(元素对象).perform()
测试用例保存到Excel中,使用第三方库openpyxI完成对Excel的操作
for i in range(1, 1000): if i % 7 == 0 and i % 5 ==3: print(i) 执行结果: 28 63 98 133 168 ........
根据题意是要买一百本书,一百块钱,看有多少种买法(钱不一定非要花完 ,只要能买到一百本书) :
三本书的价格分别为: 5,3,0.5,那么能买到最多的数学书为20本,英语书33本,语文书200本。但是也有组合的买法,所以可以通过一个三重for循环来实现, ijk分别代表购买数学,英语,语文书的数量,循环条件分别是i<=20,j<=33,k<=200,那么只要满足 i+j+k == 100,5*i+3*j+0.5*k<= 100即可。最后统计所有的组合就是买法的数量。
n = 0 for i in range(21): for j in range(34): for k in range(201): if 5 * i + 3 * j + k * 0.5 <= 100 and i + j + k == 100: n += 1 print(n)
monkey 对 APP进行测试的时候,会利用adb shell monkey-p包名-f脚本-V-V -v >D:log.txt 把日志输出到本地,并且将出现错误时候的日志截图,把日志截图以及bug描述提交到禅道,指派给对应的开发。但是在提交bug之前会手动去重现下这个bug。
A、自动化测试可以完全取代手工测试
B、自动化测试可以大幅度减少测试团队的工作量
C、性能测试不能自动化
D、自动化测试能够发现大量的新缺陷
参数使用 *args 或者 *kwargs
lambda函数:没有函数名称,是匿名函数。
好处:只做简单运算,接收任何多参数并返回值,没有复杂的函数体。可以作为回调函数,传递给某些应用,比如消息处理
如果子类没有定义构造函数,则子类默认会调用父类的构造函数;
如果子类定义了构造函数,那么在子类的构造函数中,调用父类的构造函数:python3中,使用 super()._ _init_ _()
L = ["a", "b", "c", "d", "e", "F", "g"] print(L[3]) print(L[::5]) print(L[::2]) 执行结果: d ['a', 'F'] ['a', 'c', 'e', 'g']
x = [1, 2] a1 = list(enumerate(x)) print(a1) # 执行结果:[(0, 1), (1, 2)]
print(sum(range(1, 10, 2))) # 各两位取一个之和:1,3,5,7,9 # 执行结果:25
小飞飞买好多瓶子,每对瓶子上会有一个相同的数字。小飞飞数了一遍自己的瓶子发现瓶子的个数是奇数N ,也就是有-个没有配对的瓶子。现在小飞飞要去再拿一个新瓶子,请问他给新瓶子要标几号才能让所有瓶子都有配对的。比如说他有七个瓶子( N=7 ),那么标号可以是:1,6,13,1,6,13,13
那么新瓶子就要标记为13,加入后就有(1,1),(6,6),(13,13),(13,13 )这4对
输入:测试数据的第一行一个正整数 N (1<=N<=1000 )表示有N个数, N保证是奇数,第二行N个自然数,每个数都小于10^9
输出:输出一行一个整数,新瓶子的号码
样例:
输入:
9
121233441
输出:1
def func(n, data): if 0 <= n <= 1000 and n % 2 == 1 and len(data) == n: for i in data: if 0 < i < (10 ** 9): if data.count(i) % 2 != 0: return i else: print("瓶子的号码值为自然数,并且小于10^9") else: print("传入的参数有误") res = func(7, [1, 6, 1, 6, 13, 13, 13]) print(res)
63、用 python 写一个函数,将一个字符串中给定的子串字符按从小到大的输出,第一个字符的位置为0
如: myOrder( abejykhsesm',2,5)
输出: ehjky
def my_order(s, start, len): # 先切片 s = s[start:start + len] # 强制转换为列表 li = list(s) # 排序 li.sort() # 在拼接为字符串 res = "".join(li) print("输出结果为:", res) my_order("abcedfgh", 2, 4) 结果为:cdef
64、对输入的整数数组,输出数组元素中的最大值、最大值的个数、最小值和最小值的个数
函数名称: max_ and_ min(list)
输入参数: list整数数组
输出: list整数数组,有四个值,分别表示最大值、最大值的个数、最小值和最小值的个数
示例: max and. min([1,4,21,5,6,1,1]) => [21,1,1,3]
max_ and. min(1]) => [1,1,1,1]
def max_and_min(a): b = sorted(a, reverse=True) max = b[0] max_num = b.count(max) min = b[-1] min_num = b.count(min) return [max, max_num, min, min_num] a = [5, 5, 5, 4, 3, 2, 2] print(max_and_min(a)) # 执行结果:[5, 3, 2, 2]
函数名称:rpad(src,len,str)
输入参数::src原字符串, len目标字符串长度, str用来填充的字符串
输出:补齐后的字符串
示例:
rpad ("abcd",10,"12") =>"abcd121212"
rpad ("abcd",11,"12") =>"abcd1212121"
rpad ("abcd",10,"12") =>"abcd121212”
rpad ("abd",12,"0") =>*"bd0000000”
rpad ("abcd",12,") =>"abcd
def rpad(src, length,string): while len(src) < length: for i in string: src += i if len(src) >= length: return "" + src else: return "" + src print(rpad("abcd", 10, "12")) # 10位 print(rpad("bbbb", 11, "12")) # 11位 print(rpad("cccc", 12, "12")) # 12位 print(rpad("dddd", 13, "0")) # 13位 print(rpad("ffff", 13, " ")) # 13位有空格 # 执行结果: abcd121212 bbbb1212121 cccc12121212 dddd000000000 ffff
参考:
web端的自动化测试,基本就是模拟手工测试人员来做功能测试。
用机器的自动执行代替人的操作。
web端呈现的产品有两个方向可以做自动化测试:接口层和界面操作层,且接口层自动化的比例要高于界面操作层。
并且主要对产品稳定的功能进行自动化测试,主要用于产品的核心功能冒烟测试、回归测试。
从系统最最核心的功能开始做,再根据情况慢慢铺开。
参考:
基于用户登陆的自动化测试思路:
使用 python+selenium 框架来编写登陆的所有测试用例,
使用 unittest 框架来组织测试用例。
使用 Htmltestrunner 来形成 html 版的测试报告,并使用邮件模块来发送测试报告给项目组相关人员。
如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,
咱们下期见!答案获取方式:已赞 已评 已关~
学习更多知识与技巧,关注与私信博主(03)