小微團隊怎么玩轉App自動化測試

camb1186 7年前發布 | 7K 次閱讀 自動化測試 移動開發

這篇文章,我會站在小微團隊的角度,介紹一下我對App自動化測試的一些看法。在幫助你降低對App自動化測試的期望的同時說服你開始實踐App自動化測試。

App自動化測試一直是小微團隊很少會去涉足的領域,在互聯網快速迭代這個大場景下,隨著業務發展,回歸壓力逐漸增大。相信每次因為回歸覆蓋不足而導致線上事故,懊惱郁悶到要砸桌子的絕對不止我一個。

一般情況小微團隊的測試包括回歸測試都是人工進行的,一些偏離主流程卻又比較關鍵的業務往往是人工回歸測試容易遺漏的。人力有窮盡,這個時候自動化測試這個念頭就從你的腦袋里冒出來了,然后就是去研究嘛。但可能最終也就止步于研究了。不談自動化框架的搭建,種種細分的邊界case,一個必然很繁瑣的東西想一想就更繁瑣了。如果你是App開發,本來業務開發上的人手就不是很充足,再去開發自動化腳本,有心無力!如果你是測試,每個迭代的業務需求測試就填滿了你的排期,更何況承擔的可不只是App測試任務。作為小微團隊,自動化我們也想,但我們沒有資源……

首先我們要明白App自動化測試并沒有你預想中的那么強大,但如果你像我一樣面臨著回歸測試痛點,它絕對可以滿足你的需求。沒有那么強大,所以也沒有你預想中的那么復雜,同時它的參與者也絕不只應限制在Tester或Developer上,所以在資源上你可以有更靈活的調配。當然,自動化測試是一個長期的過程,它的未來,也絕不僅是回歸……

最后我會為你安利一款偏冷的自動化測試工具:Calabash。并奉上Calabash入門教程博客和一點我的使用心得。介紹Calabash,是因為Calabash的特性在我個人看來更為適合資源緊缺的小微團隊。

大話App自動化測試

僅代表個人觀點,見識還淺,歡迎多多打臉。

現狀

先說點大家都知道的。以Android為例,從2010年開始,Android開發環境以及其迅猛的態勢發展到今天,幾近趨于成熟,開發者的目光早已不在局限于這單一的開發平臺,開始尋求Android,iOS在開發上的統一:ReactNactive,WEEX,H5……

開發環境已經成熟,但移動客戶端的測試環境卻有些滯后。這中間的幾座大山是很多團隊正在面對且駐足的:

1.App測試不像服務端測試通常只需對數據本身進行驗證即可,App涉及到界面展示及交互,自動化識別難度大。

2.互聯網企業一直都在追尋快速迭代,且App直接對接用戶,App的界面與邏輯變更更是家常便飯,編寫自動化測試腳本的穩定性很差,可能設計對界面的一次改動,之前與這個頁面掛鉤的所有腳本就都廢掉了。

3.Android iOS 雙平臺,web頁面。多平臺的情況下想要依靠一套代碼進行自動化測試幾乎是不可能的。再考慮需要經常變更,你懂得。

4.比起人工來說,自動化測試可能需要為種種邊界case編寫很多的腳本。同比人工測試,可能需要的只是事先設計幾個場景,其他的異常邊界case通過測試中人為觀察就好了。自動化測試成本倍增!

所以往往一個完善的移動自動化測試環境需要一個龐大的測試團隊支撐,但一個龐大的測試團隊只有大公司才能負擔的起。移動的自動化測試,一直都在被中小型的創業公司所忽略。小型公司開發自測了事,中型公司依靠測試人員人工操作進行驗證。

自動化測試真的對于小微團隊緊閉大門嗎?

Just do it

上面說的這些現狀只能說是難題,也許現在討論解決這些問題還早了些。我覺得你有些東西還沒確定清楚,要不然先跟著我的思路走一走?等下面一些事情都想明白了,也許這些問題能避也就避過了,需要硬上的,也有足夠心理準備了。

1.設定階段計劃試錯

其實讓小微團隊面對自動化測試左右徘徊最大的一個問題就是:投入產出比!

很難去預估實行自動化測試后,在頁面頻繁變更與腳本的開發和維護之間,測試或開發人員會不會陷入泥潭。

但紙上談兵永遠也不會有結果,其他大公司的借鑒意義也不是很強,因為這涉及到團隊、資源分配、業務變更頻度、測試工具、腳本開發的解耦程度等等。不過自動化測試是一個必然的趨勢,所以行動是最首要的!

你的團隊目前到底適不適合,只有試了才知道。不妨先設定幾個階段,然后用第一階段試錯:

階段1:抽出一個人一個迭代的資源完成主流程業務的自動化測試case,試運行兩到三個迭代,并在這期間增加主流程異常case。利用這三個迭代來評估后續發展可行性!

階段2-(階段1成功度過):如果你認為階段1的狀態還不錯,那么在維護階段1成果的基礎上從剩余業務場景中按照業務關鍵程度、變更頻率來選取一個新的業務,以一個人一個迭代一個業務的節奏編寫自動化測試case!

階段2-(階段1過度失敗):當然,經過三個迭代的評估,隨著異常case增多,同步維護難度越來越大,你可能認為實行自動化測試的成本過大,但也不要輕易放棄這三個迭代的成果。請先利用編程思維檢查所有的測試腳本,是否有抽取相似代碼,封裝特定View操作,抽離與業務無關指令的可能。同時考慮利用全組資源就此維護這套主流程自動化case。直到將來資源充足或找到更好的替代方案后進行階段3或重新階段1。

階段3:大概在5~8個迭代后,你成功撐過了階段2,說明你的自動化測試環境已經步入正軌,那么這個時候可以按照團隊資源情況適當加快自動化case覆蓋率!

利用一人一個迭代的資源進行試錯,相信是你可以接受的一個損失。當然,先不要急著做,你也許只是決定了要進行自動化測試,但還是要定一些詳細的計劃和一些思想、實際行動上的準備!

2.確定明確且簡單的目標

有了大的計劃,還要明確具體的需求,可選的需求大概有這么些:

1.黑盒測試還是白盒測試

雖然是UI自動化測試,但也可以分為黑盒或白盒,這個取決你想要的測試精密度,也就是在這個時候,可以初步確定要使用什么自動化測試工具。比如通常我們為了可以雙平臺會選擇Appium這種可以跨平臺的測試工具,但假如你有很高的測試要求,以Android為例,建議你使用Android官方推薦的測試框架:Espresso,直接在Android工程項目中寫Test。

這樣說出來好像誰都明白,但如果你不能在前期就明確你的需求,可能會在后期帶來很大的困擾!選擇Appium,因為是黑盒,遇到某些特殊的場景或需求,導致個別case無法測試。或者選擇了Espresso,但后來發現其實并沒有那么精密的測試需求,導致后期無法跨平臺或者認為Espresso編寫成本過高,還很難移交給測試團隊。

2.前端UI還是整體業務

舉個例子,搶單并且進行配送這個場景。發現一個訂單并點擊搶單,然后進行取餐,最后完成配送這一套只能用肉眼觀察到的UI層操作,我們暫定為這是前端UI邏輯。但在這一系列操作背后訂單狀態流轉引起其他數據變動,比如:錢包數據變更,活動獎勵數據變更,欺詐單判定等等這個范圍,就屬于整體業務范疇了。

而我們需要現在確定的,就是你想要達到的測試期望是UI測試,還是整體業務測試。這直接決定了你測試腳本的復雜度。而我的建議是僅測UI邏輯,也是我想讓你降低期望一個點。

先確定一個明確且簡單的目標,然后一頭扎進去。如果想的多了,困難也就多了,最后可能也就只是想想了,這就是下面緊接著要說的點: 降低期望

3.降低期望

在人工(對著手機點點點)測試的環境下,我們通常都是通過操作App進行各種case驗證,只要操作app驗證通過了那基本可以確定前后端沒什么問題了。但這個前提是人工驗證是人腦加肉眼,它會有更準確的主觀判斷。

涉及到前后端交互會增加極大的復雜性,你的測試case不會無限多無限精細,但作為人腦你可以在有限的case執行中發現更多不符合常理的bug:文字不合理的折行,不準確的數值顯示,按鈕顏色不對,Toast展示數量有誤等等等。自動化測試會死板的跟著你寫的腳本走,你能保證你的case覆蓋到了所有了嗎?

這也是談到自動化測試,好多人都會拋出的一個疑問,那么多異常case怎么寫啊,想想都累,考慮一下投入產出比要不還是人工測試吧。

首先要明確的一點,前后端自動化測試一定要分開,一套解決不了問題,這樣在前端測試中可以忽略很多的case。

另外自動化測試是一個與項目成長一樣的長期過程,自動化完全代替人工依然還需要走一段時間,你不要想著一步到位。

依然還是會有很多的case要寫對吧?資源不夠我們可以先跑通主流程再說,跑通主流程也就意味著腳本依賴(環境搭建,view定位)已經較為成熟了,其他異常case腳本對著主流程腳本修改即可,這個我們慢慢來嘛,而且這個時候你就可以放開給別的開發或測試讓他們照貓畫虎了。這也就是我們上面說的 階段1

如果這些問題不能想通,你會發現在App自動化測試條件有限的情況下,并不能實現你想要的結果,從而迫于壓力而放棄了。 說服自己降低期望

  • 降低期望,先以回歸為目標
  • 降低期望,前后端自動化測試都要有,一套解決不了問題
  • 降低期望,客戶端自動化測試限制依然很多,人工測試驗證不能全部丟下
  • 降低期望,一口吃不成個胖子,自動化測試也是需要慢慢迭代完善的,先跑通再關心驗證異常case。快速迭代,逐步完善

4.術業有專攻

也許你的團隊里是開發或者測試中的某一方無法承受壓力,從而開始探索App自動化測試。

開發去做自動化測試的優點在于因為有更豐富的開發經驗,測試環境的搭建更為熟練,且因為是自己寫的代碼,會更了解風險點在哪里,能寫出有針對性的case。測試去做自動化測試的優點在于發現更多的邊界場景,寫出更全面的測試case。

在自動化測試上,開發和測試各具不同的優勢,但同時這也是對方的劣勢。

測試case一定要越全面越好,而且自動化測試本身就是一個工程項目,在寫腳本時,如果更多的考慮一些編程思想,合理的耦合和解耦,將會讓之后的腳本編寫更便捷。

所以,非常不建議自動化測試完全單獨交給測試人員或開發人員來負責,最好是一種緊密合作的關系。 同時也是應對資源不足的一個解決之道 。雖是測試,但有開發的加入,會讓測試工程朝著更優的方向發展。

5.一個巴掌拍不響

首先再次明確我的一個觀點:在沒有足夠的資源的情況下,移動客戶端自動化測試,主要針對的應該是回歸測試。

自動化測試相比起人工測試,是非常死板的,那么就需要非常“死板”的數據支持.如果是App開發(就像我)去做自動化測試這件事,難道所有數據我都要mock一遍嗎?雖說前后端自動化應該分開,前面也說了應該只關心前端邏輯。但一定還是要在真實的服務環境(測試環境,非生產環境)進行測試。

mock數據過于死板,很多case可能就無法驗證了,比如注冊場景,要驗證注冊過的賬號無法再注冊時的異常提示,mock數據顯然較難兼顧正常注冊和異常注冊兩種。而且在真實環境中測試,萬一測出來一個后端bug不挺好么。

而且,手機淘寶這樣完全2C的應用直接在生產環境測試好像沒什么太大問題,但像蜂鳥配送這樣半2C的應用來說就比較尷尬,直接去搶線上單明顯不可能,那么在測試環境這個訂單誰來發怎么發呢?

所以這個時候你就不能自己單干了,去找測試同學,看能不能搞一個配合自動化測試的測試環境,拿搶單來說,我希望這個環境上永遠有好多單讓我搶。我就是搶單的app,沒單我還玩什么。

如果測試同學搞不定,那么就去拉后端的同學啦,我相信為了項目越來越好,他們是不會拒絕你的。

自動化測試,不僅是自動化測試工具就夠了,同樣還需要測試環境的支持。

小結

其實說了這么多,就是想要你降低期望,并付諸行動。

App的自動化識別和多平臺自然會有大批的自動化工具幫你實現,而學會降低期望的同時也會降低腳本開發和維護的難度。

難道你還在糾結細分case太多的問題?先放一放又如何?反正你都裸奔這么久了,穿褲子不也要先穿個褲衩才行么,褲子慢慢來!

或者你依然徘徊在投入產出比的問題上?買衣服不也要先試穿才知道碼號的嗎?

OK,下面我們聊聊這個褲衩,和怎么穿這個褲衩!

測試工具

做好了思想工作,具體實現還是需要選擇一個具體的測試工具,工具沒有好壞,只有適不適合。

Calabash是我個人建議小微團隊使用的測試工具,因為其兼具門檻低、跨平臺、腳本維護容易的特性,而這正是小微團隊最急需的。

且其BDD(行為驅動開發)的思想雖然有點烏托邦,但從遠瞻的角度來看,實現測試腳本先于程序開發編寫的這種先進項目管理可能性也大于其他工具,讓測試不僅僅是測試!

下面我會對Calabash的特性做一個簡單介紹,詳述其優缺點,你可以根據自身團隊經驗進行選擇是否使用,如果喜歡,文末會附上Calabash由淺入深的入門教程,加之更詳細的特性介紹和我自己的使用建議。

Calabash

談Calabash前,先要交代清楚Calabash是啥。

Calabash的核心是Cucumber,Cucumber是一個能夠用自然語言編寫實例的協作工具,其核心思想是行為驅動開發(BDD),回歸測試是其自然而然的副帶結果。你可以簡單的理解為Calabash-android 或 Calabash-iOS是在Cucumber上進行了一次擴展,從而可以對Android或iOS進行自動化測試。

在解釋一下BDD,我從網絡摘了一段介紹: 你可以在Cucumber中編寫用戶場景,讓它表現出業務規則而不僅僅是UI功能。這樣你就能夠讓業務分析師加入這個過程,在編碼工作開始前編寫場景。程序員們就能夠按照這個清晰的規范進行編碼工作了。這種方式就是行為驅動開發(BDD)。

OK,關于BDD我們就此打住,畢竟還是很未來的事情,下面我們聊點實在的。

Calabash與appium,Espresso類似,都是通過腳本去操作界面,作出點擊、滑動等操作,同時可以對界面的上UI組件進行一定識別。run起來就是那么回事,模擬控制手機。主要是腳本的編寫上不同,我們來看一下Calabash的腳本, 相信我,愛上它,就從看到它腳本開始

Feature: Login feature

  Scenario: 登錄測試用例

    When I press view with id "account_edit"
    Then I enter "15104053650流量" into input field number 1

    Then I press "發送驗證碼"
    Then I wait for 5 seconds

    When I press view with id "verifying_code_edit"
    Then I enter "306423" into input field number 2

    Then I wait for 5 seconds

    Then I press view with id "login_login"

我覺得我不需要再解釋這腳本的含義了,這就是大白話!!

Calabash最大的魅力在于,將難以理解的編程語言轉換為誰都可以看得懂得自然語言。從而降低學習門檻和維護難度。

特點1:極高的可讀性,可讀性越高的測試腳本,意義越大。當測試腳本的編寫先于或與開發同步時,測試腳本也可以成為開發過程中的設計文檔及參考手冊。

在可讀性非常高的基礎上,其編寫難度也變得非常的低。 特點2:語法簡單易懂,誰都能寫

同時可喜的是,這個代碼同時支持Android 和iOS,web也有一定的支持!RN就更不用說了,跑起來的RN就是原生代碼!WEEX還要再考察考察~在合理的解耦與耦合的情況下,Android 和iOS只需提供一套各自的View定位封裝即可共用一套場景case腳本。 特點3:支持多種平臺,代碼復用性強

一段使用自然語言編寫的腳本,其底層當然要費一番功夫。上面我們看到一段測試用例是使用Calabash預定義的Steps寫的一段測試用例。

而這些大白話一樣的Steps的實質是這樣的:

Then /^I press "([^\"]*)"$/ do |identifier|  # ---方法名
  tap_when_element_exists("* marked:'#{identifier}'")  # ---方法體
end

很傻瓜的解釋一下:你可以很簡單的認為上面這一段是一個函數、一個方法。

第一行就是一個自然語言夾雜著正則符號的方法名,方法名隨便起。第二行是用Ruby實現的方法體。

不要被這段代碼嚇到,在大部分時候,你都不需要接觸到這些大白話的具體實現(Ruby語言),而是直接用大白話寫小作文就好了。

預定義的Steps肯定不能滿足我們的需求,所以Calabash靈活的支持 不同程度自定義steps ,樣子大概就像上面那樣,你可以簡單理解為Calabash支持不同程度的,代碼到自然語言的轉換。最大程度的滿足業務需求。

正是這種靈活的轉換方式,讓我們有了更多的想象:

特點4:Steps的開發與腳本的開發解耦分離,降低入門門檻,容納更多的腳本開發人員

再簡單解釋一下:先讓一部分(實際情況可能是一個)人學起來,寫出一個個大白話似的Steps。再接納另一部分人進來,比如其他的開發或測試人員,甚至是產品經理!直接用這些大白話寫測試case,熟悉了之后有想法的話再去學自定義Steps。甚至產品都不需要學自定義Steps,給開發提需求好了,當你有一個非常豐富的Steps庫的時候,你所煩的無窮無盡的邊界case,不過就是全民小作文~

特點5:自定義語法糖

Steps的方法名定義完全自由,在帶來可讀性提高的同時也降低了Steps的記憶和腳本編寫速度。但這其實完全依賴于你定義的規范,你完全可以自定義一套符合大多數人習慣的語法糖,從而在保證可讀性的同時固化大部分指令格式,提高Steps的記憶和腳本編寫速度。

還有哦,如果你一直抱怨現在正在使用的某種語言的某個語法多么的沒人性,使用體驗糟糕透頂!現在好了,做好開發一套屬于自己的語言的準備了嘛?

特點6:維護簡單,我不知道小作文維護起來有什么難的~

特點7:case也有設計感,不在那么枯燥

在加一個最起碼我覺得很興奮的特點,考慮復用的話,自定義的Steps就要考慮與業務的解耦問題了,有的要解耦有的卻要耦合一點。而且如果為了最小程度修改代碼從而保證Android iOS在代碼上通用,Android和iOS的開發上就會有更多的交流,測試腳本的編寫也會有更通用的設計。這里面就有設計的快感了。

特點8:除模擬事件以外,Calabash還支持各種hook,如App生命周期的hook

特點9:豐富的元素定位輔助方法。

App自動化測試一個普遍的痛點就是元素定位,Calabash有非常多的元素定位輔助方法,且都較為簡單且無腦。

最后我們在看一個從網上摘下來的一段Calabash腳本:

Feature: 登陸

        Scenario: 輸入正確的用戶名密碼能夠正常登陸

        When 打開登陸頁面
        And    輸入用戶名XXX輸入密碼XXX
        And   點擊登陸
        Then  驗證登陸成功

完全純中文的腳本編寫有木有?是不看起來屌屌的~恩,雖然博主自身并不建議這樣純中文的step定義,我們就看看,你只要知道Calabash很強大就行了。

最后我們總結一下Calabash的大方向的優點:

  • 極高的可讀性
  • 語法簡單易懂,學習門檻低
  • 一種語言支持多種平臺,代碼復用性強
  • Steps的開發與腳本的開發解耦分離,降低入門門檻,容納更多的開發
  • 自定義語法糖
  • 小作文維護簡單
  • case也有設計感
  • 除模擬事件以外,Calabash還支持各種hook,如App生命周期的hook
  • 非常多的元素定位輔助方法
  • 對代碼無侵入性,純黑盒測試。
  • 用Calabash搭一個自有的云測平臺可行性很高

這只是大方向的幾個優點,文末會奉上Calabash的入門文章,更詳細的介紹Calabash的各種特性,利用這些特性,你會發現Calabash有太多的想象。

Calabash缺點

說了那么多優點,缺點當然也是有的啦~我們吐槽一下

資料、Demo稀少

Calabash大概有五年以上的歷史,最早的first commit是2012年2月份,對于一個技術工具來說,這已經可以算是很老了,但Calabash依然是一個小眾產品,然后導致的問題是資料非常非常少……官方Github只給了很簡單很基礎的API,還基本沒有Demo,(官方Demo就幾行代碼~)

資料少也意味著后面有很多坑需要自己往過趟,不過有了文末的入門教程,快速上手應該是沒問題啦~

我大膽的懷疑了一下Calabash小眾的原因,可能大廠還是更鐘愛appium這種主流測試框架,畢竟語法復雜也意味著功能強大,而小廠呢,相比起維護一套自動化測試框架,不如就手點點人工測試好了,所以Calabash這樣的,就處于一個很尷尬的位置了(這篇文章不就是讓你破解這種尷尬的嘛!)

不支持跨進程

Calabash底層是Robotium,Robotium不支持跨進程操作,所以Calabash也不支持。當你跳出當前測試App時,calabash便無法響應并做任何操作了。

在個別需要跨進程調用業務較多的App中,這個點是很痛的,甚至基本上就可以放棄Calabash了。

以蜂鳥眾包為例,需要跨進程的業務有分享和拍照(拍照調用了系統相機),分享對于蜂鳥眾包來說是一個很邊界的業務,暫不討論,但拍照影響到了主流程。

不過如果修改拍照為自定義相機,而是不調用系統相機的話,將不會存在這個問題,并且可以解決不同手機系統相機樣式不同,腳本需要進行兼容的困擾。所以即使是為了測試而對業務代碼做了這種程度的改動,也是值得的!

另外通過最近研究發現, Calabash支持跨進程似乎也是有希望的! Espresso實現跨進程操作的方式是調用了uiautomator的API。而Calabash作為開源項目,想要修改其源碼也是完全OK的。 以Android為例,其內部核心是通過java調用Robotium API實現的,所以我們只要修改其源碼調用uiautomator的API即可實現跨進程。恩……實現思想是這樣的,只是不知道官方為什么沒有這樣去做,具體情況還待研究……(2015年底之前Calabash相關的博客中可以很容易的找到修改其源碼進行功能擴展的博客,但Calabash在2015年年底將Calabash的源碼抽離到了另一個項目中,所以這些博客中提到方案便無法使用了,后續的具體實現方式還待研究,詳情會在文末的教程中提到)

不夠嚴謹的自然語言

可能大部分人會對Calabash這樣的自然語言抱有懷疑,認為Calabash這樣Cucumber風格的語言(就是上面的我們看到的測試腳本)不夠嚴謹。無法向代碼那樣簡練且規范嚴格,在某種程度也降低了編寫速度,且非常不夠嚴謹易錯度高!

首先要澄清一點的是,Java、Python等隸屬編程語言,而Cucumber風格的腳本更傾向于是一種描述性語言。他們是兩種不同的領域。

所以不能站在編程語言的角度去要求Cucumber風格的腳本的嚴謹程度,而“嚴謹”也不過是作為編程人員的一種慣性思維。

而從記憶與編寫速度考慮,還記得我們上面曾說到的語法糖嗎?不恰當的定義Steps確實會導致這樣的問題。舉個例子吧

#我跳過歡迎界面
Then I skip welcome page
#我完成登錄操作
Then I have finished the login

上面是兩個濫用自然語言特性的自定義操作。如果你的所有測試腳本都是這樣寫的,雖然讀起來沒有問題,但寫起來就完全離不開文檔了。下面看一下較為建議的寫法:

#我跳過歡迎界面
Then I pass "welcome" scenario
#我完成登錄操作
Then I pass "login" scenario

兩個Steps的實際含義其實僅只是直接通過某種操作,如果我們規范的定義適合自己的語法糖,非常雜亂的腳本將變得很有規律可循,保證可讀性的同時你只需記住幾個特定的指令,從而提高腳本編寫速度。

當然,確實是因為Calabash過于寬松的語法,導致這個致命的缺點需要通過嚴格的管理進行約束,稍有不慎會埋有禍根。所以這確實是Calabash的缺點之一。

End

最后,雖然我個人建議使用Calabash,但對于小微團隊, 合適的才是最好的! 資源緊張情況下想要實行自動化測試,我的建議是在提高人效的基礎上調動更多的人力來分攤壓力。那么這對低學習門檻和低推廣成本的要求就會很高,所以學習門檻和推廣成本應該是你選擇自動化工具最需要考察的點。

正是因為Calabash的特性非常契合這兩點,我才會極力推薦,同時如果你想在未來的某一天嘗試一下BDD這種思想,或者想讓產品經理參與到這個環節做一些嘗試,同樣是非常建議使用Calabash的。當然如果你有較為寬松的資源、或者追求更加工程化的自動化測試,還可以選擇Appium這樣主流的測試工具。還是那句話: 合適的才是最好的!

 

 

來自:http://lrd.ele.me/2017/03/21/小微團隊怎么玩轉App自動化測試/

 

 本文由用戶 camb1186 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!