赞
踩
针对bing网站的搜索功能进行自动化测试
# 从谷歌公司的一个项目selenium导入webdriver这段代码来驱动浏览器 chrome = webdriver.Chrome() # 2、打开bing网站 chrome.get('http://cn.bing.com/') # 3、输入关键词 chrome.find_element_by_id('sb_form_q').send_keys('51tesing') # 4、点击搜索按钮 chrome.find_element_by_id('search_icon').click()
如今,大多数软件应用都是跑在浏览器中网站应用。不同公司和组织之间的测试效率迥异。在这个富交互和响应示处理随处可见的时代,很多组织都使用敏捷的方式来开发,因此测试自动化也称为软件项目的必备部分。测试自动化意味着使用软件工具来反复运行项目中的测试,并为回归测试提供反馈。
测试自动化有很多优点,大多数都与测试的可重复性和高执行率相关。市面上有一些商业或开源的工具来辅助测试自动化开发。Selenium应用是最广泛使用的开源方案。
import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.select import Select # 1、登录 chrome = webdriver.Chrome() chrome.implicitly_wait(10) # 由于页面稳定性较差,所以添加了一个隐式等待 chrome.maximize_window() # 窗口最大化 chrome.get('http://129.211.129.101:9007/index.php?m=user&c=public&a=login') # chrome.find_element_by_id('username').send_keys('XieChuang') 该命令的输入方式已经过期 chrome.find_element(By.ID, 'username').send_keys('XieChuang') chrome.find_element(By.ID, 'password').send_keys('123456') # chrome.find_element_by_class_name('login_btn fl').click() # 登录的类名是复合类名,不能同时使用,fl只是一个左对齐的作用 chrome.find_element(By.CLASS_NAME, 'login_btn').click() # 2、点击'进入商城购物' # 登录成功后不是立马进行页面的,所以此处添加一个时间等待 time.sleep(3) # 第三种元素定位方式,linktext chrome.find_element(By.LINK_TEXT, '进入商城购物').click() # 3、搜索'iphone' chrome.find_element(By.NAME, 'keyword').send_keys('小米6') chrome.find_element(By.CLASS_NAME, 'btn1').click() # 4、点击商品图片 chrome.find_element(By.XPATH, '/html/body/div[3]/div[2]/div[3]/div[2]/div[1]/a/img').click() # 5、窗口切换 # 1、找到新窗口的名字 new_window = chrome.window_handles[-1] # 2、切换到新窗口 chrome.switch_to.window(new_window) # 6、把选择的商品加入购物车 chrome.find_element(By.ID, 'joinCarButton').click() # 此时由于跳转了新窗口,所以无法进行操作 # 7、去购物车结算 chrome.find_element(By.CLASS_NAME, 'other_join').click() # 8、点击结算 css selector 定位方式:在两个class之前需要加. chrome.find_element(By.CSS_SELECTOR, '.shopCar_btn_03.fl').click() # 9、添加新地址 chrome.find_element(By.CLASS_NAME, 'add-address').click() # 10、填写收货人信息 chrome.find_element(By.NAME, 'address[address_name]').send_keys('XC') chrome.find_element(By.NAME, 'address[mobile]').send_keys('15910100202') # 11、选择地区的下拉框 sheng=chrome.find_element(By.ID,'add-new-area-select')# 将省这个下拉框进行实例化 Select(sheng).select_by_visible_text('北京市')# 将实例化的下拉框进行类型强制转换成Select型,再使用下拉框的属性进行选择 # 12、选择收货地区--市 由于下拉框中的ID是动态变化的,且class name又是同名的,所以使用find_elements来找到相同class name,再使用标签名来组合 shi=chrome.find_elements(By.CLASS_NAME,'add-new-area-select')[1] Select(shi).select_by_visible_text('北京市') qu=chrome.find_elements(By.TAG_NAME,'select')[2] # 使用标签名来定位 Select(qu).select_by_visible_text('海淀区') chrome.find_element(By.NAME, 'address[address]').send_keys('迈行大厦') chrome.find_element(By.NAME, 'address[zipcode]').send_keys('100000') chrome.find_element(By.CLASS_NAME,'aui_state_highlight').click()
driver.implicitly_wait(10)
和time.sleep(10)
的区别
隐式等待是一种智能等待,可以自动判断需要等待时间。括号中的时间代表最大等待时间
隐式等待只需要在声明driver之后,书写一次即可影响后面的所有代码
time.sleep()
则需要在每次等待之前进行书写
chrome.maximize_window()
找出新窗口的名字
new_window = driver.window_handles[-1]
切换到新窗口
driver.switch_to.window(new_window)
定位下拉框
element=driver.find_element(By....)
把找到的页面元素,转换为下拉框的类型Select
select = Select(element)
调用Select类中的select_by_*
方法
.select_by_value(选项的value属性的值)
.select_by_index(第几个选项)
.select_by_visible_text(选项的文本值)
find_element_by_*
的形式提示代码已过期现对原有的定位方式进行修改为find_element(By.*)
注意:使用By之前需要导包from selenium.webdriver.common.by import By
find_elements
和find_element
的区别find_elements
可以找到相同标签名的全部信息,再通过序号的形式找到对应的值
find_element
只能默认找到第一个标签名的信息
driver.find_elements(...)[0]
==diver.find_element(...)
# 1、登录 import time from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.wait import WebDriverWait chrome = webdriver.Chrome() chrome.implicitly_wait(5) chrome.maximize_window() chrome.get("http://129.211.129.101:9007/index.php?m=user&c=public&a=login") chrome.find_element(By.ID, 'username').send_keys('XieChuang') chrome.find_element(By.ID, 'password').send_keys('123456') # submit方法:类似于click(),只能用于form表单中 # 当无法定位到按钮时,可以使用同一表单中的任意元素进行submit提交 chrome.find_element(By.ID, 'password').submit() # 使用submit代替了定位登录按钮进行提交 # 2、修改个人信息 # 2.1 点击"账户设置" chrome.find_element(By.LINK_TEXT, '账号设置').click() # 2.2 点击"个人资料" 当link_text中的文字信息被其他数据阻挡时,可以使用partial_link_text使用部分的文字信息进行定位 chrome.find_element(By.PARTIAL_LINK_TEXT, '人资').click() # 2.3 修改"真实姓名" chrome.find_element(By.ID, 'true_name').clear() chrome.find_element(By.ID, 'true_name').send_keys('小谢') # 2.4 选择"性别" # 通过CSS_SELECTOR的方式,可以采用任意的属性来定位元素。只需要在属性的两边加一对中括号即可 chrome.find_element(By.CSS_SELECTOR, '[value="1"]').click() # 2.5 输入"出生年月" # 日历控件 # 传统的方法是一次一次的点击,选择年月日 # 新方法:1、删除readonly属性 2、直接向日历控件中输入日期 # 问题:selenium无法实现删除一个元素的属性,但是JavaScrip可以实现 # 2.5.1编写JavaScript命令脚本 script = 'document.getElementById("date").removeAttribute("readonly")' # 2.5.2浏览器执行这段JavaScript命令,进行属性的删除 chrome.execute_script(script) # 2.5.3 清除默认值——由于日历控件中有默认值,直接输入日期无法完成覆盖,所以进行删除操作 chrome.find_element(By.ID, 'date').clear() # 2.5.4 直接在输入框中输入生日 chrome.find_element(By.ID, 'date').send_keys('1980-02-02') # 2.6 输入"QQ" chrome.find_element(By.ID, 'qq').clear() chrome.find_element(By.ID, 'qq').send_keys('123456789') # 2.7 点击"确定" chrome.find_element(By.CSS_SELECTOR, '[value="确认"]').click() # 3、弹出框的处理 # 弹出框Alert,不是HTML的页面元素,而是JavaScript的控件 # 由于不能右键检查,所以不能用传统的方法操作 # selenium提供了三个常用处理Alert的方法 # chrome.switch_to.alert.accept() ——点击确定按钮 # chrome.switch_to.alert.dismiss() ——点击取消按钮 # chrome.switch_to.alert.text ——获取弹出框提示的文本信息 # time.sleep(3) # 处理弹出框时,隐式等待不起作用 # 隐式等待判断的是页面的加载,而弹出框出来后,页面没有刷新过,所以隐式等待在这里不起作用 # 由于time.sleep()的等待时间过长,这里引用第三种等待方式 WebDriverWait(chrome, 30, 0.5).until(expected_conditions.alert_is_present()) # WebDriverWait需要传入三个属性,diver ,timeout(最大等待时间),poll_frequency(多少时间检查一次) # expected_conditions 条件检查,需要导包 # alert_is_present 有Alert弹出 update_status = chrome.switch_to.alert.text print(update_status) chrome.switch_to.alert.accept()
可以通过submit方法提交表单中的任何一个元素。在form表单中,所有数据都是存在一个表单中的,对其中的一个元素进行提交都可造成所有数据一起提交的效果。
chrome.find_element(By.ID, 'password').submit()
浏览器中copy。在元素上鼠标右键检查元素,选择copy再选择copy selector
手工书写selector
标签名可以直接写在css selector中使用
使用任意元素的属性来进行定位,只需要在属性的两边加一对中括号
class属性前面加一个小数点.
ID属性前面加一个井号#
[]用来表示所有属性
属性间>(大于号),表示大于号前面的元素是后面元素的父元素
属性间 (空格),表示前面的元素是后面元素的祖先元素
例如:
chrome.find_element(By.CSS_SELECTOR, '[value="确认"]').click()
chrome.find_element(By.CSS_SELECTOR,'.uploadBtn.state-finish.state-ready').click()
chrome.find_element(By.CSS_SELECTOR,'#filePicker label').click()
传统的方法就是一次一次的点击,选择年月日。但是很容易出现错误
在这个日历控件中可以看到,在其属性中有一个readonly属性,这就造成了这个日历控件输入框具有只读的特性。
我们可以通过删除readonly属性,再直接输入日期的方式完成日期输入的操作
问题:
Selenium不具有删除一个元素属性的功能
JavaScript具有这个功能
# 编写一段JavaScript命令,并实例化 script = 'document.getElementById("date").removeAttribute("readonly")' # 通过浏览器执行这段JavaScript命令,完成删除readonly属性的操作 chrome.execute_script(script)
问题:
日历控件中的readonly属性删除了,日期也输入了,但是日历控件存在默认值怎么办呢?
借助Selenium的clear动作来删除默认值
chrome.find_element(By.ID, 'date').clear()
页面的弹出框Alert,是JavaScript的控件,而非是HTML的页面元素。
Selenium提供了三种常用处理Alert的方法:
driver.switch_to.alert.accept()
——点击确定
driver.switch_to.alert.dismiss()
——点击取消
driver.switch_to.alert.text
——获取弹出框提示的文本信息
注意:
在处理弹出框时,隐式等待时不起作用的
隐式等待判断的是页面加载,当Alert弹出框出现后,页面是没有刷新的,所以隐式等待无效
WebDriverWait(driver,timeout=程序需要等待的最长时间,poll_frequency=每隔几秒执行until中的方法).until(method='执行什么方法,具体来做什么事情')
例如:
WebDriverWait(chrome, 30, 0.5).until(expected_conditions.alert_is_present())
其中expected_conditions
表示条件检查
alert_is_present()
表示有Alert弹框出现
# 1、登录海盗商城的后台管理系统 import time from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.select import Select from selenium.webdriver.support.wait import WebDriverWait # 1.1 打开后台登录界面 chrome = webdriver.Chrome() chrome.implicitly_wait(5) chrome.maximize_window() chrome.get('http://localhost/pirate/admin.php') # 1.2 输入用户名、密码、验证码 chrome.find_element(By.NAME, 'username').send_keys('admin') chrome.find_element(By.NAME, 'userpass').send_keys('password') chrome.find_element(By.NAME,'userverify').send_keys('1234') # 1.3 点击登录按钮 chrome.find_element(By.CLASS_NAME,'Btn').click() # 2、添加商品 # 2.1 在后台管理中心,点击商品管理 chrome.find_element(By.LINK_TEXT,'商品管理').click() # 2.2 点击添加商品 chrome.find_element(By.LINK_TEXT,'添加商品').click() # 2.3 输入商品名称 # 此处存在HTML嵌套,需要进行子页面切换 chrome.switch_to.frame('mainFrame') chrome.find_element(By.NAME,'name').send_keys('iPone xs max') # 2.4 选择商品分类 chrome.find_element(By.ID,'1').click() chrome.find_element(By.ID,'2').click() chrome.find_element(By.ID,'3').click() # chrome.find_element(By.ID,'4') # 元素的高级操作 ActionChains中封装了所有可以对页面元素进行的高级操作 # Action——动作 # Chains——链表 # chrome——当前浏览器 # 合起来就是,把当前浏览器转换为一个可以执行各种操作的行为链 # perform()作为结束标志 ActionChains(chrome).double_click(chrome.find_element(By.ID,'4')).perform() # 2.5 选择商品品牌 brand = chrome.find_element(By.NAME,'brand_id') Select(brand).select_by_value('1') # 2.6 添加商品图片 chrome.find_element(By.LINK_TEXT,'商品图册').click() ''' 在前端点击的按钮不是真正复制上传文件的控件,真正负责上传文件的控件是<input type='file' ....> 我们要做的是,找到这个控件。然后直接对这个控件进行send_keys,发送图片或文件的路径即可 ''' chrome.find_element(By.NAME,'file').send_keys('//Mac/Home/Desktop/1643087781227.jpg') # 注意:图片路径处的'\'要进行转义,也就是写为'/' chrome.find_element(By.CSS_SELECTOR,'.uploadBtn.state-finish.state-ready').click() # 处理“上传成功”弹出框 WebDriverWait(chrome, 30 ,0.5).until(expected_conditions.alert_is_present()) chrome.switch_to.alert.accept() # 2.6 点击提交按钮 chrome.find_element(By.CLASS_NAME,'button_search').click()
常见的验证码处理方式:
借助第三方图片识别文字的工具
缺点:准确率较低
借助第三方网站识别验证码
优点:准确率很高,几乎可以达到100%
缺点:收费
设置万能验证码
当我们在测试环境中时,求助开发人员帮忙设置一个万能验证码,以便使用
问题:如何查看系统是否存在万能验证码呢?以海盗商城为例
1、明确开发人员为海盗商城写的源代码位置
2、为了看懂开发人员的代码,必须了解MVC设计模型
M——模型层,主要用于和数据库打交道
V——视图层,主要和前端打交道,用于收集和显示用户数据
C——控制器,主要用于处理业务逻辑
判断验证码是否正确就属于业务逻辑层
3、也可以通过网址来分析功能的源代码位置
http://172.31.14.251/pirate/index.php?m=admin&c=public&a=login
网址中主要分为5个部分:
http:协议
172.31.14.251:域名或者IP地址
/index.php:路径
m=admin&c=public&a=login:参数
m=admin——m代表模块,一个模块就是一个文件夹
c=public——c代表控制器(controller),一个控制器就是一个类,一个文件
a=login——a代表动作(action),一个action就是代码中的一个方法
4、在测试环境中屏蔽掉验证码
5、绑定IP地址
有些公司,在测试环境中,如果绑定IP地址是可以不显示验证码的
6、读取cookie和缓存
7、在输入验证码前,添加一个固定的时间等待,手动输入验证码
在输入商品名称时,明明元素属性存在,但是定位失败,这是为什么呢?
chrome.find_element(By.XPATH,'/html/body/div[2]/div[2]/dl/form/dd[1]/ul/li[1]/input').send_keys('ipone xs max')
把鼠标放在根节点<body>标签上,检查页面高亮部分是否覆盖全屏
如果覆盖全屏,说明页面中不存在frame标签
如果不能覆盖全屏,说明页面中存在frame标签
检查后发现,页面中存在一个frame标签,且商品名称等信息都在该标签中
使用driver.switch_to.frame('frame的name属性名')
来切换到frame标签中,再进行定位
如何实现鼠标左键的双击呢?
Selenium中提供了一个ActionChains的方法,可以对页面元素进行高级操作
context_click()
:鼠标右击
double_click()
:鼠标左键双击
drag_and_drop
:拖动
move_to_element
:鼠标悬停在一个元素上
click_and_hold()
:按下鼠标左键在一个元素上,一般配合release()
释放使用
key_down()
:在一个元素上按住一个键不松,只能与修改键(控制,Ctrl、Alt和Shift)一起使用
key_up()
:松开按键,释放修改键
move_by_offset()
:鼠标移动
perform()
:执行所有ActionChains中存储的行为,在命令最后添加
一般在前端点击的按钮都不是真正的上传文件控件,而是为了符合整体页面布局的<label>标签
在这个<label>标签的上方还存在一个<input type='file'...>标签,且class属性为不可见。我们要做的就是找到这个控件,然后直接对这个控件进行send_keys,发送图片的路径
chrome.find_element(By.NAME,'file').send_keys('//Mac/Home/Desktop/1643087781227.jpg')
ID :使用ID进行定位
NAME:使用name进行定位
使用id和name定位的优缺点:
优点:易于定位元素,大多数时其属性值时唯一的
缺点:很多元素不具备id
和name
属性
CLASS_NAME :使用classname进行定位
TAG_NAME :使用tagname(标签名)进行定位
使用class_name和tag_name定位的优缺点:
优点:几乎所有的元素都具备class_name
和tag_name
的属性
缺点:class
和tag
的值往往不是唯一的,很难精准找到一个元素
LINK_TEXT :使用超链接文本定位
PARTIAL_LINK_TEXT :使用部分超链接文本定位
使用link_text
和partial_link_text
特点:只能用于<a>标签
XPATH :使用xpath
定位
CSS_SELECTOR :使用css_selector
定位
使用xpath
和css_selector
几乎可以用于定位所有页面元素
都有工具可以直接生成,但是工具生成的不一定100%管用,有些情况仍然需要手工书写
click()
:鼠标左键单击
send_keys
:模拟键盘输入
submi()
:提交表单
clear()
:清除
unittest2是unittest的升级版,都是Python自带测试库,是单元测试框架,提供了丰富的断言方法
unittest2的四大特点:
TestCase:测试案例,所有的用例都是直接继承于Unittest2.TestCase类
TestFixture:SetUp和TearDown,作为前置条件和后置条件
TestSuite:测试套件,一组测试案例,运行套件,则运行套件中所有的测试案例
TestRunner:测试运行器,与TestSuite结合一起使用
断言:在Unittest2中封装了很多成熟断言,可以直接被调用
Unittest2环境搭建
import unittest2
Unittest2语法规则
Unittest2中测试用例定义都是以test_开头
注意:用例排序与写的顺序无关,排序遵循A-Z,a-z,0-9
class前置条件
在类中所有方法前,需要进行的前置条件 @classmethod def setUpClass(cls):
class后置条件
在类中所有方法后,需要进行的后置条件 @classmethod def tearDownClass(cls):
前置条件
在每条测试用例方法开始前,需要进行的前置条件 def setUp(self):
后置条件
在每条测试用例方法结束后,需要进行的后置条件 def tearDown(self):
因为所有的测试用例都需要进行浏览器的相关操作
import time import unittest2 from selenium import webdriver class BaseTestCase(unittest2.TestCase): @classmethod def setUpClass(cls): cls.driver = webdriver.Chrome() cls.driver.maximize_window() cls.driver.implicitly_wait(5) @classmethod def tearDownClass(cls): # time.sleep(10) cls.driver.quit()
基础步骤:
创建一个Excel表格进行测试数据准备
username | password | confirm_password | mobile_num | |
---|---|---|---|---|
changcheng2121 | 123456 | 123456 | 13456788765 | changcheng2121@163.com |
changcheng2122 | 123456 | 123456 | 13456788766 | changcheng2121@164.com |
changcheng2123 | 123456 | 123456 | 13456788767 | changcheng2121@165.com |
changcheng2124 | 123456 | 123456 | 13456788768 | changcheng2121@166.com |
编写代码读取csv表中的内容
csvFileManager.py # 进行csv文件的读取,以进行数据驱动 # 1、导入代码库 import csv # 2、指定csv文件所在的路径 path = r'/Users/chuangxie/Desktop/学习课件/SeleniumTest/test_data/login_test_cases.csv' '''当路径中存在反斜线时,需要在字符串前面加一个字母r 这时系统会将反斜线默认为字符串的一部分''' # 3、打开csv文件 file = open(path) # 4、进行csv中数据读取 table = csv.reader(file) # 5、打印csv文件中的内容 for i in table: print(i)
上方代码中的弊端:
文件始终处于打开状态,会验证影响运行效率
csvFileManager2.py import csv import os.path def reader(filename): list = [] # path = '../test_data/' + filename 由于文件路径可能会变化,故舍弃 base_path = os.path.dirname(__file__) # 表示当前文件所在路径 path = base_path.replace('func','test_data/'+filename) # 将func路径替换成test_data文件夹 # file = open(path) with open(path) as file: table = csv.reader(file) i = 0 # 用于剔除首行标题 for row in table: if i == 0: pass else: list.append(row) i = i + 1 return list
把读取到的内容分别传入测试用例中,循环执行
register2Test.py from selenium.webdriver.common.by import By from func.csvFilemanager2 import reader from test_case.BaseTestCase import BaseTestCase class register2Test(BaseTestCase): def test_register(self): table = reader('register_test_cases.csv') for row in table: self.driver.get('http://129.211.129.101:9007/index.php?m=user&c=public&a=reg') self.driver.find_element(By.NAME, 'username').send_keys(row[0]) self.driver.find_element(By.NAME, 'password').send_keys(row[1]) self.driver.find_element(By.NAME, 'userpassword2').send_keys(row[2]) self.driver.find_element(By.NAME, "mobile_phone").send_keys(row[3]) self.driver.find_element(By.NAME, 'email').send_keys(row[4])
上方代码中的弊端:
当使用for循环时,如果有一组数据运行失败了,后面的代码都不会被执行
改进方法:使用ddt代码库
csvFileManager3.py import ddt from selenium.webdriver.common.by import By from func.csvFilemanager2 import reader from test_case.BaseTestCase import BaseTestCase @ddt.ddt class register3Test(BaseTestCase): table = reader('register_test_cases.csv') @ddt.data(*table) def test_register(self, row): self.driver.get('http://129.211.129.101:9007/index.php?m=user&c=public&a=reg') self.driver.find_element(By.NAME,'username').send_keys(row[0]) self.driver.find_element(By.NAME, 'password').send_keys(row[1]) self.driver.find_element(By.NAME, 'userpassword2').send_keys(row[2]) self.driver.find_element(By.NAME, "mobile_phone").send_keys(row[3]) self.driver.find_element(By.NAME, 'email').send_keys(row[4])
问题:类上面的修饰器的作用是什么?
@ddt.ddt class register3Test(BaseTestCase):
用来表示该类是一个数据驱动测试类
问题:方法上面的修饰器的作用是什么?
@ddt.data(*table) def test_register(self, row):
用来指定测试数据源,要求数据源格式为多个参数
*table 是将table 列表中的数据进行了拆分,每一行即为一个参数
HTMLTestRunner提供了一个可以生成美观的测试报告的模板
使用方法:
下载并复制HTMLTestRunner.py文件到我们的项目中
使用HTMLTestRunner这个类来执行测试用例
run_all_cases.py import unittest2 from lib.HTMLTestRunner import HTMLTestRunner if __name__ == '__main__': # 1、找到所有需要执行的测试用例 suite = unittest2.defaultTestLoader.discover('./test_case', '*Test.py') # 2、执行找到的测试用例集 # unittest2.TextTestRunner().run(suite) # 3、生成测试报告 # 指定测试报告生成位置 path = 'report/TestReport.html' file = open(path, 'wb') # w表示写,b表示二进制, HTMLTestRunner(stream=file, verbosity=1, title='自动化测试报告', description='测试环境:Chrome', tester='谢闯').run(suite) # 实例化HTMLTestRunner
在实例化HTMLTestRunner时需要传入五个参数
HTMLTestRunner(stream=二进制文件, verbosity=1(日志的详细程度,默认即可),title=报告的标题,description=报告的正文, tester = 测试人员的名字)
文件file = open(path, 'wb')
的保存:
默认是以只读的方式打开文件
w表示以写的方式打开文件
b表示以二进制的方式进行写入
作用:自动判断测试用例执行的结果是否成功
一般情况使用的检查点包括:
页面级别的检查
网页的标题
网址的变化
页面元素级别的检查
元素的文本
元素的某个属性
以海盗商城的登录为例 # 对比网页的title self.assertEqual('我的会员中心 - 道e坊商城 - Powered by Haidao', self.driver.title) # 对比网址的变化 self.assertEqual('http://129.211.129.101:9007/index.php?m=user&c=index&a=index', self.driver.current_url) # 对比登录成功后,是否有登录用户名显示 # a:nth-child(1)——表示为第一个<a>子标签,n=1 welcome = self.driver.find_element(By.CSS_SELECTOR, '.site-nav-right.fr > a:nth-child(1)').text self.assertEqual('您好 XieChuang', welcome) # 对比页面跳转后的搜索value属性是否相同 search = self.driver.find_element(By.CSS_SELECTOR, '.btn1').get_attribute('value') self.assertEqual('搜索', search)
实际运行代码如下: import time import ddt from selenium.webdriver.common.by import By from TestCases.BaseTestCases import BaseTestCases from TestCases.csvFileManager2 import reader @ddt.ddt class loginTest(BaseTestCases): table = reader('login_test_cases.csv') @ddt.data(*table) def test_login(self, row): self.chrome.get('http://129.211.129.101:9007/index.php?m=user&c=public&a=login') self.chrome.find_element(By.NAME, 'username').send_keys(row[0]) self.chrome.find_element(By.NAME, 'password').send_keys(row[1]) self.chrome.find_element(By.NAME, 'password').submit() time.sleep(3) welcome = self.chrome.find_element(By.CSS_SELECTOR, '.site-nav-right.fr>a:nth-child(1)').text self.assertEqual('您好 '+row[0]+'', welcome)
目标:
实现定时执行测试用例
测试报告邮件提醒
安装jdk
配置环境变量JAVA_HOME:安装路径
解压tamcat文件
解压tomacat文件夹,一般存放在D盘根目录中
Jenkins文件处理
将Jenkins.war文件复制到到tomacat\webapps文件夹中
运行tomacat\bin下面的startup.bat文件
当出现jenkins is fully up and running后
在浏览器上输入网址
或者在webapps目录下使用dos命令:java -jar jenkins.war
在构建中选择window批处理命令
cd 项目路径
Python 测试用例执行脚本.py
编辑日程表
5个时间单位
分钟
小时
日期
月份
星期
6个符号
空格 :时间单位的间隔,有且只能有4个
*星号:表示有可能的取值
例:0 21 * * * 每天21点分别执行一次
-横线:表示区间
例:0 21 * * 1-5 每周一到周五的21点自动执行一次
,逗号:表示枚举
例: 0 8,12,20 * * * 每天的8点、12点、20点自动执行一次
/斜线:表示间隔
例:*/30 * * * * 每隔30分钟执行一次
H:用于分散负载
例:H/30 * * * * 同样是每隔30分钟执行一次,但不一定是整点和半点执行,可能在任何一个时间点。会自动找服务器的空闲时间执行,更推荐使用
安装插件
HTML Publisher
Email Extension Plugin
Email Extension Template Plugin
修改配置信息
系统管理员邮件地址
改成发邮件的邮箱
注意:要求是一个设置过客户端授权码的邮箱(我的授权码TALEENGMSITQLWAQ)
Extended E-mail Notification
SMTP server:smtp.163.com
SMTP Port:465
点击高级:添加jenkins
用户名:邮箱账号
密码:授权码,不能使用邮箱密码
ID:空
描述:空
勾选USE SSL
Default user e-mail suffix(默认邮箱后缀):@163.com
点击高级:
Admin Account Address:填写发件箱
SMTP server:smtp.163.com
SMTP Port:25
Default Content Type:HTML(text/html)
Default Recipients:默认的收件人地址
Default Content:默认的邮件正文
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title> </head> <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0"> <table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif"> <tr> 本邮件由系统自动发出,无需回复!<br/> 各位同事,大家好,以下为${PROJECT_NAME }项目构建信息</br> <td><font color="#CC0000">构建结果 - ${BUILD_STATUS}</font></td> </tr> <tr> <td><br /> <b><font color="#0B610B">构建信息</font></b> <hr size="2" width="100%" align="center" /></td> </tr> <tr> <td> <ul> <li>项目名称 : ${PROJECT_NAME}</li> <li>测试报告: <a href="${PROJECT_URL}HTML_20Report">测试报告</a></li> <li>构建编号 : 第${BUILD_NUMBER}次构建</li> <li>触发原因: ${CAUSE}</li> <li>构建状态: ${BUILD_STATUS}</li> <li>构建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li> <li>构建 Url : <a href="${BUILD_URL}">${BUILD_URL}</a></li> <li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li> <li>项目 Url : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li> </ul> <h4><font color="#0B610B">失败用例</font></h4> <hr size="2" width="100%" /> $FAILED_TESTS<br/> <h4><font color="#0B610B">最近提交(#$SVN_REVISION)</font></h4> <hr size="2" width="100%" /> <ul> ${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="<li>%d [%a] %m</li>"} </ul> 详细提交: <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a><br/> </td> </tr> </table> </body> </html>
勾选Enable Debug Mode:如果邮件发送失败,日志中会包含详细的错误信息
点击Default Triggers
勾选Always:不论测试执行是否失败,总是发送邮件
保存,设置完成
项目设置
打开之前创建的任务,进入配置
构建后操作
选择Editable Email Notification
Project From:必须为空,否则邮件发送失败
SVN版本控制和GIT版本控制
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。