一、初识WEB-selenium自动化测试

针对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()

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.*)

注意:使用By之前需要导包from selenium.webdriver.common.by import By

6、find_elementsfind_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()

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 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()

1、验证码的处理

常见的验证码处理方式:

  • 借助第三方图片识别文字的工具

    • 缺点:准确率较低

  • 借助第三方网站识别验证码

    • 优点:准确率很高,几乎可以达到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、在输入验证码前,添加一个固定的时间等待,手动输入验证码

2、frame标签的处理

在输入商品名称时,明明元素属性存在,但是定位失败,这是为什么呢?

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标签中,再进行定位

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、如何上传图片

一般在前端点击的按钮都不是真正的上传文件控件,而是为了符合整体页面布局的<label>标签

在这个<label>标签的上方还存在一个<input type='file'...>标签,且class属性为不可见。我们要做的就是找到这个控件,然后直接对这个控件进行send_keys,发送图片的路径

chrome.find_element(By.NAME,'file').send_keys('//Mac/Home/Desktop/1643087781227.jpg')

5、元素定位的8种方式

  • ID :使用ID进行定位

  • NAME:使用name进行定位

    • 使用id和name定位的优缺点:

      • 优点:易于定位元素,大多数时其属性值时唯一的

      • 缺点:很多元素不具备idname属性

  • CLASS_NAME :使用classname进行定位

  • TAG_NAME :使用tagname(标签名)进行定位

    • 使用class_name和tag_name定位的优缺点:

      • 优点:几乎所有的元素都具备class_nametag_name的属性

      • 缺点:classtag的值往往不是唯一的,很难精准找到一个元素

  • LINK_TEXT :使用超链接文本定位

  • PARTIAL_LINK_TEXT :使用部分超链接文本定位

    • 使用link_textpartial_link_text特点:只能用于<a>标签

  • XPATH :使用xpath定位

  • CSS_SELECTOR :使用css_selector定位

    • 使用xpathcss_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前置条件

在类中所有方法前,需要进行的前置条件
@classmethod
def setUpClass(cls):
  • class后置条件

在类中所有方法后,需要进行的后置条件
@classmethod
def tearDown(cls):
  • 前置条件

在每条测试用例方法开始前,需要进行的前置条件
def setUp(self):
  • 后置条件

在每条测试用例方法结束后,需要进行的后置条件
def tearDown(self):

3、BaseTestCase的封装

因为所有的测试用例都需要进行浏览器的相关操作

import time
import unittest2
from selenium import webdriver
​
​
class BaseTestCase(unittest2.TestCase):@classmethoddef setUpClass(cls):cls.driver = webdriver.Chrome()cls.driver.maximize_window()cls.driver.implicitly_wait(5)
​@classmethoddef tearDownClass(cls):# time.sleep(10)cls.driver.quit()

4、数据驱动测试

基础步骤:

  • 创建一个Excel表格进行测试数据准备

username password confirm_password mobile_num email
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:passelse:list.append(row)i = i + 1return 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 列表中的数据进行了拆分,每一行即为一个参数

5、生成测试报告(HTMLTestRunner)

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表示以二进制的方式进行写入

6、断言

作用:自动判断测试用例执行的结果是否成功

一般情况使用的检查点包括:

  • 页面级别的检查

    • 网页的标题

    • 网址的变化

  • 页面元素级别的检查

    • 元素的文本

    • 元素的某个属性

以海盗商城的登录为例
# 对比网页的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)').textself.assertEqual('您好 '+row[0]+'', welcome)

六、持续集成

目标:

  • 实现定时执行测试用例

  • 测试报告邮件提醒

1、安装环境

  • 安装jdk

    • 配置环境变量JAVA_HOME:安装路径

  • 解压tamcat文件

    • 解压tomacat文件夹,一般存放在D盘根目录中

  • Jenkins文件处理

    • 将Jenkins.war文件复制到到tomacat\webapps文件夹中

2、启动Jenkins

  • 运行tomacat\bin下面的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:默认的邮件正文

      <!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:必须为空,否则邮件发送失败

5、版本控制

SVN版本控制和GIT版本控制

WEB自动化测试总结篇相关推荐

  1. pythonselenium教程模拟鼠标和键盘_【02篇】python+selenium实现Web自动化:鼠标操作和键盘操作!...

    一.前言 最近问我自动化的人确实有点多,个人突发奇想:想从0开始讲解python+selenium实现Web自动化测试,请关注博客持续更新! 这是python+selenium实现Web自动化第二篇博 ...

  2. git关闭密码自动存储_RobotFramework实战篇PC端web自动化demo及持续集成

    自己学习自动化的话,除了要选好一款框架之外,还要选好一个用来练习的项目.这里小编推荐新手入门可以考虑一下Robotframework这个框架,原因:该框架的学习成本比较低,很多功能都是现成的,而且脚本 ...

  3. 从零开始的自动化测试框架-web自动化篇

    随着软件测试领域对于技术要求越来越清晰,到现在测试人员在市场上的岗位需求也变得越来越复杂.极大部分的企业都开始对自动化测试岗位有了更多的需要.自然而然,自动化测试技术开始成为了下一个被玩烂的技术点. ...

  4. python selenium - web自动化环境搭建

    前提: 安装python环境. 参考另一篇博文:https://www.cnblogs.com/Simple-Small/p/9179061.html web自动化:实现代码驱动浏览器进行点点点的操作 ...

  5. RFS的web自动化验收测试——第12讲 List Variables-List变量及其用法

    引言:什么是RFS--RobotFramework+Selenium2library,本系列主要介绍web自动化验收测试方面. ( @齐涛-道长 新浪微博) 这一讲我们重点来介绍List Variab ...

  6. ide循环执行用例 selenium_Selenium Web自动化Page Object设计模式——循环执行测试用例...

    继续优化上一篇博客的设计 Selenium Web自动化Page Object设计模式--driver初始化 https://www.cnblogs.com/Ravenna/p/14172411.ht ...

  7. Web 安全工具篇:Burp Suite 使用指南

    本文来自作者 肖志华 在 GitChat 上分享 「Web 安全工具篇:Burp Suite 使用指南」,「阅读原文」查看交流实录.​​​​​​​ 编辑 | 哈比 前提声明: 此次 Gitchat 分 ...

  8. 做Web自动化前,你必会的几个技能

    学习web自动化的前提条件:手工测试(了解各种测试的知识).学习编程语言.学习Web基础.学习自动化测试工具 .学习自动化测试框架 .需要掌握前端的一些知识,无论学习语言还是前端知识,都是为了接下来的 ...

  9. Day32 Web自动化进阶

    系列文章目录 Day01 软件测试基础总结 Day02 测试用例知识点总结(上) Day03 测试用例知识点总结(下) Day04 禅道-从安装到卸载 Day05 MySql的基础使用 Day06 M ...

最新文章

  1. python列表的解析(转)
  2. mysql求女生人数_在读女硕士110多万!为什么越来越多的女生选择考研?
  3. 网站转移到新服务器后显示乱码,请问在国内制作的英文网站放到国外的服务器后在国外打开怎么全是乱码?...
  4. 排序箭头,升序,降序简单实现
  5. linux常用命令 运算命令
  6. 把室友的STM32换成了GD32,会被打吗?
  7. 如何使用FF的Firebug组件中的net工具查看页面元素加载消耗时间
  8. 互联网晚报 | 3月3日 星期三 |​ 淘特宣布上线淘特10元店、淘特100;​A股三大指数集体收涨,多只地产股涨停...
  9. 信息传输计算机服务业,信息传输软件和信息技术服务业包括哪些
  10. 拳王虚拟项目公社:流量如何截流?各类流量截流技巧分享
  11. 长痘痘了吃什么好得快?
  12. hdu-acm steps Common Subsequence
  13. 属于计算机网络资源子网的,属于计算机网络的资源子网.pdf
  14. matlab句柄无效怎么解决,新编MATLABSimulink自学一本通第21章 MATLAB程序编译.ppt
  15. 2011浙江省公务员考试申论大作文的写作
  16. 天玑1300和骁龙778plus哪个好
  17. 看雪CTF2020 KCTF 秋季赛 签到题
  18. 纽约大学研究生 计算机科学 申请,纽约大学计算机科学理学硕士理学硕士研究生申请要求及申请材料要求清单...
  19. MPEG4视频编码技术介绍
  20. python 电子词典的实现

热门文章

  1. Git合并指定commits到另一个分支
  2. python图书管理系统制作
  3. python属于前端_Django是前端还是后端?
  4. Angular基础教程
  5. 结构流体多物理场耦合高性能仿真计算集群配置推荐
  6. 左右端点相同的开区间和闭区间/半开半闭区间 之间的一一映射怎么构造
  7. 电控—关于电机转子预定位的一些理解
  8. 精灵图(css sprites)
  9. 关于tesseract的报错解决
  10. 「现代C++设计魅力」虚函数继承-thunk技术初探