由於項目需要,最近在寫一個接口測試腳本,所以許久沒有更新了,不過寫完后,也有一些收獲和大家分享一下
本次寫的主要是查詢類接口,所以重點說一下編寫查詢類接口時用到的一些方法
1. 按照日期查詢
這類查詢功能,在平時測試時往往需要選定一個日期,點擊查詢,然后查看列表中列出的結果是否符合預期
那么針對日期類的查詢,如何構造有效的參數呢
要考慮一點:如何使所選定的日期長久有效
假如選定2019-05-01至2019-05-29,
它存在的問題是,到了2020年再執行這個腳本時,數據就顯得比較舊,甚至由於清除數據庫臟數據,再也查不到結果了,所以盡量不要指定日期
有一個解決方法,先獲取當前日期,然后往前倒退30天、50天等
例如今天是2019-10-29,那就查詢2019-09-29至2019-10-29的數據,永遠以當前日期為基准
獲取當前日期,可以用python自帶的datetime模塊
#coding:UTF-8 import datetime now_date = datetime.datetime.now() # 獲取今天時間 # print(now_date) end_date = now_date.strftime("%Y-%m-%d") # 定義今天時間為查詢結束時間,並轉為字符串對象,以年-月-日格式輸出 offset = datetime.timedelta(days=-50) # 定義偏移量,即與當前日期的時間間隔 begin_date = (now_date + offset).strftime("%Y-%m-%d") # 定義查詢開始時間=當前時間回退50天
2. 從一批響應內容中隨機取出一個進行斷言
使用random.choice()方法,從一組數據中隨機取出一個,一般是從一個列表、元祖或字符串中抽取數據
假如一個查詢接口中返回了多組數據,每組數據的構造相似,這時做斷言的話,不可能每個數據都匹配一次
如下拉勾網搜索一個職位時
可以看到result列表中包含許多條職位信息,每個職位信息都各自在一個json字符串中,斷言時,只需取其中一組數據即可;
問題來了,選哪一組進行斷言,第一組?最后一組?指定一組?
第一組可以達到目的,最后一組也行
但是指定斷言一組不靠譜,因為這次查詢可能返回了3組,下次可能返回了2組
還有一種方式,就是隨機取一組數據進行斷言,
這時候就可以使用random.choice()方法,從所有返回結果中隨機取出一組數據,再將那一組數據的某個值與預期斷言即可
示例:
>>>import random >>>numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] >>>random.choice(numbers) 5 >>> for i in range(3): # 循環8次,每次隨機取一個數 random.choice(numbers) 4 4 9
之前寫過一個電話號碼生成器(可以到歷史文章中查看詳細介紹),也用到了random.choice()
3.利用字符串切片斷言電話號碼后四位
有時候一些敏感信息需要進行脫敏處理,例如會把電話號碼或身份證號碼的中間幾位進行加密處理,常見形式如下
188****8888
當以電話號碼進行查詢時,返回結果中一般也會把電話加密,不過既然是根據電話號碼來查詢,如果響應中有返回號碼信息,最好還是用電話號碼進行斷言
這時候可以匹配電話號碼的后四位,如果匹配成功則認為查詢結果正確
因此可以使用切片方法來取出電話號碼的后四位
>>> phone = "188****8888" >>> phone '188****8888' >>> phone[-4:] '8888' >>>
4. 使用zip()函數遍歷2個列表,將信息組合顯示
場景:比如按照某個主題進行查詢時,實際傳參傳的是該主題對應的編號,
例如『主題A』對應編號『11』,『主題B』對應編號『22』
在編寫腳本時,我希望打出的日志更人性化,
可以打印出:查詢『主題編號"11",對應的主題名稱為"主題A"』的數據有xx條
由於主題名稱和主題編號是在2個列表中,所以就想如何把2個列表關聯起來呢? 能不能同時迭代2個列表,將主題名稱與主題編號對應起來?
於是就找到了zip()函數
網上的一個簡單例子:
>>> list1 = ['a', 'b', 'c', 'd'] >>> list2 = ['apple', 'boy', 'cat', 'dog'] >>> for x, y in zip(list1, list2): print(x, 'is', y) # 輸出 a is apple b is boy c is cat d is dog
復雜一點的例子,列表中包含字典
>>> a = [{"first_name":1,"second_name":2,"third_name":3}, {"first_name":4,"second_name":5,"third_name":6}, {"first_name":7,"second_name":8,"third_name":9}] b = [{"first":11,"second":22,"third":33}, {"first":44,"second":55,"third":66}, {"first":77,"second":88,"third":99}] >>> for x,y in zip(a,b): print("一級主題名稱:{},一級id:{}~二級主題名稱:{},二級id:{}~三級主題名稱:{},三級id:{}".format(x["first_name"],y["first"],x["second_name"],y["second"],x["third_name"],y["third"])) 運行結果如下: 一級主題名稱:1,一級id:11~二級主題名稱:2,二級id:22~三級主題名稱:3,三級id:33 一級主題名稱:4,一級id:44~二級主題名稱:5,二級id:55~三級主題名稱:6,三級id:66 一級主題名稱:7,一級id:77~二級主題名稱:8,二級id:88~三級主題名稱:9,三級id:99
5.format()函數在編寫sql語句中的應用
python中的sql語句需要寫在一對引號中,例如
original_sql = "select * from movies where movie_name = '瘋狂動物城'"
上面語句中movie_name字段目前是一個固定值,假如切換環境執行,如果對應的數據庫沒有"瘋狂動物城"這條數據,那么這個sql查詢就會失效,返回為空
所以我們需要保證要查詢的movie_name盡可能有值
假如此時有一個接口可以獲取movie_name或者事先准備好一批movie_name值
那么就可以讀取接口返回的movie_name或者讀取提前准備好的amovie_name
因此需要想辦法使sql語句中的movie_name參數化,能夠動態讀取傳進來的值
仔細看上面的sql語句,注意到sql語句包含在一對引號中,所以它就相當於一個字符串,因此可以利用format()函數來達到目的
使用方法如下
movies = ["瘋狂動物城", "壞蛋必須死", "冰雪奇緣"] original_sql = "select * from movies where movie_name = '{}'" # 注意因為sql中字符要用引號包裹,所以這里的{}也需要用引號括起來({}可以看作是一個預定的位置,存放movie_name的值) for i in movies: sql = original_sql.format(i) print(sql)
運行結果
再來看例子,假如一個名為get_name()的方法,返回電影的名稱,一個名為get_date()的方法,返回電影的上映日期
接下來要把電影名稱和上映時間放到sql的查詢條件中
original_sql = "select * from movies where movie_name = '{}' and release_date = '{}'" sql = original_sql.format(self.get_name(), self.get_date())
另外format()函數也可以設置參數
上面的例子,可以改為
original_sql = "select * from movies where movie_name = '{name}' and release_date = '{date}'" sql = original_sql.format(name=self.get_name(), date=self.get_date())
6.正則表達式提取中文字符
有時接口返回的某個字段值得時候,會自動加上某個后綴
例如姓名:張三qt,李四1,王五rw
其實數據庫中存在的數據不帶后綴,就是單純的中文字符
例如:
select * from name_list where name = '張三' #可以查到數據
select * from name_list where name = '張三qt' #查不到數據
所以在通過接口獲取到這些數據后,需要處理一下,只保留中文字符,然后傳給sql查詢語句
這里通過正則表達式的方式來處理
import re name = "張三rx" pattern = re.compile(r'[\u4e00-\u9fa5]') # 定義一個正則表達式,去掉字符串末尾的數字 m = pattern.findall(name) # 匹配結果,返回每個漢字組成的列表 print(m) real_name = "".join(m) # 將每個漢字組成一個字符串 print(real_name)
運行結果