ui自动化测试在整个测试过程中占据的地位
在一个项目的测试中手工测试(60%)/自动化测试(40%),不同公司的定义不同.总体是手工占大部分
而自动化测试中,接口自动化占据70%
ui自动化测试优先实现正向用例,回归测试时候跑一下流程
ui测试的特征
-界面修改频繁,
-界面需求变动大
-运行速度慢(浏览器打开速度慢,页面加载速度慢,页面操作动画)
-界面稳定性差
-界面排班不方便做自动化(像素点移动)
ui自动化测试流程(课堂派)
-需求分析
主要功能特性
-编写手工测试用例
提供参数以及数据,测试步骤(excel),方便以后回归测试参考--用例的作用
首先用手工测试完成用例的步骤,熟悉流程后再编写代码
-测试执行(编写自动化用例代码)
1,得到测试数据
username = "aaa"
password = "123"
expected = "密码有效长度是6到30个字符"
2.浏览器初始化操作
with Chrome(executable_path=driver) as browser:
browser.implicitly_wait(5)
browser.maximize_window()
3,访问url
browser.get('https://v4.ketangpai.com/User/login.html')
4,定位元素,传入账号密码
每次操作数据框,最好加上el.clear(),表示清空输入框
user_el = browser.find_element("name","account")
#清空输入框
user_el.clear()
browser.execute_script(f"arguments[0].value='{username}'",user_el)
pass_el = browser.find_element("name","pass")
pass_el.clear()
pass_el.send_keys(password)
5,点击按钮执行登录操作
browser.find_element(By.CSS_SELECTOR,".btn-btn").click()
6,获得实际结果
定位实际结果的元素
#获取文本
actual = browser.find_element(By.CSS_SELECTOR,'.error-tips').text
7,断言
#断言
assert expected == actual
8,生成报告
import pytest
from datetime import datetime
ts = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
pytest.main([f'--html=reports/report-{ts}'])
完整流程
class TestSignIn:
def test_sign_in(self):
'''登录功能
1,输入url: https://v4.ketangpai.com/User/login.html
2,输入用户名: aaa
3,密码: 123
4,点击登录按钮
'''
username = "aaa"
password = "123"
expected = "密码有效长度是6到30个字符"
with Chrome(executable_path=driver) as browser:
browser.implicitly_wait(5)
browser.maximize_window()
#访问url
browser.get('https://v4.ketangpai.com/User/login.html')
user_el = browser.find_element("name","account")
#清空输入框
user_el.clear()
browser.execute_script(f"arguments[0].value='{username}'",user_el)
pass_el = browser.find_element("name","pass")
pass_el.clear()
pass_el.send_keys(password)
browser.find_element(By.CSS_SELECTOR,".btn-btn").click()
#获取文本
actual = browser.find_element(By.CSS_SELECTOR,'.error-tips').text
#获取元素属性
actual1 = browser.find_element(By.CSS_SELECTOR,'.error-tips').get_attribute("name")
#断言
assert expected == actual
整体下来我们可以发现,在自动化测试用例中,包含了测试数据,还有元素定位的方法,代码多,而且数据维护起来不方便,因此,我们引入PO模式这个概念
PO模式-页面对象模型
是一个ui测试模式
把一个页面需要的操作封装到一个类,url作为类属性
好处:
1,自动化测试用例的代码变得简洁
2,可读性变强
3,页面操作封装完成,隔离管理,当前端界面发生变化,不需要维护测试用例,只需要维护页面操作的代码
4,po页面的操作可以重复使用
分层设计
1,隔离测试数据,当需要添加修改数据时候可以在单独的模块中修改
跟接口自动化不一样的是,接口自动化只需要把账号密码等可以重复使用的用户信息保存在配置文件夹里的py文件,因为接口自动化的测试步骤每次都相同
而web自动化需要把测试数据直接保存在测试数据文件夹里的py文件,原因是因为测试步骤每次都不一样,每次准备测试数据的结构都会存在差异
#获得测试数据
usename = login_fail["username"]
password = login_fail["password"]
expected = login_fail["expected"]
2,浏览器的管理可以重复使用,要进行单独封装
每次使用自动化测试函数,都需要得到浏览器对象,才能使用selenium的方法,所以我们会把浏览器初始化的操作封装成一个夹具
把得到浏览器的操作进行单独封装成一个夹具,表示每次执行用例时候都要先获取浏览器,并且执行完用例的时候关闭浏览器
@pytest.fixture()
def get_browser():
browser1 = Chrome(executable_path=driver)
browser1.implicitly_wait(5)
browser1.maximize_window()
yield browser1
browser1.quit()
这里最好不用使用with语句,因为with语句是打开之后并且关闭,容易混淆
然后在自动化测试函数中,把夹具作为参数传入
class TestLogin:
def test_login(self,get_browser):
夹具的返回值,就是通过Chome()得到的浏览器对象,代表我们通过夹具,生成了一个浏览器对象,每次执行用例都会得到这个对象(browser),然后就可以直接使用get_browser.方法了
3,需要把驱动放到配置文件中进行单独管理,可以存放多个驱动,可以灵活配置
4,域名单独管理,当改变了测试环境后可以方便管理
把host域名(常量)单独存放到配置文件,url地址用拼接的方式,放到po模式的类里,变成一个类属性,然后再使用实例方法调用类属性访问
5,页面的操作可以单独提取出来放到一个模块
该项目可以重复使用,方便以后操作其他页面
把登录页面所需操作都封装到一个类,形成PO模式,这个类就代表整个登录页面
在这个类里,方法都是需要浏览器对象,设置一个初始化函数,参数传入浏览器的对象,这样下面的方法就能少传参数
小技巧:
我们可以在初始化的参数里,加一个 :Chrome,表示这个参数是一个浏览器对象,之后的代码都会有selenium的提示
from selenium.webdriver.common.by import By
from config.config import host
class LoginPage:
url = host + "/User/login.html"
#初始化浏览器
def __init__(self,browser):
self.browser = browser
def get_url(self):
self.browser.get(self.url)
def login(self,username,password):
user_el = self.browser.find_element("name", "account")
# 清空输入框
user_el.clear()
self.browser.execute_script(f"arguments[0].value='{username}'", user_el)
pass_el = self.browser.find_element("name", "pass")
pass_el.clear()
pass_el.send_keys(password)
self.browser.find_element(By.CSS_SELECTOR, ".btn-btn").click()
def get_error_tips(self):
result = self.browser.find_element(By.CSS_SELECTOR,'.error-tips').text
return result
使用方法的时候,需要先初始化,填入浏览器对象
#从类中得到实例,传入夹具的返回值(浏览器对象)作为参数
broswer = LoginPage(get_browser)
#使用类里的实例方法
broswer.get_url()
broswer.login(usename,password)
#获取错误信息
actual = broswer.get_error_tips()
#断言
assert actual == expected
扩展:夹具嵌套
因为每次使用自动化测试用例都需要创建实例,我们还可以把初始化PO模式的页面类的实例再提取出去,变成一个夹具
在夹具中初始化PO模式里类的对象,参数传入上一个夹具(返回值就是浏览器对象)的名称
def get_browser():
browser = Chrome(executable_path=driver)
browser.implicitly_wait(5)
browser.maximize_window()
return browser
@pytest.fixture()
def browser():
browser = get_browser()
yield browser
browser.quit()
@pytest.fixture()
def login_page(browser):
return LoginPage(browser)
@pytest.fixture()
def home_page(browser):
return HomePage(browser)
之后就可以直接使用login_page这个夹具,它的返回值就是在Po的类里初始化的一个实例,可以调用类的实例方法,省略了在测试用例函数里初始化实例的步骤
class TestLogin:
def test_login(self,login_page):
#获得测试数据
usename = login_fail["username"]
password = login_fail["password"]
expected = login_fail["expected"]
#从类中得到实例,传入夹具的返回值(浏览器对象)作为参数
# broswer = LoginPage(get_browser)
#使用类里的实例方法
login_page.get_url()
#使用登录方法
login_page.login(usename,password)
#获取错误信息
actual = login_page.get_error_tips()
#断言
assert actual == expected
而无论父夹具(get_brower)被多少个子夹具嵌套,父夹具只会执行一次夹具里的操作,但是父夹具的返回值就可以被多个子夹具所调用
夹具嵌套的使用场景,在同一个浏览器上操作不同的页面,多端操作要继承不同的父夹具
完整框架
未完..