自动化测试平台
测试平台搭建1.框架概述框架模型前端(vue)+后端(django)+数据库(mysql、redis)+nginx(代理服务器)+uwsgi(web服务器)2. 技术概述前端(vue)1.视图,数据,结构分离2.数据双向绑定3.Vue的响应式原理4.vue中created与mounted区别5.watch来监听数据的变化1.监听的数据后面可以写成对象形式,包含handler方法,immediate
·
自动化测试平台
1.效果展示
用例管理(思维导图)
用例管理(表格)
自动化(列表)
接口自动化
接口编辑
ui自动化
测试报告(仿allure样式自开发)
2.框架概述
框架模型前端(vue)+后端(django)+数据库(mysql、redis)+nginx(代理服务器)+uwsgi(web服务器)
3. 功能概述
一.自动化类
Ⅰ.界面自动化(ui)
模块:selenium、Selenium Grid、Remote、redis、mysql、log、apscheduler、django_apscheduler、
getattr 反射实现
python内置模块
time模块
time.time() # 时间戳
time.gmtime() # 转换时区
datatime模块
datetime.datetime.now() # 获取当前时间
random模块
random.randint(1, 3)
random.randrange(1, 3)
random.choice([1, '23', [4, 5]])
sys模块
os模块
json模块
pickle模块
shelve模块
xml模块
re模块
logging模块
uuid模块
base64模块
configparser解析配置文件模块
hashlib、md5模块
hashlib.md5(‘md5_str‘).hexdigest() 对指定字符串md5加密
md5.md5(‘md5_str‘).hexdigest() 对指定字符串md5加密
math模块
selenium
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.support.select import Select
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 启动浏览器
# 普通模式
driver = webdriver.Chrome(driver)
driver.implicitly_wait(10)
driver.maximize_window()
# 远程模式
chrome_options = webdriver.ChromeOptions()
BaseUi.driver = webdriver.Remote(command_executor=command_executor, options=chrome_options)
BaseUi.driver.maximize_window()
BaseUi.driver.implicitly_wait(10)
# 无界面模式
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument("window-size=1920,1080")
chrome_options.add_argument("--no-sandbox")
BaseUi.driver = webdriver.Chrome(chrome_options=chrome_options, executable_path=self.driver_path_local)
BaseUi.driver.implicitly_wait(10)
BaseUi.driver.maximize_window()
WebDriverWait(self.driver, secs).until(EC.invisibility_of_element_located(element)) # 显示等待
# 常用方法
# 定位元素方法
id、name、class_name、css_selector、tag_name、link_text、partial_link_text、xpath
# css和xpath的区别
1.语法格式不一样:
xpath直接元素用/, 内部元素用//
css直接元素用>, 内部元素用空格
2.定位常规属性的区别:
xpath用@属性名
css中id用'#', class用'.',name用'[name]'
xpath多个属性用'and', css用'[属性]'
xpath有文本属性, css没有文本属性
xpath索引用'[num]', css用'(num)'
xpath不能直接操作select, css可以
xpath找父元素用'/..',
xpath可以通过元素文本模糊匹配'contains(text(), '模糊匹配')'
# 浏览器操作
maximize_window()
set_window_size(wide, high)
close()
quit()
forward()
back()
refresh()
# 属性
title
current_url
text
# 操作元素
get()
send_keys()
click()
context_click()
double_click()
move_to_element() # 鼠标移动到元素上方,并保持悬浮
drag_and_drop() # 拖拽一个元素到另一个元素
ActionChains(driver)
submit() # 提交表单
execute_script() # 执行js代码
get_attribute() # 获取元素属性的值
page_source() # 获取页面源代
is_displayed() # 判断元素是否可见
switch_to.frame # 切入iframe框架里边
switch_to.parent_frame() # 退出当前iframe
switch_to.default_content() # 切出iframe,回到主界面
switch_to.window(handle) # 切换到名字为title的窗口
get_screenshot_as_file(file_path) # 截图(类型为文件)
定时任务
from apscheduler.triggers.cron import CronTrigger
from utils.common.cron_trigger import MyCronTrigger
from django_apscheduler.jobstores import DjangoJobStore
from apscheduler.schedulers.background import BackgroundScheduler
# 实例化定时任务对象
scheduler = BackgroundScheduler() # [ˈʃedjuːl]
scheduler.add_jobstore(DjangoJobStore(), "default")
scheduler.start()
# 任务的方法
新增任务:add_job(fun_name, trigger=MyCronTrigger.my_from_crontab(cron), id=name, kwargs={"task_data": task_data}, timezone=pytz.utc, max_instances=4)
删除任务:remove_job(job_name)
暂停任务:pause_job(job_name) # [pɔːz]
恢复任务:resume_job(job_name) # [rɪˈzjuːm]
修改任务:reschedule_job(job_id, trigger=CronTrigger(second=str(trigger)))
获取单个任务:get_job(job_id)
获取所有任务:get_jobs()
redis
import redis
# rs = redis.Redis(host='127.0.0.1', port=6379, decode_responses=True)
pool = redis.ConnectionPool(host='127.0.0.1', port=6379, decode_responses=True)
rs = redis.Redis(connection_pool=pool)
1.字符串的操作
rs.set(name, value, ex=None, px=None, nx=False, xx=False) # 批量设置值
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行,同setnx(name, value)
xx,如果设置为True,则只有name存在时,当前set操作才执行
rs.mset(name1='zhangsan', name2='lisi') # 批量获取
rs.getset(name, value) # getset 设置新值,打印原值
rs.type(name) # 查看类型
rs.keys() # 获取所有的key值
rs.delete(name) # 删除指定的key-value值
rs.flushall() # 清除redis里面的所有key-value
2.列表操作
rs.rpush('list',1,2,3) # 尾部添加
rs.lpush('list',0) # 头部添加
rs.llen('list') # 返回列表的长度
rs.lrange('list',0,-1) # 获取list全部内容
rs.lindex('list',1) # 获取索引元素
3.Set 操作
rs.sadd(name,values) # 给name对应的集合中添加元素
rs.smembers('set_name') # 获取name对应的集合的所有成员
rs.scard("set_name") # 获取name对应的集合中的元素个数
4.哈希表操作
rs.hset('price','cake',5) # 添加映射
rs.hget('price','cake') # 根据键获取数据
rs.hmset('price',{'banana':2,'apple':3,'pear':6,'orange':7}) # 批量添加映射
rs.hmget('price',['apple','orange']) # 批量获取
rs.hexists('price','banana') # 在price中banana是否存在 返回True
rs.hdel('price','banana') # 从price中删除banana 返回1
rs.hlen('price') # 输出price的长度
rs.hkeys('price') # 输出所有的映射键名
rs.hvals('price') # 输出所有的映射键值
rs.hgetall('price') # 输出所有的映射键对
随机函数
import random
import string
import pinyin
random.random() # 用于生成一个[0,1)范围的浮点数
random.uniform(10, 20) # 生成一个指定范围内的随机符点数
random.randint(12, 20) # 生成一个指定范围内的整数
random.choice(string) # 随机选取一个字符
yaml配置文件
import yaml
with open(yaml_path, 'r', encoding='utf-8') as f:
content = yaml.load(f.read(), Loader=yaml.FullLoader)
return content
日志
import logging
logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)
root_path = os.path.realpath("./report/log/")
# 定义日志级别(一般日志)
handler = TimedRotatingFileHandler(root_path + 'info.log'.format(now_ymd()), when='d', interval=1, backupCount=30, encoding='utf-8')
handler.setLevel(logging.INFO) # 日志级别INFO、ERROR、DEBUG
formatter = logging.Formatter('%(levelname)s - %(asctime)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
发送邮件
import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
message = MIMEText('接口自动化发送邮件测试...', 'plain', 'utf-8') # 文本邮件
message = MIMEText(mail_msg, 'html', 'utf-8') # 网页邮件
# 发送附件
att = MIMEText(open('../../Report/Log/error.log', 'rb').read(), 'base64', 'utf-8')
att["Content-Type"] = 'application/octet-stream'
att["Content-Disposition"] = 'attachment; filename="error.log"'
smtp = smtplib.SMTP()
smtp.connect(mail_host, 25) # 设置服务器, 25为SMTP端口号
smtp.login(mail_user, mail_pass) # 登录验证(pass口令)
smtp.sendmail(sender, receivers, message.as_string()) # 发件人,收件人,消息内容
图片接口
def img(request, folder_name, name):
return HttpResponse(open(str("./report/image/" + folder_name + '/' + name) + ".png", "rb"), content_type="image/png")
上传文件
driver_file = request.FILES.get('files')
driver_form = request.POST.get('driverForm').split(',')
file_exists = os.path.exists(driver_file_path)
os.mkdir(driver_file_path)
destination = open(driver_file_path + '/' + driver_file.name, 'wb+') # 打开特定的文件进行二进制的写操作
for chunk in driver_file.chunks(): # 分块写入文件
destination.write(chunk)
Ⅱ.接口自动化(api)
Ⅲ.定时任务()
二.工具类
Ⅰ.版本验证
模块:requests、bs4、re
soup = BeautifulSoup(page_html_text, 'html.parser')
soup.find_all('tbody')[0])
Ⅱ.幂等验证
模块:grequests
request_list = [
grequests.post(url, json=data, cookies=cookies),
grequests.post(url, json=data, cookies=cookies),
grequests.post(url, json=data, cookies=cookies),
grequests.post(url, json=data, cookies=cookies),
grequests.post(url, json=data, cookies=cookies),
]
grequests.map(request_list)
Ⅲ.服务数据
模块:requests
# 求取并集
list(set(sprint_list).union(set(swagger_list)).union(set(sky_walking_list)))
Ⅳ.思维导图
模块:MindElixir
Ⅴ.在线文档
模块:Luckysheet
4. 技术概述
前端(vue)
1.视图,数据,结构分离
2.数据双向绑定
3.Vue的响应式原理
4.vue中created与mounted区别
5.watch来监听数据的变化
1.监听的数据后面可以写成对象形式,包含handler方法,immediate和deep。
2.immediate表示在watch中首次绑定的时候,是否执行handler,值为true则表示在watch中声明的时候,就立即执行handler方法,值为false,则和一般使用watch一样,在数据发生变化的时候才执行handler。
3.当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
watch: {
name: {
handler(newName, oldName) {
},
deep: true,
immediate: true
}
}
6.插槽slot
7.vue中常用的一些指令
8.v-show和v-if
1.v-model指令:用于表单输入,实现表单控件和数据的双向绑定。
2.v-on:简写为@,基础事件绑定
3.v-bind:简写为:,动态绑定一些元素的属性,类型可以是:字符串、对象或数组。
4.v-if指令:取值为true/false,控制元素是否需要被渲染
5.v-else指令:和v-if指令搭配使用,没有对应的值。当v-if的值false,v-else才会被渲染出来。
6.v-show指令:指令的取值为true/false,分别对应着显示/隐藏。
7.v-for指令:遍历data中存放的数组数据,实现列表的渲染。
8.v-once: 通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新
9.vue的生命周期
生命周期通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
beforecreate (初始化界面前)
created (初始化界面后)
beforemount (渲染界面前)
mounted (渲染界面后)
beforeUpdate (更新数据前)
updated (更新数据后)
beforedestory (卸载组件前)
destroyed (卸载组件后)
10.axios 是什么
1.Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。前端最流行的 ajax 请求库,
2.react/vue 官方都推荐使用 axios 发 ajax 请求
特点:
1.基于 promise 的异步 ajax 请求库,支持promise所有的API
2.浏览器端/node 端都可以使用,浏览器中创建XMLHttpRequests
3.支持请求/响应拦截器
4.支持请求取消
5.可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据
6.批量发送多个请求
7.安全性更高,客户端支持防御 XSRF,就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略,假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。
后端(django)
数据库(mysql、redis)
nginx(代理服务器)
uwsgi(web服务器)
docker容器(集装箱)
1.基础命令
systemctl stop docker # 启动
systemctl restart docker # 关闭
systemctl enable docker # 重启
systemctl status docker # 设置随服务启动而自启动
netstat -untlp # 监控TCP/IP网络
2.镜像命令
docker images
docker pull 镜像名:tag
docker run 镜像名:Tag
docker rmi -f 镜像名/镜像ID # 删除镜像,当前镜像没有被任何容器使用才可以删除
docker image rm 镜像名称/镜像ID # 强制删除镜像
docker save 镜像名/镜像ID -o 镜像保存在哪个位置与名字 # 保存镜像
3.容器命令
docker ps # 查看正在运行容器列表
docker ps -a # 查看所有容器
# -it 表示 与容器进行交互式启动 -d 表示可后台运行容器 (守护式运行)
# --name 给要运行的容器 起的名字 /bin/bash 交互路径
docker run -it -d --name 要取的别名 镜像名:Tag /bin/bash
docker run -it -d --name redis001 redis:5.0.5 /bin/bash # 启动容器
docker run -itd --name redis002 -p 8888:6379 redis:5.0.5 /bin/bash # 容器端口映射
docker exec -it 容器名/容器ID /bin/bash # 进入容器
docker attach 容器名/容器ID # 进入容器
Ctrl + p + q # 退出
docker stop 容器ID/容器名 # 停止容器
docker restart 容器ID/容器名 # 重启容器
docker start 容器ID/容器名 # 启动容器
docker kill 容器ID/容器名 # kill 容器
5.线上部署
uwsgi配置
[uwsgi]
#配置和nginx接的socket接
socket=127.0.0.1:8000
master = true
processes = 1
threads = 2
chdir = /www/wwwroot/test_platform
wsgi-file= /www/wwwroot/test_platform/test_platform
# http = 0.0.0.0:8000
logto = /www/wwwroot/test_platform/logs/error.log
chmod-socket = 660
vacuum = true
master = true
max-requests = 1000
nginx配置
server
{
listen 80;
server_name 10.1.201.1;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/test_platform/templates/dist/;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8000; #端口要和uwsgi里配置的一样
uwsgi_param UWSGI_SCRIPT test_platform.wsgi; #wsgi.py所在的目录名+.wsgi
uwsgi_param UWSGI_CHDIR /www/wwwroot/test_platform/; #项目路径
proxy_connect_timeout 600;
}
location /static/ {
root /www/wwwroot/test_platform/templates/dist/; #静态资源路径
}
location /favicon.ico {
root /www/wwwroot/test_platform/templates/dist/; #静态资源路径
}
}
更多推荐
已为社区贡献1条内容
所有评论(0)