契約測試框架-Pact實(shí)踐_第1頁
契約測試框架-Pact實(shí)踐_第2頁
契約測試框架-Pact實(shí)踐_第3頁
契約測試框架-Pact實(shí)踐_第4頁
契約測試框架-Pact實(shí)踐_第5頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、 契約測試框架-Pact實(shí)踐dotNET跨平臺 微信號 opendotnet功能介紹 在這里你可以談微軟.NET,Mono的跨平臺開發(fā)技術(shù),也可以談?wù)勂渌目缙脚_技術(shù)。 在這里可以讓你的.NET項(xiàng)目有新的思路,不局限于微軟的技術(shù)棧,橫跨Windows,Linux 主流平臺本文將介紹一個開源的契約測試框架Pact,它最初是用ruby語言實(shí)現(xiàn)的,后來被js,C#,java,go,python 等語言重寫,此文將介紹Pact框架的相關(guān)知識并結(jié)合示例代碼講解在實(shí)際項(xiàng)目中應(yīng)該怎么使用。Pact是什么?Pact是一個開源框架,最早是由澳洲最大的房地產(chǎn)信息提供商REA Group的開發(fā)者及咨詢師們共同創(chuàng)造。

2、REA Group的開發(fā)團(tuán)隊(duì)很早便在項(xiàng)目中使用了微服務(wù)架構(gòu),并在團(tuán)隊(duì)中對于敏捷和測試的重要性早已形成共識,因此設(shè)計(jì)出這樣的優(yōu)秀框架并應(yīng)用于日常工作中也是十分自然。Pact工具于2013年開始開源,發(fā)展到今天已然形成了一個小的生態(tài)圈,包括各種語言(Ruby/Java/.NET/JavaScript/Go/Scala/Groovy.)下的Pact實(shí)現(xiàn),契約文件共享工具Pact Broker等。Pact的用戶已經(jīng)遍及包括RedHat、IBM、Accenture等在內(nèi)的若干知名公司,Pact已經(jīng)是事實(shí)上的契約測試方面的業(yè)界標(biāo)準(zhǔn)。Pact可以用來做什么?Pact是支持消費(fèi)者驅(qū)動的契約測試框架,針對微服務(wù)

3、的模式下多個單獨(dú)服務(wù)的接口契約測試以及前后端分離的模式提供了很好的支持。Pact的工作原理消費(fèi)者端作為數(shù)據(jù)的最終使用者非常清楚,明確的知道需要的什么樣格式,類型的數(shù)據(jù),它將負(fù)責(zé)創(chuàng)建契約文檔(包含結(jié)構(gòu)和格式的json文件),服務(wù)提供端將根據(jù)消費(fèi)者端創(chuàng)建的契約文檔提供對應(yīng)格式的數(shù)據(jù)并返回給消費(fèi)者,通過契約檢查判斷如果服務(wù)端提供的數(shù)據(jù)和消費(fèi)者生成的契約不匹配,將拋出異常并提示給服務(wù)端??偨Y(jié)如下:在消費(fèi)者項(xiàng)目代碼中編寫單元測試,期望響應(yīng)設(shè)置于模擬的服務(wù)提供者上。在測試運(yùn)行時,模擬的服務(wù)將返回所期望的響應(yīng)。請求和所期望的響應(yīng)將會被寫入到一個“pact”文件中。pact文件中的請求隨后在提供者上進(jìn)行重放,

4、并檢查實(shí)際響應(yīng)以確保其與所期望響應(yīng)相匹配。Pact相關(guān)的術(shù)語 服務(wù)消費(fèi)者服務(wù)消費(fèi)者是指向另一組件(服務(wù)提供者)發(fā)起HTTP請求的組件。注意這并不依賴于數(shù)據(jù)的發(fā)送方式無論是GET還是PUT/POST/PATCH,消費(fèi)者都是HTTP請求的發(fā)起者。服務(wù)提供者服務(wù)提供者是指向另一組件(服務(wù)消費(fèi)者)的HTTP請求提供響應(yīng)的服務(wù)器。 模擬服務(wù)提供者模擬服務(wù)提供者用于在消費(fèi)者項(xiàng)目中的單元測試?yán)锬M真實(shí)的服務(wù)提供者,意味著不必需要真實(shí)的服務(wù)提供者就緒,就可以將類集成測試運(yùn)行起來。Pact文件Pact文件是指一個含有消費(fèi)者測試中所定義的請求和響應(yīng)被序列化后的JSON的文件,即契約。 Pact驗(yàn)證(契約驗(yàn)證)要對

5、一個Pact進(jìn)行驗(yàn)證,就要對Pact文件中所包含的請求基于提供者代碼進(jìn)行重放,然后檢查返回的響應(yīng),確保其與Pact文件中所期望響應(yīng)相匹配。 提供者狀態(tài)在對提供者重放某個給定的請求時,一個用于描述此時提供者應(yīng)具有的“狀態(tài)”(類似于夾具)的名字比如“when user ken does not exists”或“when user ken has a bank account”。提供者狀態(tài)的名字是在寫消費(fèi)者測試時被指定的,之后當(dāng)運(yùn)行提供者的pact驗(yàn)證時,這個名字將被用于唯一標(biāo)識在請求執(zhí)行前應(yīng)運(yùn)行的代碼塊。Pact適用的場景 當(dāng)你的團(tuán)隊(duì)同時負(fù)責(zé)開發(fā)服務(wù)消費(fèi)者與服務(wù)提供者,并且服務(wù)消費(fèi)者的需求被用來

6、驅(qū)動服務(wù)提供者的功能時,Pact對于在服務(wù)集成方面進(jìn)行設(shè)計(jì)和測試是最具價(jià)值 的。它是組織內(nèi)部 開發(fā)和測試微服務(wù),前后端分離項(xiàng)目的絕佳工具。Pact不適用的場景性能和壓力測試。服務(wù)提供者的功能測試這是服務(wù)提供者自己的測試應(yīng)該做的。Pact是用來檢查請求和響應(yīng)的內(nèi)容及格式。當(dāng)你在必須使用實(shí)際測試的API才能將數(shù)據(jù)載入服務(wù)提供者的情況下,因?yàn)槟愕姆?wù)提供者中存在了無法mock的第三方的依賴“透傳”API的測試,是指服務(wù)提供者僅將請求內(nèi)容傳遞到下游服務(wù)而不做任何驗(yàn)證。Pact使用實(shí)例下面將展示代碼示例,這是一個前后端分離的項(xiàng)目,前端使用javascript訪問后端api獲取數(shù)據(jù),后端使用.net We

7、bApi 提供數(shù)據(jù)的返回后端代碼:新建BookingController,返回一個預(yù)定對象的信息,訪問地址:http:/localhost:51502/api/bookingpublic class BookingController : ApiController / GET: Booking HttpGet public BookingModel Get() return new BookingModel() Id = 12, FirstName = Ken, LastName = Wang, Users = new List() new User() Name = asd, Age =

8、1 , new User() Name = asd, Age = 1 , new User() Name = kenwang, Age = 223, Address = shangxi road ; BookingModel 實(shí)體定義如下:publicclassBookingModelpublicintId get;set; publicstringFirstName get;set; publicstringLastName get;set; publicList Users get;set; publicclassUserpublicstringName get;set; publicst

9、ringAge get;set; publicstringAddress get;set; 返回對象格式如下:Id: 12,FirstName:Ken,LastName:Wang,Users: Name:asd,Age:1,Address: 0,Name:asd,Age:1,Address: 0,Name:kenwang,Age:223,Address:shanxi road服務(wù)端就好了,下面看消費(fèi)端實(shí)現(xiàn)client.js 負(fù)責(zé)發(fā)起調(diào)用請求來獲取數(shù)據(jù):const request = require(superagent)const API_HOST = process.env.API_HOST

10、 | http:/localhostconst API_PORT = 51502const moment = require(moment)const API_ENDPOINT = $API_HOST:$API_PORT/ Fetch provider dataconst fetchProviderData = () = return request .get($API_ENDPOINT/api/booking) .then(res) = var Users = ; Users.push( Name: user1, Age : 11 ); Users.push( Name: asd, Age

11、: 1 ); return Id: 12, FirstName: ken, LastName: wang, Users: Users , (err) = throw new Error(Error from response: $err.body) )module.exports = fetchProviderDataconsumer.js負(fù)責(zé)調(diào)用client.js的方法獲取數(shù)據(jù),拿到數(shù)據(jù)之后記錄日志const client = require(./client)client.fetchProviderData().then(response = console.log(response),

12、error = console.error(error)添加client.js的測試代碼,前面的工作原理部分講到契約的生成是依賴于消費(fèi)者端的測試代碼而生成,也就是說消費(fèi)者端通過單元測試既覆蓋了代碼邏輯,又幫助我們生成了契約文件。consumerPact.spec.js文件是對client的測試:const chai = require(chai)const path = require(path)const chaiAsPromised = require(chai-as-promised)const pact = require(pact)const expect = chai.expect

13、const API_PORT = process.env.API_PORT | 51502const fetchProviderData = require(./client)chai.use(chaiAsPromised)/ Configure and import consumer API/ Note that we update the API endpoint to point at the Mock Serviceconst LOG_LEVEL = process.env.LOG_LEVEL | WARNconst provider = pact( consumer: Consume

14、r Demo, provider: Provider Demo, port: API_PORT, log: path.resolve(process.cwd(), logs, pact.log), dir: path.resolve(process.cwd(), pacts), logLevel: LOG_LEVEL, spec: 2)/ Alias flexible matchers for simplicityconst somethingLike: like,eachLike: eachLike, term = pact.Matchersdescribe(Pact with Our Pr

15、ovider, () = before() = return provider.setup() ) describe(given data count 0, () = describe(when a call to the Provider is made, () = describe(and a valid date is provided, () = before() = return provider.addInteraction( uponReceiving: a request for JSON data, withRequest: method: GET, path: /api/b

16、ooking , willRespondWith: status: 200, headers: Content-Type: application/json; charset=utf-8 , body: Id: like(10), FirstName: like(ken), LastName: like(wang), Users: eachLike( Name: like(test), Age: like(10) ,min:1) ) ) it(can process the JSON payload from the provider, done = const response = fetc

17、hProviderData() expect(response).perty(Id, 10) ) it(should validate the interactions and create a contract, () = return provider.verify() ) ) ) ) / Write pact files to file after() = return provider.finalize() )okay,消費(fèi)者端的代碼已經(jīng)完成,我們來執(zhí)行一下consumer.js,成功之后便會生成對應(yīng)的contract文件,如下: consumer: name: Consumer De

18、mo , provider: name: Provider Demo , interactions: description: a request for JSON data, providerState: data count 0, request: method: GET, path: /api/booking , response: status: 200, headers: Content-Type: application/json; charset=utf-8 , body: Id: 10, FirstName: ken, LastName: wang, Users: Name:

19、test, Age: 10 , matchingRules: $.body.Id: match: type , $.body.FirstName: match: type , $.body.LastName: match: type , $.body.Users: min: 1 , $.body.Users*.*: match: type , $.body.Users*.Name: match: type , $.body.Users*.Age: match: type , metadata: pactSpecification: version: 2.0.0 這就是需要消費(fèi)端需要的數(shù)據(jù)格式,

20、而作為服務(wù)提供者提供給消費(fèi)者的數(shù)據(jù)必須滿足這樣的約束,否則就是測試失敗的,下面我們建立一個C# 的contract test的工程,然后測試消費(fèi)端和提供端是否匹配統(tǒng)一的契約。測試工程需要引用xUnit 和 PactNet的Nuget包,直接從Nuget server下載安裝就可以了,會把所有的依賴都添加進(jìn)來。新建BookingContractApiTesting 的class:private readonly ITestOutputHelper _output; public RetriveBookingApiContractTesting(ITestOutputHelper output) _output = output; Fact public void EnsureEventApiHonoursPactWithConsumer() const string serviceUri = http:/localhost:51502; var config = new PactVerifierConfig Outputters = new List new XUnitOutput(_output) , Verbose = false ; IPactVerifier pactVerifier = ne

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論