打開DOS命令或者在pycharm的terminal中輸入pip install requests就可以安裝了
打開DOS命令或者在pycharm的terminal中輸入pip install pyyaml安裝
使用單元測試框架
class (類名): def setUP(self): passdef test_01(self): print('this is test01’) def tearDown(self): pass
跳過用例
#如果想要跳過某條用例,只需要在前面加****@unittest.skip**# @unittest.skip #跳過本條用例def test_02(self): print('this is test02’)def test_03(self): print('this is test03’)
只在開始和結(jié)束輸出,每條用例運行中不再輸出
@classmethoddef setUpClass(cls): print('this is start…’)@classmethoddef tearDownClass(cls): print('this is end…’)
斷言
**self.assertIn('預(yù)期結(jié)果****’,res.text)**
如果斷言結(jié)果與實際結(jié)果不一致,則會出現(xiàn)下方情況,點擊查看差異 左邊預(yù)期結(jié)果,右邊實際結(jié)果
設(shè)置全局變量global 在登錄接口中設(shè)置一個cookie的全局變量,下邊的接口中就可以使用了
global cokcok=res.cookies
導入用例: 先在項目中新建一個Python Package命名為case,然后在其中新建一個后綴為.yaml的文件, 然后在文件中寫入用例,格式為:
Url: 網(wǎng)址 #每個參數(shù)名的冒號后面要加空格再跟參數(shù)值method: 請求方式Detil:描述(此項可不寫)data: 參數(shù)名: 參數(shù)值(不加引號)check:
預(yù)期結(jié)果(-后有空格) 如:
url: http://192.168.2.110/geeknet/flow.php?step=add_to_cartmethod: POSTDetil: 加入購物車data: goods: '{“quick”:1,”spec”:[],”goods_id”:62,”number”:”1”,”parent”:0}’check: #預(yù)期結(jié)果 - one_step_buy-url: http://192.168.2.110/geeknet/flow.php?step=cartmethod: GETdata:check:
購物車( 1 ) 在類前添加@ddt.ddt 然后在需要引入的函數(shù)前加@ddt.file_data(r’用例文件存放路徑’)如
@ddt.file_data(r’D:\python\jiekou0518\case\api.yaml’)#加r防止路徑轉(zhuǎn)移
然后在函數(shù)中使用如:
def test_one(self,**test_data):url=test_data.get('url’)
如何連接數(shù)據(jù)庫 (1)新建一個python包config,然后在其中創(chuàng)建一個config.ini文件,向其中寫入數(shù)據(jù)庫的連接配置:哪個MySQL連接,主機,端口號,用戶名,密碼,庫名,編碼方式:
[MYSQL]host = 192.168.2.110port = 3306user = rootpasswd = rootdb = gkcharset = utf8
(2)在common文件夾中建一個Python文件configmysql來配置連接數(shù)據(jù)庫
#配置 mysqlimport pymysql import config parserconfig = configparser.ConfigParser() #讀取配置文件 config.read(r’D:\python\jiekou0518\config\config.ini’) class ApiTools(): #定義函數(shù)連接數(shù)據(jù)庫 def conn_mysql(self): host = config.get('MYSQL’,’host’) port = config.get('MYSQL’,’port’) user = config.get('MYSQL’,’user’) passwd = config.get('MYSQL’,’passwd’) db = config.get('MYSQL’,’db’) charset = config.get('MYSQL’,’charset’) self.connect = pymysql.connect( host = host, port = int(port), user = user, passwd = passwd, db = db, charset = charset, ) #連接數(shù)據(jù)庫中的游標cursor,用來執(zhí)行sql語句 self.cursor = self.connect.cursor()# 定義執(zhí)行MySQL的函數(shù),不同的場景下有不同的方法def execute_sql(self,sql): '’’ 執(zhí)行sql語句,包括更新和新增數(shù)據(jù) '’’ self.conn_mysql() #連接數(shù)據(jù)庫并獲取游標 self.cursor.execute(sql) #用游標去執(zhí)行sql語句 self.connect.commit() #執(zhí)行完畢提交def search_sql(self,sql): '’’ 執(zhí)行查詢語句 '’’ self.conn_mysql() self.cursor.execute(sql) return self.cursor.fetchall() #返回所有行的值#定義關(guān)閉sql連接的函數(shù),避免占用服務(wù)器資源def close_sql(self): '’’ 關(guān)閉游標和數(shù)據(jù)庫連接 '’’ self.cursor.close() self.connect.close()#測接口要測冪等,為了防止重復提交if __name__ == '__main__’:too = ApiTools()too.conn_mysql()sql = 'delete from gk_order_info WHERE zipcode =457100;’api = too.execute_sql(sql)too.close_sql()print(api)
最后在runfile文件中新增*tearDownClass*函數(shù),用來刪除用例執(zhí)行后的臟數(shù)據(jù)(無用的)
@classmethoddef tearDownClass(cls): too = configmysql.ApiTools() too.conn_mysql() sql = “delete from gk_order_info where order_sn in(select o.order_sn from “ “(select order_sn from gk_order_info order by add_time desc limit 1) as o)” too.execute_sql(sql) too.close_sql()
最后將用例打印出報告,使用unittest。*makeSuite(*類名*)*可以將主函數(shù)所有的類都添加到測試集合中
if __name__=='__main__’: # unittest.main() su=unittest.TestSuite() #建立測試集合 su.addTest(unittest.makeSuite(Test)) #將主函數(shù)中的所有用例都添加進去 now=time.strftime('%Y-%m-%d %H-%M-%S') #使用當前時間并格式化時間為年月日時分秒 filename = r’D:\python\jiekou0518\report\ '+ now +’resuilt.html’ fp=open(filename,’wb’)runner=HTMLTestRunner(stream=fp,title='自動化測試報告’,description='用例描述’) runner.run(su) fp.close()
import unittest import ddt,time,requests from common import configmysql from HTMLTestRunner import HTMLTest Runner@ddt.ddtclass Test(unittest.TestCase): @classmethoddef setUpClass(cls): #在所有用例執(zhí)行之前先先執(zhí)行登錄的用例,獲取cookies url='http://192.168.2.110/geeknet/user.php’ data={ 'username’:’lee000000’, 'password’:’000000’, 'act’:’act_login’, 'back_act’:’http://192.168.2.110/geeknet/', 'submit’:’’ } res=requests.post(url=url,data=data) cls.assertIn(cls,’歡迎您回來’,res.text) global cok cok=res.cookies@ddt.file_data(r’D:\python\jiekou0518\case\api.yaml’)#加r防止路徑轉(zhuǎn)移def test_one(self,**test_data): url=test_data.get('url’) method=test_data.get('method’) detil=test_data.get('detil’) data=test_data.get('data’) check=test_data.get('check’) if method=='GET’: #轉(zhuǎn)化為文本格式,方便后邊去斷言 res=requests.get(url=url,cookies=cok).text elif method=='POST’: res=requests.post(url=url,data=data,cookies=cok).text # for I in check: # try: # self.assertIn(i,res) # print(i,’用例執(zhí)行成功’) # except Exception as e: # print(i,’用例執(zhí)行失敗’) for I in check: self.assertIn(i,res)@classmethoddef tearDownClass(cls): too = configmysql.ApiTools() too.conn_mysql() sql = “delete from gk_order_info where order_sn in(select o.order_sn from “ “(select order_sn from gk_order_info order by add_time desc limit 1) as o)” too.execute_sql(sql) too.close_sql() if __name__=='__main__’: # unittest.main() su=unittest.TestSuite() #建立測試集合 su.addTest(unittest.makeSuite(Test)) #將主函數(shù)中的所有用例都添加進去 now=time.strftime('%Y-%m-%d %H-%M-%S') #使用當前時間并格式化時間為年月日時分秒 filename = r’D:\python\jiekou0518\report\ '+ now +’resuilt.html’fp=open(filename,’wb’) runner=HTMLTestRunner(stream=fp,title='自動化測試報告’,description='用例描述’) runner.run(su) fp.close()
如何將測試報告通過郵件發(fā)送到指定人員 Config.ini 配置mail為163郵箱時,password不是登錄密碼,只是一個授權(quán)碼 (1)在config.ini配置文件中新增郵箱配置:
[email]smtpserver = smtp.163.com sender = luokuo8080@163.com password = luokuo8080 receive = luokuo1018@163.com
(2)在common包中新增configmail.py文件。編寫發(fā)送郵件的代碼
import configparser import osimport smtplib from email.mime.text import MIMEText from email.header import Header config = configparser.ConfigParser()config.read(r’D:\python\jiekou0518\config\config.ini’) class Send_mail: #我們需要先將最新的測試報告?zhèn)鞯轿覀兊暮瘮?shù)中 def send_email(self,new_report): #parm new_report是把找到的最新的測試報告?zhèn)鬟M來作為郵件內(nèi)容發(fā)送 f = open(new_report,’rb’) body = f.read() f.close() smtpserver = config.get('email','smtpserver') #從config.ini文件中取出email的參數(shù) sender = config.get('email’,’sender’) password = config.get('email’,’password’) receive = config.get('email’,’receive’) subject = 'API TEST 自動化測試報告lee' #定義標題 msg = MIMEText(body,’html’,’utf-8’) msg['from’] = sender msg['to’] = receive msg['subject’] = Header(subject,’utf-8’) smtp = smtplib.SMTP() #實例化smtp(發(fā)送郵件的方法) smtp.connect(smtpserver) #連接smtp服務(wù)器 smtp.login(sender,password) #登錄 smtp.sendmail(sender,receive,msg.as_string()) #發(fā)送 smtp.quit() #退出def latest_report(self,report_dir): #:param report_dir:把報告存放的路徑傳進來,以供篩選最新生成的測試報告 #report_dir:把報告存放的路徑傳進來 lists = os.listdir(report_dir) #列舉report_dir下面的所有文件 結(jié)果以列表的形式返回 #對列表進行排序(默認從小到大) lists.sort(key = lambda fn:os.path.getmtime(report_dir + '\\’ +fn)) #os.path.getmtime是獲取文件的最后修改時間 #os.path.join路徑拼接 file = os.path.join(report_dir,lists[-1]) #即file= 'D:\python\jiekou0518\report\ 2020-05-20 10-46-05resuilt.html' return file if __name__ == '__main__’: mail = Send_mail() report_dir = r’D:\python\jiekou0518\report’ new_report = mail.latest_report(report_dir)mail.send_email(new_report) (3)在runfile中調(diào)用發(fā)送郵件的函數(shù)并將測試報告發(fā)送到指定郵箱#先引入configmail文件中的類f rom common.configmail import Send_mail #然后調(diào)用 mail = Send_mail() report_dir = r’D:\python\jiekou0518\report’ new_report = mail.latest_report(report_dir) mail.send_email(new_report)
我們使用的是用python編寫的一個小型的接口自動化 使用的是python+unittest+yaml+request+ddt框架,進行編寫的接口自動化腳本。 一般我們會把接口自動化的測試用例按格式放到y(tǒng)aml文件里面 然后把一些固定的配置文件可以放到config.ini文件里面,比如說數(shù)據(jù)庫的IP地址,賬號和密碼,端口,要連接的數(shù)據(jù)庫的庫名等等,如果需要調(diào)用config.ini里的配置可以通過實例化configparser把配置文件里面的內(nèi)容給get進來然后我們會寫一些經(jīng)常用到的工具,放到tools里面,比如說連接數(shù)據(jù)庫的函數(shù),包括提交sql語句和查詢語句和關(guān)閉數(shù)據(jù)庫連接的函數(shù)。把他們放到configmysql文件里面,然后在我們測試的時候我們會把我們的主方法寫在runmain.py 這個文件里面,然后在這個文件里面使用request方法重構(gòu)get和post請求,我們會首先用ddt.file_data把yaml文件路徑引入,然后定義一個函數(shù),把測試用例的url,方法和請求參數(shù)以及預(yù)期結(jié)果通過**test_data把數(shù)據(jù)傳進來之后再一個一個給get進來,然后用if語句去判斷get請求或者post請求并用request去發(fā)送請求,然后用for循環(huán)把檢查點給循環(huán)出來并進行assert斷言,并用try方法去處理異常信息,然后執(zhí)行完畢之后我們可以調(diào)用數(shù)據(jù)庫處理的方法去進行數(shù)據(jù)清理,最后用HtmlTestrunner發(fā)送測試報告。
對于依賴的接口我們一般是 把上一個接口的返回值給一個中間變量return出來,并 且把這個變量設(shè)置成全局變量,如果下個接口使用直接調(diào)用這個全局變量就可以了。
一般需要登錄的接口我們使用的是unittest框架 那么我們就可以把需要登錄的接口放到setupclass里面然后把cookie的值給一個 中間變量,然后把中間變量global成全局變量,然后下面的接口如果需要cookie直 接在請求的時候直接把全局變量的cookie傳入進去就可以了。
我們的測試用例是在yaml文件里面管理的,把測試用例維護到y(tǒng)aml文件里面 然后在使用里面的測試用例的時候我們可以用ddt進行數(shù)據(jù)驅(qū)動,用ddt.file_data 把yaml文件的路徑引入進來然后用get方法獲取yaml文件里面的每個字段的字段名 然后再去構(gòu)造請求。
用python連數(shù)據(jù)庫,做增刪改查的操作。測試用例前置操作,用setUp做數(shù)據(jù)準備比如登錄。測試用路后置操作,tearDown連接數(shù)據(jù)庫做數(shù)據(jù)清理
通過導入pymysql包去連接數(shù)據(jù)庫 需要通過configparser用get方法去獲取config.ini配置文件里面 的數(shù)據(jù)庫的參數(shù)比如:port 、user 、passwd 、db名字、charset 編碼方式 然后用pymsql.connet方法把參數(shù)傳進去去連接數(shù)據(jù)庫獲取數(shù)據(jù)庫游標cursor 然后用游標的execute方法去執(zhí)行sql用commit方法去提交數(shù)據(jù),如果是 查詢的數(shù)據(jù)需要通過cursor.fetchall()獲取所有數(shù)據(jù)并把數(shù)據(jù)return出來, 然后最后關(guān)閉游標,關(guān)閉連接。
**腳本結(jié)構(gòu):** **— api.yaml** **存放接口測試用例** **— config.ini** **存放數(shù)據(jù)庫的連接配置** **存放email的連接的配置** **— common** **—configmysql.py** **構(gòu)造數(shù)據(jù)庫連接的方法** **構(gòu)造數(shù)據(jù)庫執(zhí)行(execute_sql)** **/查詢(****search_sql****)** **/關(guān)閉數(shù)據(jù)庫連接(****close_sql****)** **--configemail.py** **發(fā)送郵件** **-- runmain.py** **主方法**