一、軟件測試
1、軟件測試的目的
軟件測試是在軟件投入運行前,對軟件需求分析、設計規格說明和編碼的最終復審,它是軟件質量保證的關鍵步驟。測試要求以較少的用例、時間和人力找出軟件中潛在的各種錯誤和缺陷,以確保系統的質量。
軟件測試的目的決定了如何去組織測試。如果測試的目的是為了盡可能多地找出錯誤,那么測試就應該直接針對軟件比較復雜的部分或是以前出錯比較多的位置。如果測試目的是為了給最終用戶提供具有一定可信度的質量評價,那么測試就應該直接針對在實際應用中會經常用到的商業假設。這里引用Grenford J. Myers在《The Art of Software Testing》一書中的觀點:
、、軟件測試是為了發現錯誤而執行程序的過程;
、、測試是為了證明程序有錯,而不是證明程序無錯誤。
、、一個好的測試用例是在于它能發現至今未發現的錯誤;
、、一個成功的測試是發現了至今未發現的錯誤的測試。
軟件測試是一項細致并需要高度技巧的工作,稍有不慎就會顧此失彼,發生不應有的疏漏。軟件工程的總目標是充分利用有限的人力和物力資源,高效率、高質量地完成測試。為了降低測試成本,選擇測試用例時應注意遵守"經濟性"的原則。
2、軟件測試的分類
從測試的類型來看,測試分為2種:黑盒測試和白盒測試。
黑盒測試又稱為功能測試或數據驅動測試,把系統看成一個黑盒子,不考慮程序的內在邏輯,只根據需求規格說明書的要求來檢查程序的功能是否符合它的功能說明。
白盒測試又稱為結構測試和邏輯驅動測試,允許測試人員對程序內部邏輯結構及有關信息來設計和選擇測試用例,對程序的邏輯路徑進行測試。
從測試實際的前后過程來看,軟件測試上是由一系列的不同測試所組成,這些軟件測試的步驟分為:單元測試、組裝測試(集成測試)、確認測試和系統測試。
單元測試針對每個模塊進行的測試,通常在編碼階段進行,必要的時候要制作驅動模塊和樁模塊。集成測試在單元測試的基礎上,將所有模塊按照設計要求組裝成為系統,必須精心計劃,應提交集成測試計劃、集成測試規格說明和集成測試分析報告。確認測試驗證軟件的功能和性能及其它特性是否與用戶的要求一致,系統測試是在實際運行環境下進行一系列的測試。軟件開發的過程是自頂向下的,測試則正好相反,以上這些過程就是自底向上,逐步集成的
3、軟件測試工作的流程:
測試并不僅僅是為了要找出錯誤。通過分析錯誤產生的原因和錯誤的分布特征,可以幫助項目管理者發現當前所采用的軟件過程的缺陷,以便改進。同時,這種分析也能幫助我們設計出有針對性地檢測方法,改善測試的有效性。
沒有發現錯誤的測試也是有價值的,完整的測試是評定測試質量的一種方法。詳細而嚴謹的可靠性增長模型可以證明這一點。由此可見,軟件測試工作應該貫穿于整個軟件開發階段。
下面是軟件測試工作的總體流程圖和每個主要階段的流程圖:
二、單元測試
1、 什么是單元測試
單元測試是在軟件開發過程中要進行的最低級別的測試活動,測試的對象是軟件設計的最小單位——模塊。單元測試的依據是詳細設描述,單元測試應對模塊內所有重要的控制路徑設計測試用例,以便發現模塊內部的錯誤。在單元測試活動中,軟件的獨立單元將在與程序的其他部分相隔離的情況下進行測試。單元測試多采用白盒測試技術,系統內多個模塊可以并行地進行測試。
在一種傳統的結構化編程語言中,比如C,要進行測試的單元一般是函數或子過程。在象C++這樣的面向對象的語言中,要進行測試的基本單元是類。對Ada語言來說,開發人員可以選擇是在獨立的過程和函數,還是在Ada包的級別上進行單元測試。單元測試的原則同樣被擴展到第四代語言(4GL)的開發中,在這里基本單元被典型地劃分為一個菜單或顯示界面。
單元測試不僅僅是作為無錯編碼一種輔助手段在一次性的開發過程中使用,單元測試必須是可重復的,無論是在軟件修改,或是移植到新的運行環境的過程中。因此,所有的測試都必須在整個軟件系統的生命周期中進行維護。
經常與單元測試聯系起來的另外一些開發活動包括代碼走讀(Code review),靜態分析(Static analysis)和動態分析(Dynamic analysis)。靜態分析就是對軟件的源代碼進行研讀,查找錯誤或收集一些度量數據,并不需要對代碼進行編譯和執行。動態分析就是通過觀察軟件運行時的動作,來提供執行跟蹤,時間分析,以及測試覆蓋度方面的信息。
2、單元測試任務
單元測試任務包括:1 模塊接口測試;2 模塊局部數據結構測試;3 模塊邊界條件測試;4 模塊中所有獨立執行通路測試;5 模塊的各條錯誤處理通路測試。
模塊接口測試是單元測試的基礎。只有在數據能正確流入、流出模塊的前提下,其他測試才有意義。測試接口正確與否應該考慮下列因素:
1 輸入的實際參數與形式參數的個數是否相同;
2 輸入的實際參數與形式參數的屬性是否匹配;
3 輸入的實際參數與形式參數的量綱是否一致;
4 調用其他模塊時所給實際參數的個數是否與被調模塊的形參個數相同;
5 調用其他模塊時所給實際參數的屬性是否與被調模塊的形參屬性匹配;
6調用其他模塊時所給實際參數的量綱是否與被調模塊的形參量綱一致;
7 調用預定義函數時所用參數的個數、屬性和次序是否正確;
8 是否存在與當前入口點無關的參數引用;
9 是否修改了只讀型參數;
10 對全程變量的定義各模塊是否一致;
11是否把某些約束作為參數傳遞。
如果模塊內包括外部輸入輸出,還應該考慮下列因素:
1 文件屬性是否正確;
2 OPEN/CLOSE語句是否正確;
3 格式說明與輸入輸出語句是否匹配;
4緩沖區大小與記錄長度是否匹配;
5文件使用前是否已經打開;
6是否處理了文件尾;
7是否處理了輸入/輸出錯誤;
8輸出信息中是否有文字性錯誤;
檢查局部數據結構是為了保證臨時存儲在模塊內的數據在程序執行過程中完整、正確。局部數據結構往往是錯誤的根源,應仔細設計測試用例,力求發現下面幾類錯誤:
1 不合適或不相容的類型說明;
2變量無初值;
3變量初始化或省缺值有錯;
4不正確的變量名(拼錯或不正確地截斷);
5出現上溢、下溢和地址異常。
除了局部數據結構外,如果可能,單元測試時還應該查清全局數據(例如FORTRAN的公用區)對模塊的影響。
在模塊中應對每一條獨立執行路徑進行測試,單元測試的基本任務是保證模塊中每條語句至少執行一次。此時設計測試用例是為了發現因錯誤計算、不正確的比較和不適當的控制流造成的錯誤。此時基本路徑測試和循環測試是最常用且最有效的測試技術。計算中常見的錯誤包括:
1 誤解或用錯了算符優先級;
2混合類型運算;
3變量初值錯;
4精度不夠;
5表達式符號錯。
比較判斷與控制流常常緊密相關,測試用例還應致力于發現下列錯誤:
1不同數據類型的對象之間進行比較;
2錯誤地使用邏輯運算符或優先級;
3因計算機表示的局限性,期望理論上相等而實際上不相等的兩個量相等;
4比較運算或變量出錯;
5循環終止條件或不可能出現;
6迭代發散時不能退出;
7錯誤地修改了循環變量。
一個好的設計應能預見各種出錯條件,并預設各種出錯處理通路,出錯處理通路同樣需要認真測試,測試應著重檢查下列問題:
1輸出的出錯信息難以理解;
2記錄的錯誤與實際遇到的錯誤不相符;
3在程序自定義的出錯處理段運行之前,系統已介入;
4異常處理不當;
5錯誤陳述中未能提供足夠的定位出錯信息。
邊界條件測試是單元測試中最后,也是最重要的一項任務。眾的周知,軟件經常在邊界上失效,采用邊界值分析技術,針對邊界值及其左、右設計測試用例,很有可能發現新的錯誤。
3、單元測試的過程與環境
一般認為單元測試應緊接在編碼之后,當源程序編制完成并通過復審和編譯檢查,便可開始單元測試。測試用例的設計應與復審工作相結合,根據設計信息選取測試數據,將增大發現上述各類錯誤的可能性。在確定測試用例的同時,應給出期望結果。
應為測試模塊開發一個驅動模塊(driver)和(或)若干個樁模塊(stub),下圖顯示了一般單元測試的環境。驅動模塊在大多數場合稱為"主程序",它接收測試數據并將這些數據傳遞到被測試模塊,被測試模塊被調用后,"主程序"打印"進入-退出"消息。
驅動模塊和樁模塊是測試使用的軟件,而不是軟件產品的組成部分,但它需要一定的開發費用。若驅動和樁模塊比較簡單,實際開銷相對低些。遺憾的是,僅用簡單的驅動模塊和樁模塊不能完成某些模塊的測試任務,這些模塊的單元測試只能采用下面討論的綜合測試方法。
提高模塊的內聚度可簡化單元測試,如果每個模塊只能完成一個,所需測試用例數目將顯著減少,模塊中的錯誤也更容易發現。
三、集成測試的基本方法
時常有這樣的情況發生,每個模塊都能單獨工作,但這些模塊集成在一起之后卻不能正常工作。主要原因是,模塊相互調用時接口會引入許多新問題。例如,數據經過接口可能丟失;一個模塊對另一模塊可能造成不應有的影響;幾個子功能組合起來不能實現主功能;誤差不斷積累達到不可接受的程度;全局數據結構出現錯誤,等等。綜合測試是組裝軟件的系統測試技術,按設計要求把通過單元測試的各個模塊組裝在一起之后,進行綜合測試以便發現與接口有關的各種錯誤!
某設計人員習慣于把所有模塊按設計要求一次全部組裝起來,然后進行整體測試,這稱為非增量式集成。這種方法容易出現混亂。因為測試時可能發現一大堆錯誤,為每個錯誤定位和糾正非常困難,并且在改正一個錯誤的同時又可能引入新的錯誤,新舊錯誤混雜,更難斷定出錯的原因和位置。與之相反的是增量式集成方法,程序一段一段地擴展,測試的范圍一步一步地增大,錯誤易于定位和糾正,界面的測試亦可做到完全徹底。
下面討論兩種增量式集成方法。
1、自頂向下集成
自頂向下集成是構造程序結構的一種增量式方式,它從主控模塊開始,按照軟件的控制層次結構,以深度優先或廣度優先的策略,逐步把各個模塊集成在一起。深度優先策略首先是把主控制路徑上的模塊集成在一起,至于選擇哪一條路徑作為主控制路徑,這多少帶有隨意性,一般根據問題的特性確定。以下圖為例,若選擇了最左一條路徑,首先將模塊M1,M2,M5和M8集成在一起,再將M6集成起來,然后考慮中間和右邊的路徑。廣度優先策略則不然,它沿控制層次結構水平地向下移動。仍以下圖為例,它首先把M2、M3和M4與主控模塊集成在一起,再將M5和M6 和其他模塊集資集成起來!
自頂向下綜合測試的具體步驟為:
1 以主控模塊作為測試驅動模塊,把對主控模塊進行單元測試時引入的所有樁模塊用實際模塊替代; 2 依據所選的集成策略(深度優先或廣度優先),每次只替代一個樁模塊; 3 每集成一個模塊立即測試一遍; 4 只有每組測試完成后,才著手替換下一個樁模塊; 5 為避免引入新錯誤,須不斷地進行回歸測試(即全部或部分地重復已做過的測試)! 從第二步開始,循環執行上述步驟,直至整個程序結構構造完畢。下圖中,實線表示已部分完成的結構,若采用深度優先策略,下一步將用模塊M7替換樁模塊S7,當然M7本身可能又帶有樁模塊,隨后將被對應的實際模塊一一替代!
自頂向下集成的優點在于能盡早地對程序的主要控制和決策機制進行檢驗,因此較早地發現錯誤。缺點是在測試較高層模塊時,低層處理采用樁模塊替代,不能反映真實情況,重要數據不能及時回送到上層模塊,因此測試并不充分。解決這個問題有幾種辦法,第一種是把某些測試推遲到用真實模塊替代樁模塊之后進行,第二種是開發能模擬真實模塊的樁模塊;第三種是自底向上集成模塊。第一種方法又回退為非增量式的集成方法,使錯誤難于定位和糾正,并且失去了在組裝模塊時進行一些特定測試的可能性;第二種方法無疑要大大增加開銷;第三種方法比較切實可行,下面專門討論。
2、自底向上集成
自底向上測試是從"原子"模塊(即軟件結構最低層的模塊)開始組裝測試,因測試到較高層模塊時,所需的下層模塊功能均已具備,所以不再需要樁模塊!
自底向上綜合測試的步驟分為:
1 把低層模塊組織成實現某個子功能的模塊群(cluster); 2 開發一個測試驅動模塊,控制測試數據的輸入和測試結果的輸出; 3 對每個模塊群進行測試; 4 刪除測試使用的驅動模塊,用較高層模塊把模塊群組織成為完成更大功能的新模塊群! 牡谝徊介_始循環執行上述各步驟,直至整個程序構造完畢! ∠聢D說明了上述過程。首先"原子"模塊被分為三個模塊群,每個模塊群引入一個驅動模塊進行測試。因模塊群1、模塊群2中的模塊均隸屬于模塊Ma,因此在驅動模塊D1、D2去掉后,模塊群1與模塊群2直接與Ma接口,這時可對MaD3被去掉后,M3與模塊群3直接接口,可對Mb進行集成測試,最后Ma、Mb和 Mc全部集成在一起進行測試。
自底向上集成方法不用樁模塊,測試用例的設計亦相對簡單,但缺點是程序最后一個模塊加入時才具有整體形象。它與自頂向綜合測試方法優缺點正好相反。因此,在測試軟件系統時,應根據軟件的特點和工程的進度,選用適當的測試策略,有時混和使用兩種策略更為有效,上層模塊用自頂向下的方法,下層模塊用自底向上的方法。
此外,在綜合測試中尤其要注意關鍵模塊,所謂關鍵模塊一般都具有下述一或多個特征:①對應幾條需求;②具有高層控制功能;③復雜、易出錯;④有特殊的性能要求。關鍵模塊應盡早測試,并反復進行回歸測試。
四、確認測試的基本方法
通過集成測試之后,軟件已完全組裝起來,接口方面的錯誤也已排除,確認測試即可開始。確認測試應檢查軟件能否按合同要求進行工作,即是否滿足軟件需求說明書中的確認標準。
1. 確認測試標準 實現軟件確認要通過一系列墨盒測試。確認測試同樣需要制訂測試計劃和過程,測試計劃應規定測試的種類和測試進度,測試過程則定義一些特殊的測試用例,旨在說明軟件與需求是否一致。無是計劃還是過程,都應該著重考慮軟件是否滿足合同規定的所有功能和性能,文檔資料是否完整、準確人機界面和其他方面(例如,可移植性、兼容性、錯誤恢復能力和可維護性等)是否令用戶滿意! 〈_認測試的結果有兩種可能,一種是功能和性能指標滿足軟件需求說明的要求,用戶可以接受;另一種是軟件不滿足軟件需求說明的要求,用戶無法接受。項目進行到這個階段才發現嚴重錯誤和偏差一般很難在預定的工期內改正,因此必須與用戶協商,尋求一個妥善解決問題的方法。
2. 配置復審 確認測試的另一個重要環節是配置復審。復審的目的在于保證軟件配置齊全、分類有序,并且包括軟件維護所必須的細節。
3. α、β測試 事實上,軟件開發人員不可能完全預見用戶實際使用程序的情況。例如,用戶可能錯誤的理解命令,或提供一些奇怪的數據組合,亦可能對設計者自認明了的輸出信息迷惑不解,等等。因此,軟件是否真正滿足最終用戶的要求,應由用戶進行一系列"驗收測試"。驗收測試既可以是非正式的測試,也可以有計劃、有系統的測試。有時,驗收測試長達數周甚至數月,不斷暴露錯誤,導致開發延期。一個軟件產品,可能擁有眾多用戶,不可能由每個用戶驗收,此時多采用稱為α、β測試的過程,以期發現那些似乎只有最終用戶才能發現的問題! ˇ翜y試是指軟件開發公司組織內部人員模擬各類用戶行對即將面市軟件產品(稱為α版本)進行測試,試圖發現錯誤并修正。α測試的關鍵在于盡可能逼真地模擬實際運行環境和用戶對軟件產品的操作并盡最大努力涵蓋所有可能的用戶操作方式。經過α測試調整的軟件產品稱為β版本。緊隨其后的β測試是指軟件開發公司組織各方面的典型用戶在日常工作中實際使用β版本,并要求用戶報告異常情況、提出批評意見。然后軟件開發公司再對β版本進行改錯和完善。
五、系統測試的基本方法
計算機軟件是基于計算機系統的一個重要組成部分,在系統測試之前,軟件工程師應完成下列工作:
為測試軟件系統的輸入信息設計出錯處理通路;
設計測試用例,模擬錯誤數據和軟件界面可能發生的錯誤,記錄測試結果,為系統測試提供經驗和幫助;
參與系統測試的規劃和設計,保證軟件測試的合理性!
系統測試應該由若干個不同測試組成,目的是充分運行系統,驗證系統各部件是否都能政黨工作并完成所賦予的任務。
下面簡單討論幾類系統測試。
1、恢復測試 恢復測試主要檢查系統的容錯能力。當系統出錯時,能否在指定時間間隔內修正錯誤并重新啟動系統;謴蜏y試首先要采用各種辦法強迫系統失敗,然后驗證系統是否能盡快恢復。對于自動恢復需驗證重新初始化(reinitialization)、檢查點(checkpointing mechanisms)、數據恢復(data recovery)和重新啟動 (restart)等機制的正確性;對于人工干預的恢復系統,還需估測平均修復時間,確定其是否在可接受的范圍內。
2、安全測試 安全測試檢查系統對非法侵入的防范能力。安全測試期間,測試人員假扮非法入侵者,采用各種辦法試圖突破防線。例如,①想方設法截取或破譯口令;②專門定做軟件破壞系統的保護機制;③故意導致系統失敗,企圖趁恢復之機非法進入;④試圖通過瀏覽非保密數據,推導所需信息,等等。理論上講,只要有足夠的時間和資源,沒有不可進入的系統。因此系統安全設計的準則是,使非法侵入的代價超過被保護信息的價值。此時非法侵入者已無利可圖。
3、強度測試 強度測試檢查程序對異常情況的抵抗能力。強度測試總是迫使系統在異常的資源配置下運行。例如,①當中斷的正常頻率為每秒一至兩個時,運行每秒產生十個中斷的測試用例;②定量地增長數據輸入率,檢查輸入子功能的反映能力;③運行需要最大存儲空間(或其他資源)的測試用例;④運行可能導致虛存操作系統崩潰或磁盤數據劇烈抖動的測試用例,等等。
4、 性能測試 對于那些實時和嵌入式系統,軟件部分即使滿足功能要求,也未必能夠滿足性能要求,雖然從單元測試起,每一測試步驟都包含性能測試,但只有當系統真正集成之后,在真實環境中才能全面、可靠地測試運行性能系統性能測試是為了完成這一任務。性能測試有時與強度測試相結合,經常需要其他軟硬件的配套支持。
六、軟件測試自動化的一些具體做法
因為軟件測試的工作量很大(40% 到60% 的總開發時間),而又有很大部分適于自動化,因此,測試的改進會對整個開發工作的質量、成本和周期帶來非常顯著的效果!
下面舉出一些測試自動化的例子:
1. 測試個案(test case ,或稱為測試用例)的生成
用編程語言或更方便的劇本語言(script language 例如Perl等)寫出短小的程序來產生大量的測試輸入(包括輸入數據與操作指令);蛲瑫r也按一定的邏輯規律產生標準輸出。輸入與輸出的文件名字按規定進行配對,以便控制自動化測試及結果核對的程序易于操作! ∵@里提到測試個案的命名問題,如果在項目的文檔設計中作統一規劃的話,軟件產品的需求與功能的命名就應該成為后繼開發過程的中間產品的命名分類依據。這樣,就會為文檔管理和配置管理帶來很大的方便,使整個產品的開發過程變得更有條理,更符合邏輯。任何新手半途加入到開發工作中也會更容易進入狀態。
2. 測試的執行寫控制
單元測試或集成測試可能多用單機運行。但對于系統測試或回歸測試,就極有可能需要多臺機在網絡上同時運行。記住一個這樣的原則,在開發過程中的任何時候,如果你需要等候測試的運行結果的話,那就是一個縮短開發時間的機會。對于單個的測試運行,挖潛的機會在測試的設置及開始運行和結果的對比及顯示。有時候,需要反復修改程序,重新匯編和重新測試。這樣,每一個循環的各種手工鍵入的設置與指令所花費的時間,加起來就非?捎^。如果能利用make或類似的軟件工具來幫助,就能節省大量的時間。 對于系統測試或回歸測試這類涉及大量測試個案運行的情況,挖潛的的機會除了利用軟件工具來實現自動化之外,就是怎樣充分利用一切硬件資源。往往,就算是在白天的工作時間內,每臺計算機的負荷都沒有被充分利用。能夠把大量測試個案分配到各臺機器上去同時運行,就能節省大量的時間。另外,把大量的系統測試及回歸測試安排到夜間及周末運行,更能提高效率。如果不購買商品化的工具的話,應當遵從正規的軟件開發要求來開發出好的軟件測試自動化工具。在實踐中,許多企業自行開發的自動化工具都是利用一些現成的軟件工具再加上自己寫的程序而組成的。這些自己開發的工具完全是為本企業量身定做的,因此可用性非常強。同時,也能根據需要隨時進行改進,而不必受制于人。在設計軟件自動測試工具的時候,路徑(path)控制是一個非常重要的功能。理想的使用情況是:這個工具可以在任何一個路徑位置上運行,可以到任何路徑位置去取得測試用例,同時也可以把測試的結果輸出放到任何的路徑位置上去。這樣的設計,可以使不同的測試運行能夠使用同一組測試用例而不至于互相干擾,也可以靈活使用硬盤的空間,并且使備份保存工作易于控制。同時,軟件自動測試工具必須能夠有辦法方便地選擇測試用例庫中的全部或部分來運行,也必須能夠自由地選擇被測試的產品或中間產品采作為測試對象。
3. 測試結果與標準輸出的對比
在設計測試用例的時候,必須考慮到怎樣才能夠易于對此測試結果和標準輸出。輸出數據量的多少及數據格式對比較的速度有直接影響。而另一方面,也必須考慮到輸出數據與測試用例的測試目標的邏輯對應性及易讀性,這將會大大有利于分析測試所發現的不吻合,也有利于測試用例的維護! ≡S多時候,要寫一些特殊的軟件來執行測試結果與標準輸出的對比工作,因為可能有部分的輸出內容是不能直接對比的(比如,對運行的日期時間的記錄,對運行的路徑的記錄,以及測試對象的版本數據等),就要用程序進行處理。
4. 不吻合的測試結果的分析、分類、記錄和通報
上一點所談到的,用于對測試結果與標準輸出進行對比的特殊軟件,往往也同時擔任對不吻合的測試結果進行分析、分類、記錄和通報的任務。"分析"是找出不吻合的地方并指出錯誤的可能起因。"分類"包括各種統計上的分項,例如,對應的源程序的位置,錯誤的嚴重級別(提示、警告、非失效性錯誤、失效性錯誤;或別的分類方法),新發現的還是已有記錄的錯誤,等等。"記錄",是按分類存檔。"通報",是主動地對測試的運行者及測試用例的"負責人"通報出錯的信息! 這里提到測試用例的"負責人"的概念。是用以指定一個測試用例運行時發現的缺陷,由哪一個開發人員負責分析(有時是另外的開發人員引進的缺陷而導致的錯誤)及修復。在設立測試用例庫時,各用例均應有指定的負責人! ∽钪苯拥耐▓蠓椒ㄊ怯自動測試軟件發出電子郵件給測試運行者及測試用例負責人。郵件內容的詳細程度可根據需要靈活決定。
5. 總測試狀況的統計,報表的產生
這些都是自動測試工具所應有的功能。目的是提高過程管理的質量,同時節省用于產生統計數據的時間。產生出來的統計報表,最好是存放到一個約定的路徑位置,以便任何有關人員都知道怎樣查閱。同時,可按需要用電子郵件向適當的對象(如項目經理,測試經理和質量保證經理)寄出統計報表。
文章來源于領測軟件測試網 http://www.kjueaiud.com/
版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
技術支持和業務聯系:info@testage.com.cn 電話:010-51297073
老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月