python+Selenium-Grid+mysql+fastDFS实现分布式测试

1. 测试系统简介

刚开始写自动化的时候网上也看过许多教程,但都显得不够灵活。后面经过多次改良写出个测试框架,可以将所有的断言、xpath、用户操作等信息全部写在excel里面,代码里面只是封装操作方式,这样就提高了易用性、可维护性,希望对有意转向自动化的人有一些帮助。此测试框架由seleniumGrid+python完成,使用fastdfs储存测试截图并将截图路径和测试用列保存到数据库,然后将测试结果以网页的形式发送邮箱。教程不适合初学者看,需要具备python、selenium的基础知识。

若是有不同的见解或者更好的方式请留言或者联系我QQ:98669918一起学习,一起进步。
欢迎转载,请著名出处

2. 资源准备

2.1 搭建windows虚拟机

安装虚拟机的教程网上很多,我就不重复了
windows系统下载地址:https://msdn.itellyou.cn/
找到操作系统,选择你自己需要的下载就行
windows虚拟机,需要安装java。

如果不想用虚拟机可以直接在本地测试,只是在测试期间电脑将不能使用,推荐使用分布式部署

2.2 下载并配置Python

2.21 windows配置python

官网下载python安装包:https://www.python.org/downloads/windows/ 安装即可

2.22 Linux配置python

Linux系统自带python,若无特殊需求不必重新安装

2.3 创建Mysql库、表

#创建数据库
create database  pytest;
#创建测试结果存储表
create table TEST(
	title varchar(255) NOT NULL COMMENT '用例标题',
	checkpoints varchar(255) NOT NULL COMMENT '检查点',
	expected_results varchar(255) NOT NULL COMMENT '预期结果',
	state varchar(20) NOT NULL COMMENT '用例执行状态pass/fali',
	--不要用date格式,可能存数据的时候会有问题
	time varchar(50) NOT NULL COMMENT '用例启动时间',
	image_path varchar(255) NOT NUll COMMENT '截图',
	version varchar(50) NOT NULL COMMENT '用例版本',
	project varchar(255) NOT NULL COMMENT '用例所属项目',
	id INT(20) NOT NULL AUTO_INCREMENT,
	PRIMARY KEY(id)
);

2.4 安装、配置FastDFS文件服务器

>>>>>>>>>>>>>>>>>FastDFS安装教程

2.5 下载、配置selenium

官网下载:http://selenium-release.storage.googleapis.com/index.html
网盘下载:https://pan.baidu.com/s/1CnXXiEwTBYyywojlALAq9w 提取码 ndsa
我用的:selenium-server-standalone-3.9.1.jar
版本

2.6 安装selenium

输入命令:pip3 install selenium 进行安装,pip3是python3的,python2使用pip
安装完成输入:pip3 show selenium查看版本信息
安装selenium

3. 配置及测试selenium-Grid

3.1 启动selenium服务

不论部署几台机器,主机和测试机必须可以ping通,不然会启动失败
在主机(编写测试代码的机器)输入

java -jar selenium-server-standalone-3.9.1.jar -role hub -port 4444
#4444是默认端口,也可以修改为其他端口

在测试机(虚拟机)输入

#10.0.203.39:4444 是你自己控制机(hub所在机器)的IP和端口
#port 5555 是测试机端口,选择一个未被使用的端口就可以
java -jar selenium-server-standalone-3.9.1.jar -role node -port 5555 -hub http://10.0.203.39:4444/grid/register

当主机控制台打印测试机IP时,就表示连接成功了
链接

3.2 浏览器驱动

在进行测试之前需要在node机器安装对应的浏览器驱动
网盘下载:https://pan.baidu.com/s/1hIvvAwkU-cNbP22Lm3WRLQ 提取码 gy9h
下载后解压文件,在系统盘根目录创建driver文件夹,将其加入系统环境变量。然后吧浏览器驱动复制进去
环境变量

3.3 编写测试代码

在编写正式的代码之前,先写一个demo试一下环境是否搭建好

# -*- coding: UTF-8 -*-

from selenium.webdriver import Remote

'''浏览器驱动封装'''
def browser(host,browserb):
    dc = {'browserName': browserb}
    driver = Remote(command_executor=host, desired_capabilities=dc)
    return driver
    
if __name__ == "__main__":
	'''输入node的ip和端口'''
	#chrome
    dr = browser('http://172.16.122.151:5555/wd/hub','chrome')
	#firefox
	#dr = browser('http://172.16.122.151:5555/wd/hub','firefox')
    dr.get('http://www.baidu.com')

执行代码后,node机打开浏览器并访问百度,就代表环境搭建完成,若是第一次启动报错,就先手动去node机启动浏览器驱动(双击运行即可)

4 公用方法

目录说明:

|__Login
|  |__LoginCase:登录测试用例
|  |__LoginExcel : 获取Login测试数据
|__action:操作方法封装
|__fdfs.conf:fastdfs文件服务器配置
|__fdfs:文件上传
|__main:入口
|__Screenshot:截图
|__sql:储存测试数据
|__email:发送邮件

4.1 线程类

重写Thread线程类,以测试机数量为线程数量,做到多台机器同步测试.
先传递node机器IP和浏览器类型到WebDriver,然后在执行测试类

main.py
# -*- coding: UTF-8 -*-

import threading
from selenium.webdriver import Remote
from email import Email
from Login import LoginCase

'''浏览器驱动封装'''
def driver(host,browserb):
    print(host,browserb)
    dc = {'browserName': browserb}
    driver = Remote(command_executor=host, desired_capabilities=dc)
    return driver

#线程锁,多线程读取系统资源时要枷锁,不然可能会出现数据混乱的情况
threadLock = threading.Lock()
#线程类
class myThread(threading.Thread):
    def __init__(self, name,host,browser):
        threading.Thread.__init__(self)
        self.name = name
        self.host = host
        self.browser = browser
    def run(self):
        threadLock.acquire()
        case(self.host, self.browser)
        threadLock.release()
    def __del__(self):
        print(self.name, " : END Thread!")


#node机器IP与浏览器
hosts = {
    'chrome':'http://172.16.122.160:5555/wd/hub'
    #'firefox':'http://172.16.122.154:5555/wd/hub'
}

#创建线程
threads = []
def Thread():
    i =0
    for browsers ,host in hosts.items():
    	#线程名称
        thread = 'thread%s' % (i)
        #传递node ip、浏览器类型到线程类
        thread = myThread(thread,host,browsers)
        threads.append(thread)
        i = i + 1
    #加入线程池
    for t in threads:
            t.start()
    #等待所有线程结束
    for t in threads:
            t.join()

#执行测试
def case(host,browser):
    #执行Login测试类
    LoginCase.main(host,browser)

if __name__ == "__main__":
    Thread()
    Email()

4.2 封装操作方法

操作方法封装,后面的测试类直接传递参数调用即可,减少代码冗余

action.py
# -*- coding: UTF-8 -*-

from selenium.webdriver.common.by import By
#xpath是页面元素定位
#input 是用户输入的参数
# 打开URL
def open_url(dr, url):
    dr.get(url)


# 输入内容
def type_input(dr, xpath, input):
    dr.find_element(By.XPATH, xpath).send_keys(input)


# 点击
def type_submit(dr, xpath):
    dr.find_element(By.XPATH, xpath).click()


# 获取文本
def get_text(dr, xpath):
    text = dr.find_element(By.XPATH, xpath).text
    return text

#获取弹出框 alert值
def get_alert(dr):
    alert = dr.switch_to_alert()
    text = alert.text
    alert.accept()
    return text

# 退出
def quit(dr):
    dr.quit()

4.3 上传截图文件

上传截图文件到fast文件服务器并返回文件ID

# -*- coding: UTF-8 -*-
import fdfs_client
from fdfs_client.client import *

#上传截图到fastdfs
def fastdfs(file):
    #配置文件路径
    client_conf = get_tracker_conf('/root/PycharmProjects/SeleniumGrid/fdfs.conf')
    client = Fdfs_client(client_conf)
    #以图像名称上传
    #imgs = client.upload_appender_by_filename(file)
    #以文件流上传
    imgs = client.upload_appender_by_buffer(bytes(file, encoding="utf8"),'jpg')
    #接受文件ID
    path = str(imgs['Remote file_id'],encoding="utf8")
    #接受fdfs文件服务器地址
    ip = str(imgs['Storage IP'],encoding="utf8")
    #拼接文件地址
    img = str('%s/%s' % (ip,path))
    return img

4.4 截图

使用selenium截图功能,将图片以流的形式上传,并将测试结果、测试截图存到数据库

# -*- coding: UTF-8 -*-
from fdfs import fastdfs, datetime
from sql import sqlDriver


def io(dr,title,jcd,qwjg,ass):
    nowTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    version = '1.0'
    project = 'TEST'
    #截图
    #files = dr.get_screenshot_as_base64()
    files = dr.get_screenshot_as_png()
    #上传截图,并保存截图位置
    img = fastdfs(files)
    #存储测试结果
    sql = "INSERT INTO TEST(title,checkpoints,expected_results,state,time,image_path,version,project) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s')" % (title,jcd,qwjg,ass,nowTime,img,version,project)
    sqlDriver(sql)

4.5 数据库方法封装

链接数据库,执行sql语句,返回结果

# -*- coding: UTF-8 -*-

import pymysql

# 打开数据库连接
def sqlDriver(sql):
	#数据库IP和密码换成你自己的
    db = pymysql.connect("127.0.0.1","root","root","pytest" )
    cu = db.cursor()
    cu.execute(sql)
    data = cu.fetchall()
    db.commit()
    return data

4.5 fastdfa配置文件

connect_timeout = 2
network_timeout = 30
charset = UTF-8
#服务器端口
http.tracker_http_port = 80
http.anti_steal_token = no
#密钥
http.secret_key = FastDFS1234567890
#服务器IP,端口默认22122
tracker_server =127.0.0.1:22122

4.6 发送测试结果

email.py
# -*- coding: UTF-8 -*-

import smtplib
from email.mime.text import MIMEText
from email.header import Header

#第三方邮件服务
mail_host = "smtp.yeah.net"
mail_user = "123456@yeah.net"
#这个地方不是邮箱登录密码,是授权码,不同的厂商有不同的设置方式
mail_pass = "123456"
# 发送邮件地址
sender = '1234@yeah.net'
# 接收邮件地址
receivers = ['1234@yeah.net']
#主题,我这里发的主题是一个链接,点击之后进入网页展示页面

mail_msg = """
<p><a href="http://127.0.0.1/Test">测试报告</a></p>
"""


message = MIMEText(mail_msg, 'html', 'utf-8')
message['From'] = Header('测试','utf-8')
message['To'] = Header('测试','utf-8')
subject = '测试报告'
message['Subject'] = Header(subject, 'utf-8')

def Email():
    try:
        smtpObj = smtplib.SMTP()
        smtpObj.connect(mail_host, 25)
        smtpObj.login(mail_user, mail_pass)
        smtpObj.sendmail(sender, receivers, message.as_string())
        print("邮件发送成功")
    except smtplib.SMTPException:
        print("Error: 无法发送邮件")

5. 测试类

5.1 Login数据获取

获取excel测试数据,存到list
List名称随意,要和excel对应起来
excel内容

LoginExcel.py
# -*- coding: UTF-8 -*-

import xlrd
#标题
title  = {}
#检查点
jcd = {}
#期望结果
qwjg = {}
#用户名
user = {}
#密码
passwd = {}
#断言内容
ass = {}
#用户名xpath
userxpath = {}
#密码xpath
passxpath = {}
#断言xpath
assxpath={}
#登录按钮xpath
sub = {}
#断言类型,text,alert
ass_type={}


def excel(s):
    #excel路径
    file_path = '/root/test.xlsx'
    #打开excel
    ex = xlrd.open_workbook(file_path)
    #选取Sheet,0表示第一个
    sheet = ex.sheets()[s]
    #获取总行数
    nors = sheet.nrows
    #总列数
    cols = sheet.ncols
    #读取excel每行内容
    for j in range(nors):
        #跳过第一行,一般第一行都是标题,
        if j == 0:
            continue
		#存到List
        title[j-1] = sheet.cell_value(j, 0)
        jcd[j-1] =  sheet.cell_value(j, 1)
        qwjg[j-1] =  sheet.cell_value(j, 2)
        user[j-1] = sheet.cell_value(j, 3)
        passwd[j-1] =  sheet.cell_value(j, 4)
        ass[j-1] =  sheet.cell_value(j, 5)
        userxpath[j-1] =  sheet.cell_value(j, 6)
        passxpath[j-1] =  sheet.cell_value(j, 7)
        assxpath[j-1] =  sheet.cell_value(j, 8)
        sub[j-1] =  sheet.cell_value(j, 9)
        ass_type[j - 1] = sheet.cell_value(j, 10)
    return nors


#获取数据
def get_title(i):
    return title[i]

def get_jcd(i):
    return jcd[i]

def get_qwjg(i):
    return qwjg[i]

def get_user(i):
    return user[i]

def get_passwd(i):
    return passwd[i]

def get_ass(i):
    return ass[i]

def get_userxpath(i):
    return userxpath[i]

def get_passxpath(i):
    return passxpath[i]

def get_assxpath(i):
    return assxpath[i]

def get_sub(i):
    return sub[i]

def get_asstype(i):
    return ass_type[i]

5.2 测试用列封装

根据登录页面内容,测试类思路如下:

1. 根据excel提供的xpath获取用户名文本框,并输入excel提供的用户名
2. 根据excel提供的xpath获取密码文本框,并输入excel提供的密码
3. 根据excel提供的xpath获取登录按钮并点击
4. 根据excel提供的断言类型判断应该用那种方式获取断言文本
5. 根据excel提供的xpath获取断言内容
6. 比较页面获取的断言内容是否与excel存放的断言内容一致
7. 页面截图并将测试信息存到数据库
LoginCase.py
# -*- coding: UTF-8 -*-
from time import sleep
from Login.LoginExcel import *
from Screenshot import io
from action import *
from main import driver


def main(host, browser):
    global text
    #登录页面地址
    url = "http://www.sightfuture.cn:81/zentao/user-login.html"
    #获取excel总行数
    nor = excel(0)
    #遍历excel并执行测试,一般excel第一行是标题,不是测试数据。所以nor-1
    for i in range(nor-1):
        # WebDriver
        dr = driver(host, browser)
        # 打开网页
        open_url(dr, url)
        #输入用户名
        type_input(dr,get_userxpath(i),get_user(i))
        #输入密码
        type_input(dr, get_passxpath(i),get_passwd(i))
        #点击登录
        type_submit(dr, get_sub(i))
        #获取断言类型
        type = get_asstype(i)
        #根据断言类型判断怎样获取断言文本
        if(type == 'text'):
            # 获取断言文本
            text = get_text(dr, get_assxpath(i))
        elif(type =='alert'):
            #获取alert弹出文本
            text = get_alert(dr)

        #比较获取的断言文本是否为excel储存的文本
        if(text == get_ass(i)):
            status = 'pass'
        else:
            status = 'fail'
 		print("断言内容:%s ,断言结果 :%s" % (text,status))
        #截图并将测试信息存到数据库
        #截图延迟
        sleep(1)
        io(dr,get_title(i),get_jcd(i),get_qwjg(i),status)
        # 退出浏览器
        dr.quit()

到此测试代码部分编写完成,虽然只有Login,但其他页面也可以按照这种模式进行设计,一次设计永久使用,以后只需要不断维护excel即可,减小测试开发时间。
接下来运行一次看下效果:
结果
可以看到两次都是测试通过,说明登录功能正常
到此处测试部分代码已经编写完成,剩下的前端展示页面自行解决,只需要展示数据内容和图片即可

5.3 代码下载

完整代码下载路径:
https://pan.baidu.com/s/1aTED0OFo9qmZop5OEsRZ4g 提取码 c6fa

更多教程查看主页>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值