当前位置:   article > 正文

WEB自动化测试总结篇

web自动化测试

一、初识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 tearDownClass(cls):
  • 前置条件

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

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

3、BaseTestCase的封装

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

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

4、数据驱动测试

基础步骤:

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

usernamepasswordconfirm_passwordmobile_numemail
changcheng212112345612345613456788765changcheng2121@163.com
changcheng212212345612345613456788766changcheng2121@164.com
changcheng212312345612345613456788767changcheng2121@165.com
changcheng212412345612345613456788768changcheng2121@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 列表中的数据进行了拆分,每一行即为一个参数

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)').text
       self.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版本控制

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/999469
推荐阅读
相关标签
  

闽ICP备14008679号