selenium某些元素定位+unittest、pytest用法、allure

1、selenium4.4的版本没有find_element_by_id等用法了
换成了find_element和find_elements

测试本地文件:
driver=webdriver.Chrome()
path=os.path.dirname(os.path.abspath(__file__)) #如果还有上层,再套一层os.path.dirname()
file_path='file:///'+path+'/xx.html'
driver.get(file_path)

复选框选中示例:checkbox
#is_selected是否被选中,返回true选中 male
=driver.find_element(By.NAME,'male') if not male.is_selected(): male.click() 单选框选中示例:radio,具有排他性,只能执行一个个选,操作方法与复选框类似 下拉列表操作

 


 

from selenium.webdriver.support.select impot Select

#下拉单单选
se=driver.find_element(By.id,'idname')
sel=Select(se)
sel.select_by_index(2) #第三个
time.sleep(2)
sel.select_by_value('bj')
time.sleep(2)
sel.select_by_visible_text('shanghai')

#下拉框多选
for i in range(3):
    sel.select_by_index(i)
    time.sleep(1)
time.sleep(3)
#反选,选中多个后取消选中
sel.deselect_all()
time.sleep(3)

#打印下拉框所有选项值
for option in sel.options:
    print(option)


弹窗处理、用法
1、alert  用来提示
2、confirm 用来确认
3、prompt  输入内容

#方法属性
1、accept()  接受
2、dismiss() 取消
3、text  显示的文本
4、send_keys  输入内容

#alert处理
driver.find_element(By.ID,'alert').click()
#切换到alert
alert=driver.switch_to.alert
print(alert.text)
time.sleep(3)
alert.accept()

#confirm处理
driver.find_element(By.ID,'confirm').click()
confirm=driver.switch_to.alert
print(confirm.text)
time.sleep(3)
confirm.accept() #确认
confirm.dismiss() #取消

#prompt处理
driver.find_element(By.ID,'prompt').click()
time.sleep(2)
prompt=driver.switch_to.alert
print(prompt.text)
time.sleep(2)
prompt.accept()
time.sleep(2)



selenium三种等待方式
1、time.sleep,调试的时候可以用,但在实际开发自动化框架中不建议用 
2、implicitly_wait隐式等待,全局有效,最长等待时间,在规定时间内网页加载完成则执行下一步,
否则一直等到时间结束,然后执行下一步。只要设置一次就可以
3、WebDriverWait显示等待,等待单个的元素加载,通常配合until()until_not()方法使用。
from selenium.webdriver.support.wait impo WebDriverWait


WebDriverWait的参数:
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)

driver:浏览器驱动

timeout:最长超时时间,默认以秒为单位

poll_frequency:检测的间隔步长,默认为0.5s

ignored_exceptions:超时后的抛出的异常信息,默认抛出NoSuchElementExeception异常。

这个模块一共只有2个方法until、until_not:
method: 在等待期间,每隔一段时间(__init__中的poll_frequency)调用这个传入的方法,直到返回值不是False
message: 如果超时,抛出TimeoutException,将message传入异常

示例:
time.sleep #线程阻塞blocking wait
driver.implicitly_wait(10) #最长10s找不到进入下一步

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait impo WebDriverWait
wait=WebDriverWait(driver,5) #5s超时
wait.until(EC.title_is('百度一下')) #找到了title再进行下一步



Selenium等待条件
from selenium.webdriver.support import expected_conditions as EC

例如:
wait=WebDriverWait(driver,5) #5s超时
wait.until(EC.text_to_be_present_in_element(By.id,'id1'),'id 1')
print(driver.find_element(By.ID,'id 1').text)
print('ok')



鼠标和键盘事件
右击,双击,拖动等操作,这些操作包含在ActionChains类
#正确使用方法
ActionChains(driver).click(btn).perfmon()下面列出的ActionChains常用方法

 


 



示例:
from selenium.webdriver import ActionChains, Keys

driver.get('https://sahitest.com/demo/clicks.htm')
#双击
btn=driver.find_element(By.XPATH,'/html/body/form/input[2]')
ActionChains(driver).double_click(btn).perform()
#单击
btn=driver.find_element(By.XPATH,'/html/body/form/input[3]')
ActionChains(driver).click(btn).perform()
#右击
btn=driver.find_element(By.XPATH,'/html/body/form/input[4]')
ActionChains(driver).context_click(btn).perform()

#键盘
driver.get('https://www.baidu.com')
kw=driver.find_element(By.ID,'kw')
kw.send_keys('selenium')
#复制、剪切、粘贴
kw.send_keys(Keys.CONTROL,'a')
kw.send_keys(Keys.CONTROL,'x')
kw.send_keys(Keys.CONTROL,'v')
#鼠标移到某个元素
e=driver.find_element(By.ID,'tj_login')
ActionChains(driver).move_to_element(e).click(e).perform()


selenium执行js脚本
有两个方法,分别是:
1、execute_script 同步执行
2、execute_async_script 异步执行
通过js通常可以实现页面滚动

#执行js方法和技巧
#加js弹出框
driver.get('https://www.baidu.com')
driver.execute_script('alert'('test'))
sleep(2)
driver.switch_to.alert.accept()

#打印页面title
js='return document.title'
title=driver.execute_script(js)
print(title)

#变更输入框颜色
driver.find_element(By.ID).send_keys('selenium')
driver.find_element(By.ID).click()
sleep(2)
js='var a=document.getElementById("ke");q.style.border="2px solid red"'
driver.execute_script(js)
sleep(2)


selenium屏幕截屏

 


 

#保存图片
st= time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime(time()))
file_name=st+'.png'
#按日期命名图片
driver.save_screenshot(file_name)
#保存到文件夹
path=os.path.abspath('screenshot')
file_path=path+'/'+file_name
driver.get_screenshot_as_file(file_path)


selenium定位frame、iframe
frame标签有frameset、frame、iframe三种,frameset跟其他普通标签没有区别,不会影响到正常的定位,而frame
与iframe对selenium定位而言是一样的,selenium有一组方法对frame进行操作
#frame定位
driver.get('https://sahitest.com/demo/framesTest.htm')
top=driver.find_element(By.NAME,'top')
driver.switch_to.frame(top)
driver.find_element(By.XPATH,'/html/body/table/tbody/tr/td[1]/a[1]').click()
sleep(3)
#找第二个frame
#跳出,再切到另一个frame里去操作
driver.switch_to.default_content()
second=driver.find_element(By.XPATH,'/html/frameset/frame[2]')
driver.find_element(By.XPATH,'/html/body/table/tbody/tr/td[1]/a[2]').click()


协议勾选定位不到用PyAutoGUI组件通过坐标定位
pip install pyautogui
import pyautogui
from selenium.webdriver.common.by import By


def test1():
    driver=webdriver.Chrome()
    driver.get('https://testerhome.com/account/sign_up')
    driver.maximize_window()
    sleep(1)
    elem=driver.find_element(By.CLASS_NAME,'custom-control-label')
    r1=elem.rect
    pyautogui.moveTo(r1['x']+10,r1['y']+130)
    pyautogui.click()
sleep(3)


Selenium断言方法
断言方法:
assertEqual(a, b, [msg='测试失败时打印的信息'])       # a == b    断言a和b是否相等,相等则测试用例通过

assertNotEqual(a,b,[msg='测试失败时打印的信息'])      # a != b    断言a和b是否相等,不相等则测试用例通过

assertTrue(x,[msg='测试失败时打印的信息'])            # x is True  断言x是否True,是True则测试用例通过

assertFalse(x,[msg='测试失败时打印的信息'])           # x is False  断言x是否False,是False则测试用例通过

assertIn(a,b,[msg='测试失败时打印的信息'])            # a in b    断言a是否在b中,在b中则测试用例通过

assertNotIn(a,b,[msg='测试失败时打印的信息'])         # a not in b    断言a是否在b中,不在b中则测试用例通过

assertIsNone(x,[msg='测试失败时打印的信息'])          # x is None 断言x是否None,是None则测试用例通过

assertIsNotNone(x,[msg='测试失败时打印的信息'])       # x not is None 断言x是否None,不是None则测试用例通过

assertIs(a,b,[msg='测试失败时打印的信息'])            # a is b    断言a是否是b,是则测试用例通过

assertNotIs(a,b,[msg='测试失败时打印的信息'])         # a not is b    断言a是否是b,不是则测试用例通过

assertIsInstance(a,b,[msg='测试失败时打印的信息'])      # 断言a是是b的一个实例,是则测试用例通过

assertNotIsInstance(a,b,[msg='测试失败时打印的信息'])   # 断言a是是b的一个实例,不是则测试用例通过


selenium获取文本的方法

element=driver.find_element(By.XPATH, '//*[@class="el-form-item__error"]')])
1.element.text
2.get_attribute(“textContent”)
优点:可以获取隐藏元素的文本

缺点:IE不支持;获取有些元素的文本时,结果中带有空字符串;(没有尝试过)

3.get_attribute("innerText")
优点:可以获取隐藏元素的文本

缺点:FireFox不支持;(每个博客能搜到的都说这个缺点,但我实际操作发现可以获取到每次所需的文本)





示例:
from selenium.webdriver.common.by import By

driver.find_element(By.XPATH,'//button[text()="Some Text"]')
driver.find_elements(By.XPATH,'//button')


2、元素重复时,找上一层即父类的class元素
username_el1=driver.find_elements(By.CLASS_NAME,'form-group')[1] #先找父类的元素,父类元素在第2个值即1
username_el2=username_el1.find_element(By.CLASS_NAME,'form-control') #再找父类下的元素,默认取第一个值0
username_el2.send_keys('css') #最后发送值


3、#找元素返回true或false,3s找不到就关闭
locate=(By.CLASS_NAME,'form-group')
WebDriverWait(driver,3).until(EC.visibility_of_element_located(locate))
driver.close()


4、打印文本框的值,输出文本框的值和send_keys的值
username_ele=driver.find_element(By.ID,'user_name')
#文本框的默认值
print(username_ele.get_attribute('placeholder'))
username_ele.send_keys('css')
#打印文本框的值,默认用value字段
print(username_ele.get_attribute('value'))


5、随机生成用户名、邮箱等信息
import random

for i in range(5):
    #random.sample('123456sjsldhh',5)生成的是列表,要转成字符串
    user_login=''.join(random.sample('123456sjsldhh',5))
    user_email=''.join(random.sample('123456sjsldhh',5))+'@123.com'
    # print(user_login)
    # print(user_email)
#调用随机生成的用户名和邮箱
driver.find_element(By.ID,'user_login').send_keys(user_login)
driver.find_element(By.ID,'user_email').send_keys(user_email)


6、解决验证码
思路:保存验证码图片后,用工具解析
安装库:pip install Pillow、pip install pytesseract
from PIL import Image

#1、先将整张图保存,命名
driver.save_screenshot('E:\img\wyt.png')
#2、定位到验证码元素
code_ele=driver.find_element(By.CLASS_NAME,'rucaptcha-image')
#3、打印验证码元素位置坐标
print(code_ele.location) #{'x': 338, 'y': 721}
#4、获取验证码的坐标
left=code_ele.location['x']
top=code_ele.location['y']
right=code_ele.size['width']+left
height=code_ele.size['height']+top
#5、保存截取的坐标图
im=Image.open('E:\img\wyt.png')
img=im.crop((left,top,right,height))
img.save('E:\img\wyt1.png')

#6、解析验证码图片,只能解析有规则的验证码,带下划线等干扰的验证码不能识别
#coding=utf-8
import pytesseract
from PIL import Image

image=Image.open('E:\img\wyt1.png')
code_text=pytesseract.image_to_string(image)
print(code_text)

#7、识别有干扰的验证码
借用第三方做好的识别api调用,需要付费


#8、muggle-ocr 识别验证码库
安装库:pip install muggle-ocr -i https://mirrors.aliyun.com/pypi/simple/

说明

1、muggle_ocr是一款轻量级的ocr识别库,对于python来说是识别率较高的图片验证码模块。

2、主要用于识别各种类型的验证码,一般文字提取效果稍差。

实例:
import muggle_ocr
# 初始化sdk;model_type 包含了 ModelType.OCR/ModelType.Captcha 两种模式,分别对应常规图片与验证码
sdk = muggle_ocr.SDK(model_type=muggle_ocr.ModelType.Captcha)
 
with open(r"d:\Desktop\四位验证码.png", "rb") as f:
    img = f.read()
 
text = sdk.predict(image_bytes=img)
print(text)


相关实例扩展:
import time

# 1. 导入包
import muggle_ocr

"""
使用预置模型,预置模型包含了[ModelType.OCR, ModelType.Captcha] 两种
其中 ModelType.OCR 用于识别普通印刷文本, ModelType.Captcha 用于识别4-6位简单英数验证码

"""

# 打开印刷文本图片
with open(r"test1.png", "rb") as f:
    ocr_bytes = f.read()

# 打开验证码图片
with open(r"test2.jpg", "rb") as f:
    captcha_bytes = f.read()

# 2. 初始化;model_type 可选: [ModelType.OCR, ModelType.Captcha]
sdk = muggle_ocr.SDK(model_type=muggle_ocr.ModelType.OCR)

# ModelType.Captcha 可识别光学印刷文本
for i in range(5):
    st = time.time()
    # 3. 调用预测函数
    text = sdk.predict(image_bytes=ocr_bytes)
    print(text, time.time() - st)

# ModelType.Captcha 可识别4-6位验证码
sdk = muggle_ocr.SDK(model_type=muggle_ocr.ModelType.Captcha)
for i in range(5):
    st = time.time()
    # 3. 调用预测函数
    text = sdk.predict(image_bytes=captcha_bytes)
    print(text, time.time() - st)

"""
使用自定义模型
支持基于 https://github.com/kerlomz/captcha_trainer 框架训练的模型
训练完成后,进入导出编译模型的[out]路径下, 把[graph]路径下的pb模型和[model]下的yaml配置文件放到同一路径下。
将 conf_path 参数指定为 yaml配置文件 的绝对或项目相对路径即可,其他步骤一致,如下示例:
"""
with open(r"test3.jpg", "rb") as f:
    b = f.read()
sdk = muggle_ocr.SDK(conf_path="./ocr.yaml")
text = sdk.predict(image_bytes=b)


uinttest的加载方法
 # 1、通过测试用例类加载、测试套件
    suite.addTests(loader.loadTestsFromTestCase(TestUnittest))
    suite.addTests(loader.loadTestsFromTestCase(TestUnittest02))

    #2、通过测试用例模板加载
    suite.addTest(loader.loadTestsFromModule(TestUnittest02))

    #3、通过路劲加载,推荐
    import os
    path=os.path.dirname(os.path.abspath(__file__))
    suite.addTest(loader.discover(path))

    runner=unittest.TextTestRunner()
    runner.run(suite)


pytest编写规则
1、测试文件以test开头(以test结尾也可以)
2、测试类以Test开头,并且不能带有init方法
3、测试函数以test开头
4、断言使用基本的assert即可


 


 

 

 

 

 

 

 


import pytest

class TestCase02(object):
    @pytest.mark.do
    def test01(self):
        print('测试1')
        self.add()

    #pytest函数命名要以test开头才会执行,或者其他函数调用执行
    def add(self):
        print('增加')

    @pytest.mark.undo
    def test02(self):
        print('测试2')

if __name__=='__main__':
    pytest.main(['test02.py'])


import pytest

'''pytest参数化处理:
使用参数化装饰器、解析列表、元组、字典等数据
'''
#列表
data=['123','456']

@pytest.mark.parametrize('pwd',data)
def test1(pwd):
    print(pwd)

#元组
data2=[
    (1,2,3), #或者[1,2,3]
    (4,5,6) #或者[4,5,6]
]

@pytest.mark.parametrize('a,b,c',data2)
def test2(a,b,c):
    print(a,b,c)

#字典
data3=(
    {
        'user':1,
        'pwd':2
    },
    {
        'age':1,
        'email':'111@dd.com'
    })

@pytest.mark.parametrize('dic',data3)
def test3(dic):
    print(dic)


data_1=[
    #id的值可以自定义,方便理解每个用例是干什么的即可
    pytest.param(1,2,3,id='(a+b):pass'),
    pytest.param(4,5,10,id='(a+b):fail')
]

def add(a,b):
    return a+b

class TestParametrize(object):

    @pytest.mark.parametrize('a,b,expect',data_1)
    def test_parametrize_1(self,a,b,expect):
        assert add(a,b) == expect



import pytest

@pytest.fixture()
def init():
    print('测试init')
    return 1

def test1(init):
    print('测试1')

def test2(init):
    print('测试2')

if __name__=='__main__':
    pytest.main(['-sv','test04.py'])


 


 

import pytest    
class TestCase(object):
    @classmethod
    def setup_class(cls):
        print('setup-class')

    @classmethod
    def teardown_class(cls):
        print('teardown-class')


    def test01(self):

        print('class-test01')

    def test02(self):
        print('class-test02')

def setup_function():
    print('setup_function')

def teardown_function():
    print('teardown_function')

def setup_module():
    print('setup module')

def teardown_module():
    print('teardown_module')

def test1():
    print('测试1')

def test2():
    print('测试2')

if __name__=='__main__':
pytest.main(['test04.py','-sv'])  


pytest allure生成测试报告
第一步安装:pip install allure-pytest
第二步下载:官网https://github.com/allure-framework/allure2/releases
之后要配置环境变量:下载的包可放任意位置,下载allure之后将bin路径配置到环境变量中,重启电脑
重新配置Java home路径(一定要注意编辑路径时看不到分号,保存完毕后分号就出来了,这个时候需要在新的文本框中重新配置路径)

 


 


问题:
cmd 下 ,输入:allure 点击【enter】 后 界面无如何显示并自动打开allure.py文件。如下图:
 
 解决方案:
1、先确定JDK 环境变量的配置是否正确
2、确定无误后,进入到D:\Program Files\allure-2.17.2\bin目录下,打开 PowerShell 界面,输入 allure.bat 发现可以正常输出相应的帮助信息
3、于是,在 cmd 界面中 输入 allure.bat 可以正常显示相应的帮助信息
在使用的过程中,用 allure.bat ;如:
注意:生成测试报告,必须在命令行执行
pytest --alluredir ./reports test02.py
allure.bat serve ./reports 启动allure 查看报告(没有问题的就用allure serve ./reports )


完整示例:
import pytest import allure @pytest.fixture(scope='session') def login(): print('用例先登录') @allure.step('步骤1:点xxx') def step_1(): print('1111') @allure.step('步骤2:点xxx') def step_2(): print('222') @allure.feature('编辑页面') class TestEditPage(): #编辑页面 @allure.story('这是一个xxx的用例') def test1(self,login): '''先登录,再去执行xxx''' step_1() step_2() print('xxx的用例') @allure.story('打开a的页面') def test2(self,login): '''先登录,再去执行''' print('a的页面') if __name__=='__main__': #注意:生成测试报告,必须在命令行执行 #pytest --alluredir ./reports test02.py #allure.bat serve ./reports 启动allure 查看报告 pytest.main(['--alluredir','./reports','test02.py'])

 


 

 

 

 


日志时间:
my_format='%(asctime)s-%(filename)s-%(module)s-%(lineno)d'

logging.basicConfig(
    filename='my.log',
    level=logging.INFO,
    format=my_format
)

logging.info('info')
logging.debug('debug')
logging.warning('warming')
logging.error('error')
logging.critical('critical')
最后写在my.log文件里


 

 

 

 

 

 

 

 

 

def get_logger():
    logger = logging.getLogger('mylogger')
    logger.setLevel(logging.DEBUG)

    all_path=os.path.dirname(os.path.dirname(__file__))+'\\logs\\all.txt'
    rf_handle = logging.handlers.TimedRotatingFileHandler(all_path, when='midnight', interval=1, backupCount=7,atTime=datetime.time(0, 0, 0, 0))
    rf_handle.setFormatter(logging.Formatter('%(asctime)s-%(levelname)s-%(message)s'))

    err_path=os.path.dirname(os.path.dirname(__file__))+'\\logs\\error.txt'
    f_handle = logging.FileHandler(err_path,encoding='utf-8')
    f_handle.setLevel(logging.ERROR)
    f_handle.setFormatter(logging.Formatter('%(asctime)s-%(levelname)s-%(filename)s[:%(lineno)d]-%(message)s'))

    logger.addHandler(rf_handle)
    logger.addHandler(f_handle)
return logger



DDT参数化
import pytest,csv
# import warnings
# warnings.filterwarnings("ignore", category=DeprecationWarning)

#读取csv文件
def get_data():
    with open('test.csv','r') as f:
        lst=csv.reader(f)
        mydata=[]
        for row in lst:
            #extend() 函数用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
            mydata.extend(row)
        return mydata

@pytest.mark.parametrize('name',get_data())
def test1(name):
    print(name)

if __name__== '__main__':
    # get_data()
pytest.main(['-sv','test_csv.py'])



import pytest
import json

def get_data():
    with open('data_json.json','r') as f:
        lst=[]
        data=json.load(f)
        lst.extend(data['keys'])
        return lst

@pytest.mark.parametrize('name',get_data())
def test1(name): #遍历
    print(name)

if __name__ == '__main__':
    # print(get_data())
    pytest.main(['-sv','test_json.py'])



import pytest
import xlrd

def get_data():
    filename='test.xls'
    wb=xlrd.open_workbook(filename)
    sheet=wb.sheet_by_index(0)
    rows=sheet.nrows
    cols = sheet.ncols
    lst=[]
    for row in range(rows):
        for col in range(cols):
            cell_data=sheet.cell_value(row,col)
            lst.append(cell_data)
    return lst

@pytest.mark.parametrize('name',get_data())
def test1(name):
    print(name)

if __name__ == '__main__':
pytest.main(['-sv','test_excel.py'])



1、安装mysql服务,mysql里建库建表
2、pip install mysqlclient
import MySQLdb
import pytest

conn=MySQLdb.connect(
    user = 'root',
    passwd='123456',
    host='localhost',
    port=3306,
    db='test_db'
)

def get_data():
    query_sql='select id,username,pwd from user_tbl'
    lst=[]
    try:
        cursor=conn.cursor() #获取游标
        cursor.execute(query_sql)
        r=cursor.fetchall()
        for x in r:
            u=(x[0],x[1],x[2]) #0、1、2代表的是id,username,pwd
            lst.append(u)
        return lst
    finally:
        cursor.close()
        conn.close()

@pytest.mark.parametrize('id,name,pwd',get_data())
def test1(id,name,pwd):
    print(id,name,pwd)

if __name__ == '__main__':
    pytest.main(['-sv','test_db.py'])


#读取yaml文件
1、ymal文件如下:env.yaml
  
-
 name: 登录成功
 request:
  url: xxx
  method: get
  headers: null
 data:
  password: 123456
  email: 111@11.com
 validate:
  assert: null


-
 name: 登录失败
 request:
  url: xxx
  method: get
  headers: null
 data:
  password: 123456
  email: 111@11.com
 validate:
  assert: null
python文件读取yaml和调用:
import os
import yaml,pytest

# yaml_file_path=os.getcwd()+r'/data/env.yml'

def read_yaml(yaml_file_path):
    with open(yaml_file_path, encoding="utf-8") as f:
        value = yaml.load(f, Loader=yaml.FullLoader)
        # print(value)
        return value

# print(read_yaml('env.yaml'))

@pytest.mark.parametrize('caseinfo',read_yaml('env.yaml'))
def test_yaml(caseinfo):
    print(caseinfo)
    print('用例名称',caseinfo['name'])
    print('请求url',caseinfo['request']['url'])        

有了pytest后ddt就用的较少了,因为pytest有自己的参数化数据驱动的方式
pip install ddt
import os
from ddt import ddt,data,unpack,file_data
import unittest

def get_data():
    testdata=[{'name':'tom','age':20},{'name':'kite','age':19}]
    return testdata


@ddt
class MyTestCase(unittest.TestCase):
    #读取元组数据-单组元素
    @data(1,2,3)
    def test1(self,value):
        print('测试1',value)

    #读取元组数据,多组元素
    @data((1,2,3),(4,5,6))
    def test2(self,value):
        print('测试2',value)

    #读取元组数据-拆分数据
    @data((1,2,3),(4,5,6))
    @unpack #拆分数据 pack打包
    def test3(self,value1,value2,value3):
        print('测试3',value1,value2,value3)

    #列表
    @data([{'name':'tom','age':20},{'name':'kite','age':19}])
    def test4(self,value):
        print('测试4',value)

    #字典
    @data({'name':'tom','age':20},{'name':'kite','age':19})
    def test5(self,value):
        print('测试5',value)

    #字典拆分
    @data({'name':'tom','age':20},{'name':'kite','age':19})
    def test6(self,name,age):
        print('测试6',name,age)

    #变量或者方法调用
    testdata=[{'name':'tom','age':20},{'name':'kite','age':19}]

    #@data(*testdata) #调用testdata变量
    @data(get_data()) #调用方法
    def test7(self,value):
        print('测试7',value)

    #读文件
    @file_data(os.getcwd()+'/data_json.json')
    def test8(self,value2):
        print('测试8',value2)

if __name__ == '__main__':
    unittest.main()

 

posted @ 2022-08-22 12:04  ilspring  阅读(481)  评论(0)    收藏  举报