针对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 timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom 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)# 第三种元素定位方式,linktextchrome.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()
1、隐式等待driver.implicitly_wait(10)
和time.sleep(10)的区别
隐式等待是一种智能等待,可以自动判断需要等待时间。括号中的时间代表最大等待时间
隐式等待只需要在声明driver之后,书写一次即可影响后面的所有代码
time.sleep()则需要在每次等待之前进行书写
2、窗口最大化chrome.maximize_window()
3、窗口切换
找出新窗口的名字
new_window = driver.window_handles[-1]
切换到新窗口
driver.switch_to.window(new_window)
4、下拉框选择
定位下拉框
element=driver.find_element(By....)
把找到的页面元素,转换为下拉框的类型Select
select = Select(element)
调用Select类中的select_by_*方法
.select_by_value(选项的value属性的值)
.select_by_index(第几个选项)
.select_by_visible_text(选项的文本值)
5、find_element_by_*的形式提示代码已过期现对原有的定位方式进行修改为find_element(By.*)
6、find_elements和find_element的区别注意:使用By之前需要导包from selenium.webdriver.common.by import By
find_elements可以找到相同标签名的全部信息,再通过序号的形式找到对应的值
find_element只能默认找到第一个标签名的信息
driver.find_elements(...)[0]==diver.find_element(...)
三、针对海盗商城的修改个人信息功能进行自动化测试# 1、登录import timefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditionsfrom selenium.webdriver.support.wait import WebDriverWaitchrome = 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.textprint(update_status)chrome.switch_to.alert.accept()
1、当对submit按钮无法定位时可以通过submit方法提交表单中的任何一个元素。在form表单中,所有数据都是存在一个表单中的,对其中的一个元素进行提交都可造成所有数据一起提交的效果。
chrome.find_element(By.ID, 'password').submit()
2、css_selector定位方式
浏览器中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()
3、如何操作日历控件传统的方法就是一次一次的点击,选择年月日。但是很容易出现错误
在这个日历控件中可以看到,在其属性中有一个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()
4、弹出框的处理页面的弹出框alert,是Javascript的控件,而非是HTML的页面元素。
Selenium提供了三种常用处理alert的方法:
driver.switch_to.alert.accept()——点击确定
driver.switch_to.alert.dismiss()——点击取消
driver.switch_to.alert.text——获取弹出框提示的文本信息
注意:
在处理弹出框时,隐式等待时不起作用的
隐式等待判断的是页面加载,当alert弹出框出现后,页面是没有刷新的,所以隐式等待无效
5、显示等待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 timefrom selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditionsfrom selenium.webdriver.support.select import Selectfrom 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()'''在前端点击的按钮不是真正复制上传文件的控件,真正负责上传文件的控件是我们要做的是,找到这个控件。然后直接对这个控件进行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()
1、验证码的处理常见的验证码处理方式:
借助第三方图片识别文字的工具
缺点:准确率较低
借助第三方网站识别验证码
优点:准确率很高,几乎可以达到100%
缺点:收费
设置万能验证码
当我们在测试环境中时,求助开发人员帮忙设置一个万能验证码,以便使用
2、frame标签的处理问题:如何查看系统是否存在万能验证码呢?以海盗商城为例
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')
把鼠标放在根节点
标签上,检查页面高亮部分是否覆盖全屏
如果覆盖全屏,说明页面中不存在frame标签
如果不能覆盖全屏,说明页面中存在frame标签
检查后发现,页面中存在一个frame标签,且商品名称等信息都在该标签中
使用driver.switch_to.frame('frame的name属性名')来切换到frame标签中,再进行定位
3、元素的高级操作如何实现鼠标左键的双击呢?
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中存储的行为,在命令最后添加
4、如何上传图片一般在前端点击的按钮都不是真正的上传文件控件,而是为了符合整体页面布局的
在这个
chrome.find_element(By.NAME,'file').send_keys('//Mac/Home/Desktop/1643087781227.jpg')
5、元素定位的8种方式
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特点:只能用于标签
XPATH :使用xpath定位
CSS_SELECTOR :使用css_selector定位
使用xpath和css_selector几乎可以用于定位所有页面元素
都有工具可以直接生成,但是工具生成的不一定100%管用,有些情况仍然需要手工书写
6、几种常用定位元素后的操作方式
click() :鼠标左键单击
send_keys:模拟键盘输入
submi():提交表单
clear():清除
五、自动化测试框架unittest2 1、unittest2介绍unittest2是unittest的升级版,都是Python自带测试库,是单元测试框架,提供了丰富的断言方法
unittest2的四大特点:
TestCase:测试案例,所有的用例都是直接继承于Unittest2.TestCase类
TestFixture:SetUp和TearDown,作为前置条件和后置条件
TestSuite:测试套件,一组测试案例,运行套件,则运行套件中所有的测试案例
TestRunner:测试运行器,与TestSuite结合一起使用
断言:在Unittest2中封装了很多成熟断言,可以直接被调用
2、unittest2的使用
Unittest2环境搭建
import unittest2
Unittest2语法规则
Unittest2中测试用例定义都是以test_开头
注意:用例排序与写的顺序无关,排序遵循A-Z,a-z,0-9
class前置条件
在类中所有方法前,需要进行的前置条件@classmethoddef setUpClass(cls):
class后置条件
在类中所有方法后,需要进行的后置条件@classmethoddef tearDown(cls):
前置条件
在每条测试用例方法开始前,需要进行的前置条件def setUp(self):
后置条件
在每条测试用例方法结束后,需要进行的后置条件def tearDown(self):
3、baseTestCase的封装因为所有的测试用例都需要进行浏览器的相关操作
import timeimport unittest2from selenium import webdriverclass 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()
4、数据驱动测试基础步骤:
创建一个Excel表格进行测试数据准备
编写代码读取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.pyimport csvimport os.pathdef 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.pyfrom selenium.webdriver.common.by import Byfrom func.csvFilemanager2 import readerfrom test_case.baseTestCase import baseTestCaseclass 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.pyimport ddtfrom selenium.webdriver.common.by import Byfrom func.csvFilemanager2 import readerfrom test_case.baseTestCase import baseTestCase@ddt.ddtclass 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):
用来表示该类是一个数据驱动测试类
5、生成测试报告(HTMLTestRunner)问题:方法上面的修饰器的作用是什么?
@ddt.data(*table) def test_register(self, row):
用来指定测试数据源,要求数据源格式为多个参数
*table 是将table 列表中的数据进行了拆分,每一行即为一个参数
HTMLTestRunner提供了一个可以生成美观的测试报告的模板
使用方法:
下载并复制HTMLTestRunner.py文件到我们的项目中
使用HTMLTestRunner这个类来执行测试用例
run_all_cases.pyimport unittest2from lib.HTMLTestRunner import HTMLTestRunnerif __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表示以二进制的方式进行写入
6、断言作用:自动判断测试用例执行的结果是否成功
一般情况使用的检查点包括:
页面级别的检查
网页的标题
网址的变化
页面元素级别的检查
元素的文本
元素的某个属性
以海盗商城的登录为例# 对比网页的titleself.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)——表示为第一个子标签,n=1welcome = self.driver.find_element(By.CSS_SELECtOR, '.site-nav-right.fr > a:nth-child(1)').textself.assertEqual('您好 XieChuang', welcome)# 对比页面跳转后的搜索value属性是否相同search = self.driver.find_element(By.CSS_SELECTOR, '.btn1').get_attribute('value')self.assertEqual('搜索', search)
实际运行代码如下:import timeimport ddtfrom selenium.webdriver.common.by import Byfrom TestCases.baseTestCases import baseTestCasesfrom TestCases.csvFileManager2 import reader@ddt.ddtclass 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)
六、持续集成目标:
实现定时执行测试用例
测试报告邮件提醒
1、安装环境
安装jdk
配置环境变量JAVA_HOME:安装路径
解压tamcat文件
解压tomacat文件夹,一般存放在D盘根目录中
Jenkins文件处理
将Jenkins.war文件复制到到tomacatwebapps文件夹中
2、启动Jenkins
运行tomacatbin下面的startup.bat文件
当出现jenkins is fully up and running后
在浏览器上输入网址
或者在webapps目录下使用dos命令:java -jar jenkins.war
3、定时执行测试任务
在构建中选择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分钟执行一次,但不一定是整点和半点执行,可能在任何一个时间点。会自动找服务器的空闲时间执行,更推荐使用
4、设置邮件提醒
安装插件
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:默认的邮件正文
项目名称 : ${PROJECT_NAME} 测试报告: 测试报告 构建编号 : 第${BUILD_NUMBER}次构建 触发原因: ${CAUSE} 构建状态: ${BUILD_STATUS} 构建日志: ${BUILD_URL}console 构建 Url : ${BUILD_URL} 工作目录 : ${PROJECT_URL}ws 项目 Url : ${PROJECT_URL} 失败用例 ${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="%d [%a] %m"}详细提交: ${PROJECT_URL}changes
各位同事,大家好,以下为${PROJECT_NAME }项目构建信息 构建结果 - ${BUILD_STATUS}
构建信息
$FAILED_TESTS
最近提交(#$SVN_REVISION)
勾选Enable Debug Mode:如果邮件发送失败,日志中会包含详细的错误信息
点击Default Triggers
勾选Always:不论测试执行是否失败,总是发送邮件
保存,设置完成
项目设置
打开之前创建的任务,进入配置
构建后操作
选择Editable Email Notification
Project From:必须为空,否则邮件发送失败
5、版本控制SVN版本控制和GIT版本控制