背景
我所在的公司是一家傳統(tǒng)互聯(lián)網+教育公司,推送業(yè)務是從去年開始的,前后也經歷了多次迭代,沒有大牛,也沒有架構師來統(tǒng)籌,一路踩坑,一路填坑。我們經歷了大晚上給用戶一直重復推送的嚴重事故,也有上線后用戶收不到推送的尷尬,今天就從一個測試的角度來聊聊推送通知,因為鄙人只負責IOS端的業(yè)務,所舉的例子多以IOS為主。
推送架構
服務器后端——第三方推送SDK——APP,畫了一個簡易的流程圖如下:

大意就是APP啟動后,去第三方請求注冊(目前實現(xiàn)安卓用的是信鴿,IOS用的是極光),第三方返回注冊id(Device token)即設備別名給APP,APP將用戶id和Device token提交到服務器,服務器將其存儲到數據庫,發(fā)推送時只要將要發(fā)送的用戶或設備信息和待發(fā)的數據參數發(fā)送給第三方便可實現(xiàn)推送。
注冊
先來說說第一步注冊,APP向第三方請求注冊,什么時候請求,登錄?APP啟動?注冊失敗后該怎么處理,是否有重試機制,重試機制重試多少次呢,是否會有死循環(huán)?
關于Devicetoken,IOS的官方文檔是這么描述的:
If the user restores backup data to a new device or computer, or reinstalls the operating system, the device token changes
An application should register every time it launches and give its provider the current token
大致是說,當進行備份恢復、或恢復出廠設置之類的操作時,Device token會發(fā)生改變,建議 APP 在每次啟動時都獲取Device token,有博客上說刪除手機上的 APP 之后,再次下載安裝,Device token會改變,我自己試了一下,IOS7卸載重裝Device token不會改變,IOS10卸載重裝后Device token發(fā)生了改變,后來我在這篇博客上找到了答案,同一設備上APP的Device token確實會發(fā)生改變,只是舊的Device token是無效的。即使這樣,仍需要將最新的Device token傳遞個服務器,這篇博客上也提供了解決方案。
通常,一個用戶是可以綁定多個設備即Device token,這也給用戶多終端同時登錄推送通知提供了可能。如果一個賬號在多臺設備登錄,指定別名下發(fā)通知,理論上多臺設備都可以收到推送。而用戶退出登錄后,怎么確保不再收到推送,需要考慮在退出登錄去注銷綁定。如果是跳過退出登錄這一步,對應的綁定關系仍在,比如說卸載后再重裝,如何去解除賬號與設備綁定就需要重新考慮了。同一設備上設備別名通常情況下都不會改變,意味著一臺設備可能綁定多個別名,就可能存在該設備已經登錄另一個賬號,但仍然可以收到推送,所以最保險的方式還是在退出登錄時,解除賬號與設備的綁定。
所以在測試之前弄清注冊的機制和服務端如何去存儲用戶和設備的綁定關系,尤為重要。
關于通知設備選擇
通過極光給出的API文檔,可以很清晰的看到設備的選擇有多種方式:

指定所有人推——只要告訴第三方推送服務器指定所有人
指定賬號推——告訴第三方需要發(fā)送用戶的ID,可以是1個用戶,也可以是批量用戶
指定設備別名推——告訴第三方設備的別名,可以是1個,也可以是多個
指定標簽推——即具有同一屬性的用戶放在一個標簽下,比方說省份,年級等。創(chuàng)建推送的時候只要將標簽發(fā)給第三方推送,就可以實現(xiàn)標簽下綁定的設備都可以收到推送。
毫無疑問,指定所有人推,肯定是效率最高的,只要告訴第三方一個指令,就可以坐等通知了,但實際的業(yè)務場景往往比這復雜的多。
假設有這么一個場景,我要對報名一場直播的10000個用戶定時發(fā)推送通知,首先在用戶報名后,需要獲取報名用戶的賬號和綁定的Device token,存儲在數據庫。接下來有兩種方式可以選擇,一、用戶報名后,就獲取用戶的userid和Device token,然后寫到第三方推送服務器,定時發(fā)送;二、在一個時間段比如說直播開始前1個小時去往第三方推送服務器寫入useid或者Device token。在userid還是Device token的選擇上,肯定是userid更為合理,可以避免報名后更換設備這類問題。如果是第一種方式,如此高頻率的調用寫入接口,即使第三方沒有問題,自己的服務器性能是否會有問題。假設是第二種方式,怎么來保證在規(guī)定時間能把全部數據寫入到第三方,對于過了時間段的報名用戶又該怎么處理這是個問題。對于出現(xiàn)調用接口失敗,該怎么處理,會不會影響后面的寫入,同樣值得推敲。
當然,有第三種方式,也就是后面提到的指定標簽的方式,也是目前我們使用的方式。
標簽推送
標簽推送可能是僅次于指定所有人的推送方式了。指定一個標簽或者多個標簽取并集或交集,前提是不要把or或者and寫反了。只要告訴第三方推送需要發(fā)送的標簽,就可以對一批用戶發(fā)通知,是不是感覺很easy。標簽的創(chuàng)建既可以是APP內置的SDK來實現(xiàn),也可以通過后臺調用第三方推送提供的API來實現(xiàn),目前公司有一部分標簽通過APP創(chuàng)建,一部分標簽通過后臺調用API來創(chuàng)建。第三方對于標簽的創(chuàng)建都存在一些限制,了解這些限制方便我們更清楚可能潛在的問題,這里可以看一下極光更新標簽的API文檔說明
為一個標簽添加或者刪除設備。
POST /v3/tags/{tag_value}
Example Request
Request Header
POST /v3/tags/{tag_value}
Authorization: Basic (base64 auth string)
Accept: application/json
Request Body
{
"registration_ids":{
"add": [
"registration_id1",
"registration_id2"
],
"remove": [
"registration_id3",
"registration_id4"
]
}
}
Request Params
action操作類型,有兩個可選:"add","remove",標識本次請求是"添加"還是"刪除"。
registration_ids 需要添加/刪除的設備registration_id。
add/remove最多各支持1000個;
極光最多創(chuàng)建1000個標簽,1次請求則最多支持1000個綁定和刪除,換到信鴿則是最多創(chuàng)建10000個標簽,1次請求則最多支持20個綁定和刪除。這里有三個問題:1、標簽綁定 如果達到上限該怎么處理;2、綁定標簽是否會有性能問題,同時有大批量的標簽需要綁定,是否會出現(xiàn)排隊問題;3、標簽綁定失敗,怎么解決?
標簽更新
標簽選擇客戶端來綁定還是服務端來綁定?選擇在什么時候去更新標簽,如果時客戶端,在啟動or登錄?當然標簽時客戶端來實現(xiàn)還是后臺來實現(xiàn),有些問題是不一樣的,所以一開始,就應該明確標簽的是實現(xiàn)方式。
另外用戶信息發(fā)生變化,是否能及時去更新?打標簽采用覆蓋的方式還是增量的方式?之前我們就出現(xiàn)極光的SDK采用覆蓋的方式來綁定標簽,導致APP綁定標簽后,服務端綁定標簽全部被覆蓋掉。用戶的屬性可能發(fā)生變化,是否能夠及時去更新,比如說版本號升級,用戶省份切換,新的標簽需要覆蓋舊的標簽,需要解綁再重新綁定。
標簽與設備Device token綁定,但我們希望收取到通知的使我們的用戶,如果用戶切換設備,怎么去更新標簽的綁定,以及怎么去解除舊的設備與標簽的綁定。假設在退出登錄去解除設備與標簽的綁定,怎么解除,客戶端來解除還是服務端來解除?重新登錄后怎么去保證標簽能夠重新綁定上?即使退出能夠解決問題,卸載呢?退出登錄碰上網絡斷開呢,是不是很瘋狂?
APP要做什么
前面說了那么多,都是在說怎么將通知發(fā)給正確的用戶,跳過這一步。假設對的人收到對的推送,是不是就萬事大吉了呢?
如何保證不同的操作系統(tǒng)以及各種版本能夠正確展示通知,包括舊到IOS7,新到IOS11,安卓亦是。在IOS10以前,如果在APP界面是收不到通知橫幅的,但是在IOS10以后,又發(fā)生了改變,即使正在操作APP一樣可以收到通知橫幅。IOS8APP界面如果沒做判斷,會自動打開通知消息,在字符串轉數值類型,IOS8帶有符號會導致過期時間變成負數。雖然處于兼容性考慮確實會影響代碼的進步,但是用戶是上帝啊。
APP未啟動如何收到通知,IOS通過APNs進行分發(fā)不會有此類問題,那么安卓呢?未啟動點擊通知能成功吊起APP進程嗎,點擊橫幅的時候怎么來確認我是否登錄,我是否有權限來訪問這條通知呢,假設用到了緩存,進入通知消息后,緩存是否及時去清除。橫幅過期了怎么辦,等到你過期我再點,你能識別出來么。
關于IOS的角標怎么處理,該死的產品經理就要求角標得和APP里面的未讀數量對應,首先,不管是PUSH通知還是PULL消息(由第三方推送給用戶的叫PUSH,APP向服務端請求的消息列表叫PULL)都需要標記已讀,在不同的場景下home到桌面或者殺死進程,角標的數量得能對應上。
最后說句感性的話
在我剛進入這個行業(yè)的時候,別人告訴我,軟件測試就是使用人工操作或者軟件自動運行的方式來檢驗它是否滿足規(guī)定的需求或弄清預期結果與實際結果之間的差別的過程。神他媽預期預期結果,哪有那么多預期結果,找出已知的問題,分析潛在的風險,凡事多問問這能行么,要不成咋辦啊,呵呵。