selenium+python学习总结
学习了一个月的selenium+python,终于学有所成,下面以一个简单的项目来总结学习所得。
1. 项目结构

在项目结构中,大家要注意到:每一个源文件夹中都要有一个__init__.py文件,确记,这是规定,不解析。
先简单解说一下项目结构:
1) config源文件夹,这个主要存放一些配置文件,如里面的golobalparameter.py就是存放一些公共参数的,我这个文件里面主要把一些文件存放的路径写成了公共参数,这样子,要修改路径的时候直接打开这个文件就可以修改,而不用一个个文件地找参数。
2) data文件夹,是个普通的文件夹,里面存放了测试数据excel文件;
3) error_img文件夹,一样是普通的文件夹,测试过程中如果发生异常,通过代码可以自动截图然后把图片存放到error_img文件夹中。
4) log文件夹,也是普通文件夹,用于存放测试过程中输出的日志文件,这个日志文件是一次生成然后不断写入的,一旦生成了log.log文件,那么不管你执行多少次测试,输出了多少日志,都会写入一个log.log文件中。当然,如果把log.log删除之后,执行测试的时候也会再次生成的。
5) report文件夹,也是普通的文件夹,用于存放最后生成的.html测试报告;
6) src源文件夹,这个源文件夹下包含了两子源文件夹,一个是common源文件夹,用于存放一些公共类;另一个是test_case源文件夹,用于存放各测试模块的代码。
7) runtest.py文件,用于执行测试。
8) runner.bat文件,是用于设置windows定时执行测试任务所要用到的的cmd命令,因为我后来用了jenkins来做定时任务,所以可以不管。
2. 项目所有代码文件
1) globalparameter.py
# coding:utf-8
__author__ = 'helen'
import time
'''
配置全局参数
'''
# 项目的绝对路径(因为 windows执行时需要绝对路径才能执行通过)
project_path = "D:\\for2017\\SPframework-Helen\\"
# 测试用例代码存放路径(用于构建suite,注意该文件夹下的文件都应该以test开头命名)
test_case_path = project_path+"src\\test_case"
# 日志文件存储路径
log_path = project_path+"log\\mylog.log"
# 测试报告存储路径,并以当前时间作为报告名称前缀
report_path = project_path+"report\\"
report_name = report_path+time.strftime('%Y%m%d%H%S', time.localtime())
# 异常截图存储路径,并以当前时间作为图片名称前缀
img_path = project_path+"error_img\\"+time.strftime('%Y%m%d%H%S', time.localtime())
# 设置发送测试报告的公共邮箱、用户名和密码
smtp_sever = 'smtp.xxxx.com' # 邮箱SMTP服务,各大运营商的smtp服务可以在网上找,然后可以在foxmail这些工具中验正
email_name = "li***@gpdi.com" # 发件人名称
email_password = "*****" # 发件人登录密码
email_To = '50****@qq.com;5*****016@qq.com;h****@163.com' # 收件人
2) excel_data.py
# coding:utf-8
__author__ = 'helen'
import xlrd
from src.common import log
'''
读取excel文件
''' class excel:
def __init__(self):
self.mylog = log.log() def open_excel(self,file):
try:
data = xlrd.open_workbook(file)
return data
except Exception, e:
self.mylog.error(u"打开excel文件失败") def excel_table(self,file, sheetName):
data = self.open_excel(file)
# 通过工作表名称,获取到一个工作表
table = data.sheet_by_name(sheetName)
# 获取行数
Trows = table.nrows
# 获取 第一行数据
Tcolnames = table.row_values(0)
lister = []
for rownumber in range(1,Trows):
row = table.row_values(rownumber)
if row:
app = {}
for i in range(len(Tcolnames)):
app[Tcolnames[i]] = row[i]
lister.append(app)
return lister
3) log.py
# coding:utf-8
__author__ = 'helen'
import logging
from config import globalparameter
'''
配置日志文件,输出INFO级别以上的日志
''' class log:
def __init__(self):
self.logname = "mylog" def setMSG(self, level, msg):
# 之前把下面定义log的一大段代码写在了__init__里面,造成了日志重复输出
# 此大坑,谨记谨记!!!!
logger = logging.getLogger()
# 定义Handler输出到文件和控制台
fh = logging.FileHandler(globalparameter.log_path)
ch = logging.StreamHandler()
# 定义日志输出格式
formater = logging.Formatter("%(asctime)s %(levelname)s %(message)s' ")
fh.setFormatter(formater)
ch.setFormatter(formater)
# 添加Handler
logger.addHandler(fh)
logger.addHandler(ch)
# 添加日志信息,输出INFO级别的信息
logger.setLevel(logging.INFO)
if level=='debug':
logger.debug(msg)
elif level=='info':
logger.info(msg)
elif level=='warning':
logger.warning(msg)
elif level=='error':
logger.error(msg)
# 移除句柄,否则日志会重复输出
logger.removeHandler(fh)
logger.removeHandler(ch)
fh.close() def debug(self, msg):
self.setMSG('debug', msg) def info(self, msg):
self.setMSG('info', msg) def warning(self, msg):
self.setMSG('warning', msg) def error(self, msg):
self.setMSG('error', msg)
4) send_email.py
# coding:utf-8
__author__ = 'helen'
import os,smtplib
from config import globalparameter
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from src.common import log
'''
邮件发送最新的测试报告
''' class send_email:
def __init__(self):
self.mylog = log.log() # 定义邮件内容
def email_init(self,report,reportName):
with open(report,'rb')as f:
mail_body = f.read() # 创建一个带附件的邮件实例
msg = MIMEMultipart()
# 以测试报告作为邮件正文
report_file = MIMEText(mail_body,'html','utf-8')
# 定义附件名称(附件的名称可以随便定义,你写的是什么邮件里面显示的就是什么)
report_file["Content-Disposition"] = 'attachment;filename='+reportName
msg.attach(report_file) # 添加附件
msg['Subject'] = '自动化测试报告' # 邮件标题
msg['From'] = globalparameter.email_name #发件人
msg['To'] = globalparameter.email_To #收件人列表
try:
server = smtplib.SMTP(globalparameter.smtp_sever)
server.login(globalparameter.email_name,globalparameter.email_password)
server.sendmail(msg['From'],msg['To'].split(';'),msg.as_string())
server.quit()
except smtplib.SMTPException:
self.mylog.error(u'邮件发送测试报告失败 at'+__file__) def sendReport(self):
# 找到最新的测试报告
lists = os.listdir(globalparameter.report_path)
report_list = sorted(lists)
new_report = os.path.join(globalparameter.report_path,report_list[-1])
# 发送邮件
self.email_init(new_report,report_list[-1])
5) runtest.py
# coding:utf-8
__author__ = 'helen'
import unittest,time,HTMLTestRunner
from config import globalparameter
from src.common import send_email
'''
构建测试套件,并执行测试
''' # 构建测试集,包含src/test_case目录下的所有以test开头的.py文件
suite = unittest.defaultTestLoader.discover(start_dir=globalparameter.test_case_path,pattern='test*.py') # 执行测试
if __name__=="__main__":
report_name = globalparameter.report_name+"Report.html"
fb = open(report_name,'wb')
runner = HTMLTestRunner.HTMLTestRunner(
stream=fb,
title=u'自动化测试报告',
description=u'项目描述。………'
)
runner.run(suite)
fb.close()
# 发送邮件
time.sleep(10) # 设置睡眠时间,等待测试报告生成完毕(这里被坑了==)
email = send_email.send_email()
email.sendReport()
6) test_baidu.py
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.common.exceptions import NoAlertPresentException
from selenium.webdriver.common.action_chains import ActionChains
import unittest
from config import globalparameter
from src.common import excel_data, log
'''
百度页面相关测试用例
''' class TestBaidu(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.baidu.com/"
self.verificationErrors = []
self.accept_next_alert = True
self.mylog = log.log()
self.excel = excel_data.excel()
def test_baidu_search(self):
u'''百度搜索功能测试'''
driver = self.driver
listdata = self.excel.excel_table("D:\\for2017\\SPframework-Helen\\data\\baidu.xlsx","search")
print(len(listdata))
if (len(listdata)<=0):
self.mylog.error(u"读取excel参数异常,参数列表小于等于0")
assert 0,u"读取excel参数异常,参数列表小于等于0"
for i in range(0,len(listdata)):
try:
driver.get(self.base_url + "/")
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys(listdata[i]["keyword"])
driver.find_element_by_id("su").click()
URL_title = driver.title
self.assertEqual(URL_title, listdata[i]['keyword']+u"_百度搜索", u"搜索失败")
self.mylog.info(u'百度搜索成功 '+__file__)
except:
driver.get_screenshot_as_file(globalparameter.img_path+"test_baidu.png")
self.mylog.error(u"百度搜索失败"+__file__) def test_baidu_changeTo_hao123(self):
u'''测试从百度首页跳转到hao123网站'''
driver = self.driver
try:
driver.get(self.base_url+"/")
driver.find_element_by_link_text("hao123").click()
self.assertEqual(driver.current_url,"https://www.hao123.com/")
self.mylog.info(u'从百度成功跳转到hao123网站')
except:
driver.get_screenshot_as_file(globalparameter.img_path+"test_baidu_changeTo_hao123.png")
self.mylog.error(u'从百度跳转到hao123网站失败') def test_baidu_more(self):
u'''打开百度产品大全页面'''
driver = self.driver
try:
driver.get(self.base_url+"/")
mouse = driver.find_element_by_link_text(u"更多产品")
ActionChains(driver).move_to_element(mouse).perform()
driver.find_element_by_link_text(u"全部产品>>").click()
self.assertEqual(driver.current_url,"https://www.baidu.com/more/")
self.mylog.info(u'打开百度产品页面成功')
except:
driver.get_screenshot_as_file(globalparameter.img_path+"test_baidu_more.png")
self.mylog.error(u'打开百度产品页面失败') def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
def tearDown(self):
self.driver.close()
self.assertEqual([], self.verificationErrors) if __name__ == "__main__":
unittest.main()
7) test_sogo.py
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.common.exceptions import NoAlertPresentException
import unittest,time
from src.common import log
from config import globalparameter
'''
搜狗页面相关测试
''' class TestSogo(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.sogou.com/"
self.verificationErrors = []
self.accept_next_alert = True
self.mylog = log.log()
def test_sogo(self):
u'''搜狗搜索功能测试'''
try:
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("query").clear()
driver.find_element_by_id("query").send_keys("selenium")
driver.find_element_by_id("query").submit()
time.sleep(5)
self.assertEqual(driver.title, u"selenium - 搜狗搜索", u"sogo搜索模块出错")
self.mylog.info(u"sogo搜索模块成功 "+__file__)
except:
driver.get_screenshot_as_file(globalparameter.img_path+"test_sogo.png")
self.mylog.error(u"sogo搜索模块失败 "+__file__) def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
def tearDown(self):
self.driver.close()
self.assertEqual([], self.verificationErrors) if __name__ == "__main__":
unittest.main()
3. 使用jenkins设置定时执行测试任务
这个傻瓜式配置即可,不写了。
selenium+python学习总结的更多相关文章
- 【坚持】Selenium+Python学习之从读懂代码开始 DAY1
学习Selenium+Python已经好几个月了,但越学发现不懂的东西越多. 感觉最大的问题还是在于基础不扎实,决定从头开始,每天坚持读代码,写代码. 相信量变一定能到质变!!! 2018/05/09 ...
- Selenium+Python学习之一
刚入门selenium+Python,实验成功之后,记录一下过程. 首先是在知乎上面看到一个关于selenium+python的示例,于是自己便尝试搭建环境上手实验. 按照作者的代码敲一遍之后执行,竟 ...
- 【坚持】Selenium+Python学习之从读懂代码开始 DAY7
2018/05/25 EC [EC](https://github.com/easonhan007/webdriver_guide/blob/master/34/expected_conditions ...
- 【坚持】Selenium+Python学习记录 DAY11
2018/06/1-2018/06/4 参考资料: [菜鸟教程](http://www.runoob.com/python3/python3-examples.html) [Python解惑:True ...
- 【坚持】Selenium+Python学习记录 DAY10
2018/05/31-2018/06/1 [官方文档](https://www.jetbrains.com/help/pycharm/set-up-a-git-repository.html) 通过p ...
- 【坚持】Selenium+Python学习记录 DAY9
2018/05/29 [来源:菜鸟教程](http://www.runoob.com/python3/python3-examples.html) 运算符重载 https://segmentfault ...
- 【坚持】Selenium+Python学习记录 DAY8
2018/05/ 28 [来源:菜鸟教程](http://www.runoob.com/python3/python3-examples.html) 继续敲类相关的代码 #No.1 class peo ...
- 【坚持】Selenium+Python学习之从读懂代码开始 DAY6
2018/05/23 Python内置的@property装饰器 [@property](https://www.programiz.com/python-programming/property) ...
- 【坚持】Selenium+Python学习之从读懂代码开始 DAY5
2018/05/22 函数作为返回值 [来源:廖雪峰的官方网站](https://www.liaoxuefeng.com/) #No.1 def lazy_sum(*args): def sum(): ...
随机推荐
- Apache里的httpd-vhosts.conf详解
首先看下面的配置: <VirtualHost *:80> ServerAdmin webmaster@dummy-host.example.com DocumentRoot "D ...
- lumen 常用辅助函数
optional 函数接收任意参数并允许你访问对象上的属性或调用其方法.如果给定的对象为空,属性或方法调用返回 null return optional($user->address)-> ...
- win7win8 64位汇编开发环境合集安装与设置
win7win8 64位汇编开发环境合集安装与设置 下载 win7 win8 64位汇编开发环境.rar 下载地址(免积分下载) http://download.csdn.net/detail/li ...
- Mac 安装Bower
1.安装bower,得首先安装node: 1 brew install npm //npm是nodejs的程序包管理器,如果安装过nodejs,可忽略此步. 2.安装Git(因为需要从Git仓库获取 ...
- Android模拟器基本使用和常用工具介绍
注:其中部分内容参考网上资源 1.Android模拟器介绍 Android中提供了一个模拟器来模拟ARM核的移动设备.Android的模拟器是基于QEMU开发的,QEMU是一个有名的开源虚拟机项目(详 ...
- handlebars Helper用法
handlebars Helper用法: http://www.cnblogs.com/iyangyuan/archive/2013/12/12/3471357.html 逻辑运算符在handle ...
- 【BZOJ1495】[NOI2006]网络收费 暴力+DP
[BZOJ1495][NOI2006]网络收费 Description 网络已经成为当今世界不可或缺的一部分.每天都有数以亿计的人使用网络进行学习.科研.娱乐等活动.然而,不可忽视的一点就是网络本身有 ...
- 【POJ3621】Sightseeing Cows 分数规划
[POJ3621]Sightseeing Cows 题意:在给定的一个图上寻找一个环路,使得总欢乐值(经过的点权值之和)/ 总时间(经过的边权值之和)最大. 题解:显然是分数规划,二分答案ans,将每 ...
- 《从零开始学Swift》学习笔记(Day 66)——Cocoa Touch设计模式及应用之通知机制
原创文章,欢迎转载.转载请注明:关东升的博客 通知(Notification)机制是基于观察者(Observer)模式也叫发布/订阅(Publish/Subscribe)模式,是 MVC( 模型-视图 ...
- java读代码步骤
一.读代码的步骤 1.知道代码时用什么IDE开发的 2.将代码导入到IDE 3.连接数据库 A)连接到测试数据库 B)有sql脚本,在本地创建一个数据库,执行脚本,建立数据结构和导入数据. 4.尝试运 ...