一、数据驱动
(一)什么是数据驱动
- 通过测试数据控制用例的执行,直接影响测试结果;
- 数据驱动是最好结合 PO+参数化技术使用。
(二)优点
数据驱动技术可以将用户把关注点放在对测试数据的构建和维护上,而不是直接维护脚本,可以利用同样的过程对不同的数据输入进行测试。
(三)常用数据格式
- JSON
- XML
- EXCEL
- CSV
- TXT
二、JSON
(一)什么是JSON
JSON的全称是”JavaScript Object Notation”,是JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式。
(二)JSON语法规则
- 数据由键值对表示
- 数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
- 可以相互嵌套
注:语法规则与Python字典一致。
(三)python字典与JSON之间的转换
- 字典转为 json 字符串
方法:dumps()
操作:
① 导包 import json;
② 调用 dumps 方法。
注:使用 dumps 方法,而不是 dump 方法。
import json
data = {
'id': 1,
'name': 'Tom',
'address': '北京市海淀区',
'school': None
}
json_str = json.dumps(data)
print(type(json_str))
- json 字符串转字典
方法: loads()
操作:
① 导包 import json;
② 调用 loads 方法。
注:
使用 loads 方法而不是 load 方法;
字符串中的键名必须使用双引号。
import json
json_str = '{"id": 1, "name": "Tom", "address": "北京市海淀区", "school": null}'
dict_data = json.loads(json_str)
print(type(dict_data))
(四)JSON文件读写
- 写入 json
方法:dump(写什么数据, 往哪写)
操作:
① 导包 import json;
② 获取文件流 f,并调用 dump 方法写入。
注意:
① 写入时模式 w;
② 写入的方法 dump() 而不是 dumps();
③ ensure_ascii:设置编码格式-解决中文问题。
import json
param = {'name': 'tom', 'age': 20}
with open('data.json', 'w', encoding='UTF-8') as f:
json.dump(param, f)
- json 字符串转字典
方法: load(文件名)
操作:
① 导包 import json;
② 获取文件流 f,并调用 load 方法读取。
注:
① 写入时模式 r;
② 写入的方法 load() 而不是 loads()。
import json
with open('data.json', encoding='UTF-8') as f:
data = json.load(f) # 返回的数据类型为字典或列表
三、实例
对网页计算器,进行加法的测试操作。通过读取数据文件中的数据来执行用例。
网址:http://cal.apple886.com/
(一)实现步骤
- 采用PO模式的分层思想对页面进行封装
- 编写测试脚本
- 使用参数化传入测试数据
- 把测试数据定义到JSON数据文件中
(二)代码结构图
(三)代码
- 对象库层:base.py
"""base.py"""
# -*-coding:utf-8 -*-
# Auothor:yue_luo
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):
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_value(self,loc):
return self.base_find_element(loc).get_attribute("value")
def base_get_img(self):
self.driver.get_screenshot_as_file("./{}.png".format(time.strftime("%Y_%m_%d_%H_%M_%S")))
"""get_driver.py"""
# -*-coding:utf-8 -*-
# Auothor:yue_luo
from selenium import webdriver
from PO import page
class GetDriver:
driver = None
@classmethod
def get_driver(cls):
if cls.driver == None:
cls.driver = webdriver.Chrome()
cls.driver.maximize_window()
cls.driver.get(page.url)
return cls.driver
@classmethod
def quit_driver(cls):
if cls.driver:
cls.driver.quit()
"""置空,一定要置空"""
cls.driver = None
- 操作层:_ _init _ _.py 和 page_login.py
"""__init__.py"""
# -*-coding:utf-8 -*-
# Auothor:yue_luo
from selenium.webdriver.common.by import By
"""以下为服务器域名配置地址"""
url ="http://cal.apple886.com/"
"""以下为登录页面配置信息"""
# cal_num = By.CSS_SELECTOR,"#simple"
cal_add = By.CSS_SELECTOR,"#simpleAdd"
cal_eq = By.CSS_SELECTOR,"#simpleEqual"
cal_result = By.CSS_SELECTOR,"#resultIpt"
cal_clear = By.CSS_SELECTOR,"#simpleClearAllBtn"
"""page_cal.py"""
# -*-coding:utf-8 -*-
# Auothor:yue_luo
from time import sleep
from PO import page
from PO.base.base import Base
from selenium.webdriver.common.by import By
class PageCal(Base):
def page_click_num(self,num):
s = By.CSS_SELECTOR ,"#simple2"
self.base_find_element(s)
for n in str(num):
loc = By.CSS_SELECTOR,"#simple{}".format(n)
self.base_click(loc)
def page_click_add(self):
self.base_click(page.cal_add)
def page_click_eq(self):
self.base_click(page.cal_eq)
def page_get_value(self):
return self.base_get_value(page.cal_result)
def page_click_clear(self):
self.base_click(page.cal_clear)
def page_get_img(self):
self.base_get_img()
def page_add_cal(self,a,b):
self.page_click_num(a)
sleep(0.5)
self.page_click_add()
self.page_click_num(b)
sleep(0.5)
self.page_click_eq()
sleep(0.5)
- 业务层:test_login.py
"""test_cal.py"""
# -*-coding:utf-8 -*-
# Auothor:yue_luo
import unittest
from PO.base.get_driver import GetDriver
from PO.page.page_cal import PageCal
from parameterized import parameterized
from PO.tool.read_json import read_json
def get_data():
data = read_json("cal.json")
# print(data)
"""
期望数据格式:[(1234, 1234, 2468), (1, 2, 3), (123445, 223265, 32626)]
"""
list = []
for n in data.values():
list.append((n["a"], n["b"], n["expect_result"]))
return list
class TestCal(unittest.TestCase):
# driver = None
@classmethod
def setUpClass(cls):
cls.driver = GetDriver().get_driver()
cls.cal = PageCal(cls.driver)
@classmethod
def tearDownClass(cls):
GetDriver().quit_driver()
@parameterized.expand(get_data())
def test_add_cla(self,a,b,expect_result):
self.cal.page_add_cal(a,b)
result =self.cal.page_get_value()
print("result:",result)
print("ex_result:",expect_result)
#136465446
try:
self.assertEqual(result,str(expect_result))
except:
self.cal.page_get_img()
raise
finally:
self.cal.page_click_clear()
- 数据(cal.json)
{
"cal_001":{"a":1,"b":2,"expect_result":3},
"cal_004":{"a":1,"b":22,"expect_result":23},
"cal_005":{"a":1,"b":23,"expect_result":24},
"cal_006":{"a":1,"b":42,"expect_result":43},
"cal_008":{"a":1,"b":52,"expect_result":53},
"cal_007":{"a":1,"b":522,"expect_result":523},
"cal_002":{"a":123445,"b":223265,"expect_result":32626},
"cal_003":{"a":1234,"b":1234,"expect_result":2468}
}
- 工具类(read_json.py)
import json
def read_json(filename):
filepath ="../data/"+ filename
with open(filepath,"r",encoding="utf8") as f:
return json.load(f)