V1顺序型:不能批量运行
import unittest
from selenium import webdriver
from time import sleep
driver = webdriver.Edge()
# driver.maximize_window()
driver.implicitly_wait(30)
# driver.get(r"https://demo5.tp-shop.cn/")
# driver.find_element_by_partial_link_text("登录").click()
driver.get("https://demo5.tp-shop.cn/Home/user/login.html")
driver.find_element_by_css_selector("#username").send_keys("15217578333")
driver.find_element_by_css_selector("#password").send_keys("123456")
driver.find_element_by_css_selector("#verify_code").send_keys("AUWR")
driver.find_element_by_css_selector(".J-login-submit").click()
msg = driver.find_element_by_css_selector(".layui-layer-content").text
print(msg)
assert "账号不存在" == msg
driver.find_element_by_css_selector(".layui-layer-btn0").click()
sleep(2)
driver.quit()
assert "密码不存在" == msg
driver.find_element_by_css_selector(".layui-layer-btn0").click()
sleep(2)
driver.quit()
Unittest:代码冗余 业务脚本与页面对象没有分开
import unittest
from selenium import webdriver
from time import sleep
class TestLogin(unittest.TestCase):
driver = None
def tearDown(self):
self.driver.refresh()
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Edge()
# driver.maximize_window()
cls.driver.implicitly_wait(30)
# cls.driver.get(r"https://demo5.tp-shop.cn/")
# cls.driver.find_element_by_partial_link_text("登录").click()
cls.driver.get(r"https://demo5.tp-shop.cn/Home/user/login.html")
@classmethod
def tearDownClass(cls):
sleep(2)
cls.driver.quit()
def test_login_username_not_exist(self):
driver = self.driver
driver.find_element_by_css_selector("#username").send_keys("15217578333")
driver.find_element_by_css_selector("#password").send_keys("123456")
driver.find_element_by_css_selector("#verify_code").send_keys("AUWR")
driver.find_element_by_css_selector(".J-login-submit").click()
msg = driver.find_element_by_css_selector(".layui-layer-content").text
print(msg)
try:
self.assertEqual("用户不存在", msg)
driver.find_element_by_css_selector(".layui-layer-btn0").click()
except AssertionError:
self.driver.get_screenshot_as_file("../image/not_exist.png")
# raise
def test_login_password_err(self):
driver = self.driver
driver.find_element_by_css_selector("#username").send_keys("15217578333")
driver.find_element_by_css_selector("#password").send_keys("123456")
driver.find_element_by_css_selector("#verify_code").send_keys("AUWR")
driver.find_element_by_css_selector(".J-login-submit").click()
msg = driver.find_element_by_css_selector(".layui-layer-content").text
print(msg)
try:
self.assertEqual("密码错误",msg)
driver.find_element_by_css_selector(".layui-layer-btn0").click()
except AssertionError:
self.driver.get_screenshot_as_file("../image/error.png")
# raise
V3 PO page object 冗余代码 耦合性太强
#page
from selenium import webdriver
class PageLogin:
def __init__(self):
self.driver = webdriver.Edge()
# driver.maximize_window()
self.driver.implicitly_wait(30)
# driver.get(r"https://demo5.tp-shop.cn/")
# driver.find_element_by_partial_link_text("登录").click()
self.driver.get(r"https://demo5.tp-shop.cn/Home/user/login.html")
# 点击登录
def page_click_login_link(self):
pass
# 输入用户名
def page_input_username(self,username):
self.driver.find_element_by_css_selector("#username").send_keys(username)
# 输入密码
def page_input_pwd(self,password):
self.driver.find_element_by_css_selector("#password").send_keys(password)
# 输入验证码
def page_input_vertify_code(self,code):
self.driver.find_element_by_css_selector("#verify_code").send_keys(code)
# 点击登录
def page_click_login_btn(self):
self.driver.find_element_by_css_selector(".J-login-submit").click()
# 获取异常提示信息
def page_get_text(self):
return self.driver.find_element_by_css_selector(".layui-layer-content").text
# 点击提示框确认按钮
def page_click_err_btn_ok(self):
self.driver.find_element_by_css_selector(".layui-layer-btn0").click()
# 组装业务登录方法、给业务层调用
def page_login(self,username,password,code):
self.page_click_login_link()
self.page_input_username(username)
self.page_input_pwd(password)
self.page_input_vertify_code(code)
self.page_click_login_btn()
#业务层
import unittest
from v3.page.page_login import PageLogin
from parameterized import parameterized
from time import sleep
class TestLogin(unittest.TestCase):
def setUp(self):
# 获取登录页面对象
self.login = PageLogin()
def tearDown(self):
self.login.driver.quit()
@parameterized.expand([("13822223333","123456","8888","账号不存在"),("13822223333","1236","8888","密码错误")])
def test_login(self,username,password,code,expect):
self.login.page_login(username,password,code)
msg = self.login.page_get_text()
try:
self.assertEqual(expect,msg)
self.login.page_click_err_btn_ok()
except AssertionError:
self.login.driver.get_screenshot_as_file("../../image/login_error%s.png" % (time.strftime("%Y_%m_%d %H_%M_%S")))
# raise
PO page object 页面 对象
V4 三层结构 base page scripts
base(基类)page页面中一些公共的方法 即抽取公共方法放到base中 (提取方法)
新建Base类 初始化方法 查找元素方法 点击元素方法 输入方法 获取文本方法 截图方法(调用数据)
page(页面对象)一个页面封装成一个对象 通过继承base类 使用其中的公共方法(实现使用)
scripts(业务层 脚本层 )导包调用page页面
from selenium.webdriver.common.by import By
loc = (By.CSS_SELECTOR,".telA")
# loc = By.CSS_SELECTOR,".telA" 也是元组类型
# driver.find_element(By.CSS_SELECTOR,".telA")
print(loc)
# 解包
print(*loc)
# ('css selector', '.telA')
# css selector .telA
包和文件夹 包多了init文件
# base
from selenium.webdriver.support.wait import WebDriverWait
import time
from selenium import webdriver
class Base:
# 临时替代
# def __init__(self, driver):
# self.driver = driver
def __init__(self):
self.driver = webdriver.Edge()
self.driver.get(r"https://demo5.tp-shop.cn/")
# 解包只需一次 driver传入即可 loc就是查找元素使用的
# 查找元素方法(提供:点击,输入,获取文本)使用
def base_find_element(self, loc,timeout=30,poll=0.5): # loc 元组 *loc进行解包
# 显示等待
return WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll).until(lambda x: x.find_element(*loc))
# 点击方法 调用时只需要输入点击哪个元素
def base_click(self,loc):
self.base_find_element(loc).click()
# 输入方法 调用时只需要两个参数 哪个元素 输什么内容
def base_input(self,loc,value):
el = self.base_find_element(loc)
el.clear()
el.send_keys(value)
# 获取文本方法 哪个元素文本
def base_get_text(self,loc):
# 一定要返回元素的文本信息
return self.base_find_element(loc).text
# 截图方法
def base_get_image(self):
self.driver.get_screenshot_as_file("../../image/login_error%s.png" % (time.strftime("%Y_%m_%d %H_%M_%S")))
# page init
from selenium.webdriver.common.by import By
# 登录页面元素配置信息 临时存放地
# 登录链接
login_link = By.PARTIAL_LINK_TEXT, "登录"
# 用户名
login_username = By.ID, "username"
# 密码
login_password = By.ID, "password"
# 验证码
login_verify = By.ID, "verify_code"
# 登录按钮
login_btn = By.CSS_SELECTOR, ".J-login-submit"
# 获取异常文本信息
login_err = By.CSS_SELECTOR, ".layui-layer-content"
# 点击异常提示框文本按钮
login_err_btn_ok = By.CSS_SELECTOR, ".layui-layer-btn0"
#page page_login
from v4 import page
from v4.base.base import Base
class PageLogin(Base):
# 点击登录按钮
def page_click_login_lin(self):
self.base_click(page.login_link)
# 输入用户名
def page_input_username(self,username):
self.base_input(page.login_username,username)
# 输入密码
def page_input_password(self,password):
self.base_input(page.login_password,password)
# 输入验证码
def page_input_vertfy_code(self,code):
self.base_input(page.login_verify,code)
# 点击登录按钮
def page_click_login_btn(self):
self.base_click(page.login_btn)
# 获取提示框文本信息
def page_get_err_info(self):
return self.base_get_text(page.login_err)
# 点击提示框确定按钮
def page_click_err_btn_ok(self):
self.base_click(page.login_err_btn_ok)
# 截图
def page_get_image(self):
self.base_get_image()
# 组装业务登录方法、给业务层调用
def page_login(self,username,password,code):
self.page_input_username(username)
self.page_input_password(password)
self.page_input_vertfy_code(code)
self.page_click_login_btn()
# scripts 业务层
import unittest
from v4.page.page_login import PageLogin
from selenium import webdriver
from parameterized import parameterized
def get_data():
return [("13822223333","123456","8888","账号不存在"),
("13822223333","1236","8888","密码错误")]
class Test_login(unittest.TestCase):
login = None
@classmethod
def setUpClass(cls):
cls.login = PageLogin()
cls.login.page_click_login_lin()
@classmethod
def tearDownClass(cls):
cls.login.driver.quit()
def tearDown(self):
self.login.driver.refresh()
@parameterized.expand(get_data())
def test_login(self,username,password,code,expect):
self.login.page_login(username,password,code)
msg = self.login.page_get_err_info()
try:
self.assertEqual(expect,msg)
self.login.page_click_err_btn_ok()
except AssertionError:
self.login.page_get_image()
# raise
单例模式:无论实例化多少对象 获取的同一个对象
用处:获取浏览器 都是一个
PO模式分层:面向对象思想 对象库层 操作层 业务层
就是进行三层代码的封装
列表也行 就是麻烦一点 list[0] list[1] 元组直接解包即可
dumps带s时转换 不带s是写json
dumps() 将字典转换成json字符串
json中dump()写入json
loads() 将字符串转为字典
load() 读取json方法
import json
# 将字典转换为json字符串
data = {"name":"小明","age":18}
print(type(data)) # <class 'dict'>
data = json.dumps(data)
print(type(data)) # <class 'str'>
print(data)
# {"name": "\u5c0f\u660e", "age": 18} 序列化
# 将字符串转为json
data = '{"name":"小明","age":18}' #属性:双引号
print(type(data)) # <class 'str'>
data = json.loads(data)
print(type(data)) # <class 'dict'>
print(data) # {'name': '小明', 'age': 18} 变成单引号了
JSON文件读写
ctrl+p 查看需要参数
加法测试项目V4PO加数据驱动
Base
base.py Base
from selenium import webdriver
from case_add import page
class GetDriver:
# 设置类属性
driver = None
# 获取driver
@classmethod
def get_driver(cls):
if cls.driver is None:
# 实例化浏览器
cls.driver = webdriver.Edge()
# 最大化
cls.driver.maximize_window()
# 打开浏览器
cls.driver.get(page.url)
return cls.driver
@classmethod
def quit_driver(cls):
if cls.driver:
print("关闭之前:", cls.driver)
cls.driver.quit()
print("关闭之后:", cls.driver)
cls.driver = None
print("置空之后:", cls.driver)
if __name__ == '__main__':
# 第一次获取浏览器
print(GetDriver().get_driver())
# 第二次获取浏览器
print(GetDriver().get_driver())
# 调用关闭,测试 关闭后driver是否为None
GetDriver().quit_driver()
print(GetDriver().get_driver())
虽然是同一个浏览器网址 但是将driver置空后
每次获取浏览器是一个全新的浏览器实例
为了确保在下次获取浏览器时可以重新实例化一个新的浏览器对象,而不是继续使用之前关闭的浏览器对象。
from selenium.webdriver.support.wait import WebDriverWait
import time
class Base:
# 初始化方法
def __init__(self, driver):
self.driver = driver
# 查找元素
def base_find_element(self, loc, timeout=30, poll=0.5):
"""
:param loc: 元素的定位信息,格式为元祖
:param timeout: 默认超时时间30秒
:param poll: 访问频率,默认0.5查找一次元素
:return: 返回查找到的元素
"""
# 显示等待
return WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll).until(lambda x: x.find_element(*loc))
# 点击
def base_click(self, loc):
self.base_find_element(loc).click()
# 获取value属性方法封装
def base_get_element_text(self, loc):
# 使用get_attribute()方法获取指定的元素属性值
# 注意:返回
return self.base_find_element(loc).get_attribute("value")
# 截图
def base_get_screen_shot(self):
self.driver.get_screenshot_as_file("../../image/{}.png".format(time.strftime("%Y_%m_%d %H_%M_%S")))
Page
init.py
from selenium.webdriver.common.by import By
"""以下为服务器域名配置地址"""
url = r"http://cal.apple886.com/"
"""以下为计算器配置数据"""
# number = By.CSS_SELECTOR,"#simple{}"
calc_add = By.CSS_SELECTOR,"#simpleAdd"
calc_equal = By.CSS_SELECTOR,"#simpleEqual"
calc_get_result = By.CSS_SELECTOR,"#resultIpt"
calc_clear = By.CSS_SELECTOR,"#simpleClearAllBtn"
num = "12345342"
for i in num:
print("simple{}".format(i))
Page_calc.py 继承Base
PageCalc
from selenium.webdriver.common.by import By
from case_add.base.base import Base
from case_add import page
class PageCalc(Base):
def page_num_click(self, num):
for i in str(num):
loc = By.CSS_SELECTOR, "#simple{}".format(i)
self.base_click(loc)
def page_add_btn(self):
self.base_click(page.calc_add)
def page_equal_btn(self):
self.base_click(page.calc_equal)
def page_get_result(self):
return self.base_get_element_text(page.calc_get_result)
def page_clear(self):
self.base_click(page.calc_clear)
def page_get_screen_shot(self):
self.base_get_screen_shot()
def page_calc(self, num1, num2):
self.page_num_click(num1)
self.page_add_btn()
self.page_num_click(num2)
self.page_equal_btn()
数据驱动
import json
def read_json(filename):
filepath = "../data/"+ filename
with open(filepath,"r",encoding="utf-8") as f:
return json.load(f)
if __name__ == '__main__':
data = read_json("calc.json")
# print(data)
# print("---" * 50)
list1 = []
for i in data.values():
list1.append((i.get('a'),i.get('b'),i.get('expect')))
print(list1)
业务层
import unittest
from case_add.tool.read_json import read_json
from case_add.base.get_driver import GetDriver
from case_add.page.page_calc import PageCalc
from parameterized import parameterized
def get_data():
data = read_json("calc.json")
arr = []
for i in data.values():
arr.append((i.get('a'), i.get('b'), i.get('expect')))
return arr
class TestCal(unittest.TestCase):
driver = None
@classmethod
def setUpClass(cls):
cls.driver = GetDriver.get_driver()
cls.calc = PageCalc(cls.driver)
@classmethod
def tearDownClass(cls):
GetDriver.quit_driver()
@parameterized.expand(get_data())
def test_calc(self,num1,num2,expect):
self.calc.page_calc(num1,num2)
result = self.calc.page_get_result()
try:
self.assertEqual(str(expect),str(result))
self.calc.page_clear()
except AssertionError:
self.calc.base_get_screen_shot()
raise
正向和逆向用例是在软件测试中常用的概念。正向用例是使用软件时的预期行为,即用户按照设计好的流程和功能来操作软件系统,以测试系统是否按照预期的方式工作。而逆向用例则是用来测试系统对不符合预期情况的处理能力,即人为制造一些异常情况或错误操作,看系统如何响应。