成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

組件測試:改建遺留系統的起點

開發 開發工具
在遺留系統中工作,無論是開發新功能,還是對舊功能進行修改,抑或是通過重構以期重拾其往日的雄風,都會面臨大量的挑戰。這些挑戰主要來自于流失的業務知識、失傳的技術和腐壞的代碼等。

在遺留系統中工作,無論是開發新功能,還是對舊功能進行修改,抑或是通過重構以期重拾其往日的雄風,都會面臨大量的挑戰。這些挑戰主要來自于流失的業務知識、失傳的技術和腐壞的代碼等。一般來說,改建遺留系統通常會先對其添加必要的測試,再開展重構和重新設計等一系列工序,從而提升其內建質量。

Martin Fowler 在微服務的測試策略的分享中,詳細討論了各種測試方法及其適用場景。在該討論中,他介紹了組件測試:

組件是在大型系統中封裝良好的、可獨立替換的中間子系統。對這樣的組件進行單獨的測試有很多好處,通過將測試范圍限制在組件之內,就能在對組件所封裝的行為進行驗收測試的同時,維持相較于高層測試更好的執行效率。在微服務架構中,組件也就是服務本身。

Martin Fowler 還按照測試時調用組件的方式,以及在對組件所依賴的存儲或服務構建測試替身時,測試替身位于進程內部還是進程外部來把組件測試分為進程內和進程外兩種形態。

改建遺留系統的起點

實踐中,為遺留系統添加單元測試和端到端的界面測試都會遇到其對應的困難,而我們發現組件測試卻能由于其關注行為的特點在單元測試和端到端測試之間取得平衡,對于改建遺留系統來說,它提供了一個不錯的起點。

避開單元測試實踐的被動

遺留系統從最初發布到現在,早已過去多年,當初的開發人員早已離開,徒留一段代碼給后來者。在遺留系統上的工作通常要求不能破壞現有其他功能,只能按要求“恰好”地修改。作為敏捷開發人員,***步的計劃就是使用單元測試來保障已有功能不被破壞。但團隊很快就會發現遺留系統使用的技術失傳已久,新的團隊中基本沒人了解,要基于這樣的技術來構建單元測試寸步難行。對于一個沒有任何自動化測試的老舊系統來說,往往也意味著其內部設計耦合度之高,想理解清楚就已經很吃力了,更遑論可測試性。

在下面的示例代碼里,我們無法方便地對其中的 StockService 中所依賴的 WebClient 實例進行模擬,從而無法對 GetUpdatedStock 的功能進行測試:

  1. public class StockService { 
  2.   public IEnumerable<Stock> GetUpdatedStock(){ 
  3.     var stockContent = new WebClient().DownloadString("https://stocks.com/stocks.json"); 
  4.     var stocks = JsonConvert.DeserializeObject<List<StockResponse>>(stockContent); 
  5.     return stocks.Select(ToStock); 
  6.   } 
  7.  
  8.   private static Stock ToStock(StockResponse resp) 
  9.   { 
  10.     //  對象轉換邏輯略 
  11.   } 
  12.  } 

另一方面,在老舊系統上的開發工作,往往也意味著接下來需要對其進行較大規模的重構,以利于更好的可維護性,更輕松地添加新功能。在這種背景之下,即使為系統添加了單元測試,接下來的重構又會使得細粒度的單元測試成為一種浪費——重構勢必要修改代碼設計,導致單元測試也需要跟著一起修改。

相比于單元測試的矛盾,組件測試關注 Web 應用本身的功能和行為,而不是其中某個單獨的層次。實際上,很多遺留系統甚至連清晰的層次化設計都沒有。組件測試對 Web 應用公開的 API 或 Web 頁面源碼測試,在避免陷入代碼細節設計不良帶來的被動局面的同時,能夠保障 Web 應用的行為的正確性,而這也正是我們為遺留系統添加單元測試想保障的。組件測試關注的是業務行為,而不是代碼實現細節。因此不會隨著代碼實現細節的變化而受到影響。所以組件測試不會限制重構手法的施展,也不會在調整設計時帶來額外的修改測試的負擔,相反它卻可以給重構提供有力的保障,幫助確保重構的安全性。

繞過端到端界面測試的窘境

在改建遺留系統開展的實踐中,不少團隊為了擺脫單元測試的被動局面,嘗試過為其添加端到端界面自動化測試的策略。這樣幾乎可以完全忽略代碼細節,而直接關注業務場景。相對來說,只需要能做到自動地部署 Web 應用和必要的依賴(比如數據庫),就可以對應用開展測試了。但實際執行過程中,團隊發現要為老舊系統構建這樣的一種環境,并不容易。端到端集成測試需要在真實的 Web 應用程序實例上運行測試,并且要求各項基礎設施也盡可能地真實,包括數據庫、緩存設施等。因此,要想讓端到端的集成測試在持續集成環境自動地運行,就要求應用程序及其所依賴的基礎設施有自動化部署的能力。老舊系統往往自動化程度很低,無法自動完成部署以開展端到端集成測試。即使 Web 應用本身的部署并不復雜,它依賴的其他服務也很難自動地部署,比如 SMTP 服務器等。

在測試金字塔中,端到端測試界面測試位于較高的層次。這意味著即使成功地構建了自動化的環境,還是會由于測試所依賴的資源較多,造成測試成本相對較高的狀況。由于端到端測試集成了系統的多個層次,測試用例的運行也就比低層次的測試用例更脆弱,而運行速度也會更慢。

這些挑戰和特點決定了我們很難在短時間里為遺留系統添加足夠的端到端界面測試案例以保障接下來的改建工作。在開展組件測試時,則完全不需要擔心端到端測試的這些問題。組件測試通過一定的方法模擬并隔離 Web 應用的外部依賴,避免了復雜的部署和配置外部依賴的過程。更小型、專用的模擬層的啟動和運行速度都可以根據測試的需求來定制;如果采用進程內的組件測試,更是可以進一步提高測試案例的運行效率與穩定性。

組件測試***實踐

把 Web 應用本身看作單元測試中的被測試的單元,將 Web 應用的外部依賴都用測試替身進行模擬和隔離,并按業務場景測試組件中提供的 API 或 Web 頁面的行為,即為組件測試。在進程內組件測試的實踐方法中,我們直接在測試代碼中自動地構建 Web 應用所需的依賴項,啟動被測試的服務,然后調用要測試的 API 并執行斷言。下面的代碼演示了這樣的測試的大體流程:動態地創建一個關系型數據庫,啟動 Web 應用,利用 Web 應用中 repository 的準備測試所需的數據,然后調用被測試的接口并對結果進行斷言。

  1. [Fact] 
  2. public async void should_handle_search_request_with_mocked_database() 
  3.   var sqliteConnection = DatabaseUtils.CreateInMemorryDatabase(out var databaseOptions); 
  4.   var appServices = SetupApplication(sqliteConnection, out var client); 
  5.  
  6.   var jim = new Employee {Id = 12Name = "Jim"}; 
  7.   appServices.GetService<IRepository<Employee>>().Save(jim); 
  8.  
  9.   var response = await client.GetAsync("/employees/search/im"); 
  10.   var employeeString = await response.Content.ReadAsStringAsync(); 
  11.    
  12.   Assert.Equal("Jim(id=12)", employeeString); 

在進程內運行的組件測試,可以選擇以合適的方式對 Web 應用的依賴進行模擬。以數據訪問層為例,我們可以直接對 DAO 類進行模擬,也可以在需要測試事務支持的時候為測試構建真實數據庫實例,并在測試運行結束時清理這些臨時創建的資源。既能享受上文所述的行為測試的穩定性,又可以獲得代碼級模擬的靈活性。

具體地,由于要在測試代碼中按需啟動應用程序,這對 Web 應用程序的基礎設施提出一些要求。如果我們基于 ASP.NET WEB API 或者 Spring Boot 等框架開發應用,那么框架就已經提供了這種能力。對數據層進行模擬時,在簡單的情形中可以采用內存重新實現的 RepositoryStub,必要時也可以采用內存中運行的嵌入式數據庫,例如 SqlLite 和 H2 數據庫,并且使用數據框架動態地在數據庫創建必要的表結構(Schema),Entify Framework Code First 以及 Hibernate 等流行的 ORM 框架均具有這樣的能力。對于外部的 HTTP 依賴,同樣可以采用臨時實現的 Stub 對象,也可以采用社區中流行的 mockhttp、Client-driver 這樣的工具庫。這里,本文也準備了一份簡單的示例程序供讀者參考,提供了 C# 版本和 Java 版本 可用。

組件測試在形式上看,是一種單元測試,而從測試范圍上看,它又是一種集成測試,在一些場合,我們形象地把它理解為“集成的單元測試”。但它與單元測試的關注點是有所區分的。在編寫組件測試的用例時,不要過于關注代碼邏輯細節,而應該從業務場景出發關注 Web 應用的行為。比如在一個用戶注冊的 API 進行測試時,可針對注冊 API 成功的場景測試給出的響應是正確的,并給用戶發送了一封確認郵件,而不是向 API 提供多個用戶名用例并測試哪些用戶名是合法的(那些應該由測試用戶名驗證程序的單元測試覆蓋)。

與進程內組件測試相比,進程外的組件測試則直接對部署后的服務進行測試,更具有集成性,但由于進程外的組件測試在運行之前需要對 Web 服務進行部署和啟動,因而其成本更大;測試運行時由于需要通過網絡調用,所以效率也會相對較低。所以在進程外運行組件測試并沒有什么優勢。它只是在進程內組件測試無法高效開展時的一種妥協。除非要改建的遺留系統的外部依賴無法高效地基于代碼進行設置、不能通過代碼在進程內啟動,否則應該優先采用進程內的組件測試。

總結

沒有人愿意每天與遺留系統為伍,但總有些約束讓我們不得不妥協。基于遺留系統開展工作,總是會遇到很多挑戰。在實踐中,我們發現在遺留系統的改建過程中,組件測試總是能夠在我們遭遇困境時,給出令人滿意的答案。

在實踐組件測試時,如果一開始不能做到在進程內進行組件測試,可以先從進程外開展,而后逐步實現更穩定高效的進程內組件測試。需要注意的是,組件測試在改建遺留系統的過程中,能成為在現時約束下的一種可貴折衷。但它并不能代替其他類型的測試,我們依然需要借助其他類型的測試來對應用進行更完整的保障。組件測試只測試了應用(組件)內部的行為,因而在必要時可能要采用契約測試等方式來關注系統間的交互行為的正確性。在開發新功能時,我們還是要優先考慮成本最小、最利于保障系統設計的單元測試;而在保障業務場景時,必要的端到端界面測試依然是必不可少的。

【本文是51CTO專欄作者“ThoughtWorks”的原創稿件,微信公眾號:思特沃克,轉載請聯系原作者】

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2022-07-08 09:41:20

遺留系統服務拆分

2010-09-06 16:35:58

SQL函數

2021-01-15 11:01:42

IT系統漏洞網絡攻擊

2022-01-13 09:49:40

遺留系統交接開發

2023-06-25 12:22:25

IT領導者CIO

2021-07-09 05:25:48

CIO遺留系統現代化用戶體驗

2022-08-24 09:50:40

系統運維

2024-04-12 10:03:48

2022-11-09 10:02:21

CDC遺留系統

2020-09-27 14:00:44

代碼

2021-06-27 17:20:20

遺留系統隱形成本CIO

2013-09-12 09:39:38

遺留系統云遷移API

2014-02-13 09:47:41

GartnerERP云ERP

2020-11-30 10:13:17

ITCIO首席信息官

2021-12-27 11:02:00

首席信息官技術發展企業管理者

2013-09-16 13:18:28

遺留系統系統遷移

2013-11-11 09:59:29

Boni Satani遺留系統系統遷移

2010-09-01 16:08:03

遺留系統Java

2022-07-14 08:16:24

Node.js后端自動化測試

2020-03-09 14:10:48

代碼開發工具
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产高清在线视频 | 国产在线中文字幕 | 成人免费淫片aa视频免费 | 国产成人精品一区二区在线 | 成人在线中文字幕 | 国产欧美在线播放 | 日韩欧美一级 | 正在播放亚洲 | 亚洲久久一区 | 精品在线视频播放 | 精品乱子伦一区二区三区 | 久久99精品久久久久久国产越南 | av在线一区二区三区 | 久久精品久久综合 | 欧美一区二区三 | 日日骚网| 国产精品激情 | 中文字幕视频在线 | 成人国产精品久久久 | 免费黄色的视频 | 亚洲国产精品一区 | 女同久久另类99精品国产 | 亚洲视频三 | 日本一区二区高清视频 | jav成人av免费播放 | 午夜爽爽爽男女免费观看 | 四虎永久在线精品免费一区二 | 欧美一级高潮片免费的 | 亚洲福利在线观看 | 自拍偷拍中文字幕 | 成人高清在线 | 国产视频二区在线观看 | 日韩精品一区二区三区久久 | 日韩一区二区在线免费观看 | 不卡视频一区二区三区 | 成人精品鲁一区一区二区 | 久久久噜噜噜www成人网 | 国产97视频在线观看 | 一级欧美 | 欧美日韩综合一区 | 亚洲成人精品免费 |