日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lego-美团接口自动化测试实践

發布時間:2024/7/5 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lego-美团接口自动化测试实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、概述

1.1 接口自動化概述

眾所周知,接口自動化測試有著如下特點:

  • 低投入,高產出。
  • 比較容易實現自動化。
  • 和UI自動化測試相比更加穩定。

如何做好一個接口自動化測試項目呢?

我認為,一個“好的”自動化測試項目,需要從“時間”“人力”“收益”這三個方面出發,做好“取舍”。

不能由于被測系統發生一些變更,就導致花費了幾個小時的自動化腳本無法執行。同時,我們需要看到“收益”,不能為了總想看到100%的成功,而少做或者不做校驗,但是校驗多了維護成本一定會增多,可能每天都需要進行大量的維護。

所以做好這三個方面的平衡并不容易,經常能看到做自動化的同學,做到最后就本末倒置了。

1.2 提高ROI

想要提高ROI(Return On Investment,投資回報率),我們必須從兩方面入手:

  • 減少投入成本。
  • 增加使用率。
  • 針對“減少投入成本”

    我們需要做到:

    • 減少工具開發的成本。盡可能的減少開發工具的時間、工具維護的時間,盡可能使用公司已有的,或是業界成熟的工具或組件。
    • 減少用例錄入成本。簡化測試用例錄入的成本,盡可能多的提示,如果可以,開發一些批量生成測試用例的工具。
    • 減少用例維護成本。減少用例維護成本,盡量只用在頁面上做簡單的輸入即可完成維護動作,而不是進行大量的代碼操作。
    • 減少用例優化成本。當團隊做用例優化時,可以通過一些統計數據,進行有針對性、有目的性的用例優化。

    針對“增加使用率”

    我們需要做到:

    • 手工也能用。不只是進行接口自動化測試,也可以完全用在手工測試上。
    • 人人能用。每一個需要使用測試的人,包括一些非技術人員都可以使用。
    • 當工具用。將一些接口用例當成工具使用,比如“生成訂單”工具,“查找表單數據”工具。
    • 每天測試。進行每日構建測試。
    • 開發的在構建之后也能觸發測試。開發將被測系統構建后,能自動觸發接口自動化測試腳本,進行測試。

    所以,我這邊開發了Lego接口測試平臺,來實現我對自動測試想法的一些實踐。先簡單瀏覽一下網站,了解一下大概是個什么樣的工具。

    1.3 Lego的組成

    Lego接口測試解決方案是由兩部分組成的,一個就是剛剛看到的“網站”,另一個部分就是“腳本”。

    下面就開始進行“腳本設計”部分的介紹。

    二、腳本設計

    2.1 Lego的做法

    Lego接口自動化測試腳本部分,使用很常見的Jenkins+TestNG的結構。

    相信看到這樣的模型并不陌生,因為很多的測試都是這樣的組成方式。

    將自動化測試用例存儲至MySQL數據庫中,做成比較常見的“數據驅動”做法。

    很多團隊也是使用這樣的結構來進行接口自動化,沿用的話,那在以后的“推廣”中,學習和遷移成本低都會比較低。

    2.2 測試腳本

    首先來簡單看一下目前的腳本代碼:

    public class TestPigeon {String sql;int team_id = -1;@Parameters({"sql", "team_id"})@BeforeClass()public void beforeClass(String sql, int team_id) {this.sql = sql;this.team_id = team_id;ResultRecorder.cleanInfo();}/*** XML中的SQL決定了執行什么用例, 執行多少條用例, SQL的搜索結果為需要測試的測試用例*/@DataProvider(name = "testData")private Iterator<Object[]> getData() throws SQLException, ClassNotFoundException {return new DataProvider_forDB(TestConfig.DB_IP, TestConfig.DB_PORT, TestConfig.DB_BASE_NAME,TestConfig.DB_USERNAME, TestConfig.DB_PASSWORD, sql);}@Test(dataProvider = "testData")public void test(Map<String, String> data) {new ExecPigeonTest().execTestCase(data, false);}@AfterMethodpublic void afterMethod(ITestResult result, Object[] objs) {...}@AfterClasspublic void consoleLog() {...} }

    有一種做法我一直不提倡,就是把測試用例直接寫在Java文件中。這樣做會帶來很多問題:修改測試用例需要改動大量的代碼;代碼也不便于交接給其他同學,因為每個人都有自己的編碼風格和用例設計風格,這樣交接,最后都會變成由下一個同學全部推翻重寫一遍;如果測試平臺更換,無法做用例數據的遷移,只能手動的一條條重新輸入。

    所以“測試數據”與“腳本”分離是非常有必要的。

    網上很多的范例是使用的Excel進行的數據驅動,我這里為什么改用MySQL而不使用Excel了呢?

    在公司,我們的腳本和代碼都是提交至公司的Git代碼倉庫,如果使用Excel……很顯然不方便日常經常修改測試用例的情況。使用MySQL數據庫就沒有這樣的煩惱了,由于數據與腳本的分離,只需對數據進行修改即可,腳本每次會在數據庫中讀取最新的用例數據進行測試。同時,還可以防止一些操作代碼時的誤操作。

    這里再附上一段我自己寫的DataProvider_forDB方法,方便其他同學使用在自己的腳本上:

    import java.sql.*; import java.util.HashMap; import java.util.Iterator; import java.util.Map;/*** 數據源 數據庫** @author yongda.chen*/ public class DataProvider_forDB implements Iterator<Object[]> {ResultSet rs;ResultSetMetaData rd;public DataProvider_forDB(String ip, String port, String baseName, String userName, String password, String sql) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");String url = String.format("jdbc:mysql://%s:%s/%s", ip, port, baseName);Connection conn = DriverManager.getConnection(url, userName, password);Statement createStatement = conn.createStatement();rs = createStatement.executeQuery(sql);rd = rs.getMetaData();}@Overridepublic boolean hasNext() {boolean flag = false;try {flag = rs.next();} catch (SQLException e) {e.printStackTrace();}return flag;}@Overridepublic Object[] next() {Map<String, String> data = new HashMap<String, String>();try {for (int i = 1; i <= rd.getColumnCount(); i++) {data.put(rd.getColumnName(i), rs.getString(i));}} catch (SQLException e) {e.printStackTrace();}Object r[] = new Object[1];r[0] = data;return r;}@Overridepublic void remove() {try {rs.close();} catch (SQLException e) {e.printStackTrace();}} }

    2.3 配置文件

    上面圖中提到了“配置文件”,下面就來簡單看一下這個XML配置文件的腳本:

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="Pigeon Api測試" parallel="false"><test name="xxx-xxx-service"><parameter name="sql"value="SELECT * FROM API_PigeonCases WHERE team_id=2AND isRun=1AND service='xxx-xxx-service'AND env='beta';"/><classes><class name="com.dp.lego.test.TestPigeon"/></classes></test><listeners><listener class-name="org.uncommons.reportng.HTMLReporter"/><listener class-name="org.uncommons.reportng.JUnitXMLReporter"/></listeners> </suite>

    對照上圖來解釋一下配置文件:

    • SQL的話,這里的SQL主要決定了選取哪些測試用例進行測試。
    • 一個 標簽,就代表一組測試,可以寫多個 標簽。
    • “listener”是為了最后能夠生成一個ReportNG的報告。
    • Jenkins來實現每日構建,可以使用Maven插件,通過命令來選擇需要執行的XML配置。

    這樣做有什么好處呢?

    使用SQL最大的好處就是靈活

    如上面的這個例子,在數據庫中會查詢出下面這56條測試用例,那么這個 標簽就會對這56條用例進行逐一測試。

    多<test>標簽時,可以分組展示

    使用多個<test>標簽來區分用例,最大的好處就是也能在最后的報告上,達到一個分組展示的效果。

    報告更美觀豐富

    由于使用了ReportNG進行報告的打印,所以報告的展示要比TestNG自帶的報告要更加美觀、并且能自定義展示樣式,點開能看到詳細的執行過程。

    如果有執行失敗的用例,通常報錯的用例會在最上方優先展示。

    支持多團隊

    當兩個團隊開始使用時,為了方便維護,將基礎部分抽出,各個團隊的腳本都依賴這個Base包,并且將Base包版本置為“SNAPSHOT版本”。使用“SNAPSHOT版本”的好處是,之后我對Lego更新,各個業務組并不需要對腳本做任何改動就能及時更新。

    當更多的團隊開始使用后,比較直觀的看的話是這個樣子的:

    每個團隊的腳本都依賴于我的這個Base包,所以最后,各個業務團隊的腳本就變成了下面的這個樣子:

    可以看到,使用了Lego之后:

    • 沒有了Java文件,只有XML文件
    • xml中只需要配置SQL。
    • 執行和調試也很方便。
    • 可以右鍵直接執行想要執行的測試配置。
    • 可以使用maven命令執行測試:
      • mvn clean test -U -Dxml=xmlFileName 。
      • 通過參數來選擇需要執行的xml文件。
    • 也可以使用Jenkins來實現定時構建測試。

    由于,所有測試用例都在數據庫所以這段腳本基本不需要改動了,減少了大量的腳本代碼量。

    有些同學要問,有時候編寫一條接口測試用例不只是請求一下接口就行,可能還需要寫一些數據庫操作啊,一些參數可能還得自己寫一些方法才能獲取到啊之類的,那不code怎么處理呢?

    下面就進入“用例設計”,我將介紹我如何通過統一的用例模板來解決這些問題。

    三、用例設計

    3.1 一些思考

    我在做接口自動化設計的時候,會思考通用、校驗、健壯、易用這幾點。

    通用

    • 簡單、方便
      • 用例數據與腳本分離,簡單、方便。
      • 免去上傳腳本的動作,能避免很多不必要的錯誤和維護時間。
      • 便于維護。
    • 模板化
      • 抽象出通用的模板,可快速拓展。
      • 數據結構一致,便于批量操作。
      • 專人維護、減少多團隊間的重復開發工作。
      • 由于使用了統一的模板,那各組之間便可交流、學習、做有效的對比分析。
      • 如果以后這個平臺不再使用,或者有更好的平臺,可快速遷移。
    • 可統計、可拓展
      • 可統計、可開發工具;如:用例數統計,某服務下有多少條用例等。
      • 可開發用例維護工具。
      • 可開發批量生成工具。

    校驗

    在寫自動化腳本的時候,都會想“細致”,然后“寫很多”的檢查點;但當“校驗點”多的時候,又會因為很多原因造成執行失敗。所以我們的設計,需要在保證充足的檢查點的情況下,還要盡可能減少誤報。

    • 充足的檢查點
      • 可以檢查出被測服務更多的缺陷。
    • 盡量少的誤報
      • 可以減少很多的人工檢查和維護的時間人力成本。
    • 還要
      • 簡單、易讀。
      • 最好使用一些公式就能實現自己想要的驗證。
      • 通用、靈活、多樣。
      • 甚至可以用在其他項目的檢查上,減少學習成本。

    健壯

    執行測試的過程中,難免會報失敗,執行失敗可能的原因有很多,簡單分為4類:

    • 被測系統出錯,這部分其實是我們希望看到的,因為這說明我們的自動化測試真正地發現了一個Bug,用例發揮了它的價值,所以,這是我們希望看到的。
    • 測試工具出錯,這部分其實是我們不希望看到的,因為很大可能我們今天的自動化相當于白跑了。
    • 測試數據錯誤,這是我們要避免的,既然數據容易失效,那我在設計測試平臺的時候,就需要考慮如果將所有的數據跑“活”,而不是只寫“死”。
    • 不可抗力,這部分是我們也很無奈的,但是這樣的情況很少發生。

    那針對上面的情況:

    • 參數數據失效
      • 支持實時去數據庫查詢。
      • 支持批量查。
    • IP進場發生變更
      • 自動更新IP。
    • 靈活、可復用
      • 支持批量維護。
      • 接口測試執行前生成一些數據。
      • 接口執行完成后銷毀一些數據。
      • 支持參數使用另一條測試用例的返回結果。
      • 支持一些請求參數實時生成,如token等數據,從而減少數據失效的問題。

    通過這些手段,提高測試用例的健壯性,讓每一條自動化測試用例都能很好的完成測試任務,真正發揮出一條測試用例的價值。

    易用

    • 簡單
      • 功能強大,但要人人會用。
      • 非技術人員也要會用。
    • 減少代碼操作
      • 讓自動化開發人員注意力能更多的放在用例本身,而不是浪費在無關緊要的開發工作上面。
    • 還要
      • 配置能復用。
      • 通用、易學。
      • 一些數據能自動生成。

    3.2 Lego接口自動化測試用例

    說了這么多,那我們來看一下一條Lego接口測試用例的樣子。

    一條Lego自動用例執行順序大概是如下圖這樣:

    簡單區分一下各個部分,可以看到:

    那上面圖中提到了兩個名詞:

    • “參數化”
    • “前后置動作”

    下面會先對這兩個名詞做一個簡單的介紹。

    3.3 參數化

    比如一個請求需要用到的參數。

    {"sync": false,"cityId": 1,"source": 0,"userId": 1234,"productId": 00004321 }

    這個例子中有個參數"productId": 00004321,而由于測試的環境中,表單00004321很可能一些狀態已經發生了改變,甚至表單已經刪除,導致接口請求的失敗,那么這時候,就很適合對"productId": 00004321進行參數化,比如寫成這樣:

    {"sync": false,"cityId": 1,"source": 0,"userId": 1234,"productId": ${myProductId} }

    所以對“參數化”簡單的理解就是:

    通過一些操作,將一個“值”替換掉測試用例里的一個“替代字符”

    ${myProductId} 的值可以通過配置獲取到:

    • Key-Value
      • 配置 Value=00004321。
    • SQL獲取
      • 執行一個select語句來實時查詢得到可用ID。
    • 已有測試用例
      • 某個接口接口測試用例的返回結果。

    “參數化”實例

    下面我們來看一個“參數化”的實例:

    (1) 首先我們在參數化維護頁面中新建一個參數化,shopdealid。

    通過配置我們可以看到這個參數的值,是執行了一條SQL后,取用執行結果中DealID字段的值。

    (2) 在用例中,將需要這個表單號的地方用${shopdealid}替代。

    那在編寫測試用例的時候,大家可以看一下這個放大的圖片,在這里的ProductID的值并不是硬代碼一個固定的表單號,而是選擇了剛才配置的參數化數據。

    (3) 執行結果中,${shopdealid} 變為實時查詢數據庫的來的一個真實的表單號。

    從結果中可以看到,我們的這個參數被替換成了一個有效的值,而這個值就是我們剛剛配置的那個SQL實時查詢而來的。

    “參數化”的場景

    多個測試用例使用同一個參數進行測試

    如50條測試用例都使用同一個id作為參數進行測試,這時候我們需要變更這個id。

    無參數化時:

    • 需要修改50次,即每條測試用例中的id都得進行修改。
    • 可能會有遺漏。 有參數化時:
    • ID部分用 ${myID} 替代。
    • 需要修改的話,在“參數化維護”頁面中維護 ${myID}這條數據就可以。修改一次,所有使用${myID}的用例都配置完成。

    測試數據過期導致測試用例執行失敗

    如一條用例參數需要傳入Token,但是Token會因為時間問題而導致過期,這時候用例就失敗了。

    無參數化時:

    • 經常修改Token,或是寫一段ID轉Token的代碼。
    • 方法可能會重復編寫。
    • 多個團隊之間可能實現方式也不同。

    有參數化時:

    • 使用參數化工具,Lego統一管理。
    • 維護一個參數化 如:${測試用Token} = id:123。

    數據庫獲取有效測試數據

    參數中需要傳入DealId作為參數,寫死參數的話,如果這個DealId被修改引起失效,那這條測試用例就會執行失敗。

    不使用Lego時:

    • 測試環境中,一個訂單時常會因為測試需要被修改數據,導致單號失效,最后導致自動化失敗。
    • 編寫相關代碼來做好數據準備工作。
    • 在代碼中編寫讀取數據庫的方法獲取某些內容。

    在Lego上的方案: - 使用參數化,實時獲取sql結果,查詢出一條符合條件的dealId來實現。 - 使用參數化,調用寫好的“生成訂單”接口用例實現,拿單號來實現。 - 前后置動作,插入一條滿足條件的數據。

    3.4 前后置動作

    “前后置動作”的概念就比較好理解了:

    在接口請求之前(或之后),執行一些操作

    目前前后置動作支持6種類型:

    • 數據庫SQL執行
      • 有時候在執行接口請求前,為了保證數據可用,可能需要在數據庫中插入或刪除一條信息,這時候就可以使用前后置動作里的“執行SQL語句”類型,來編寫在接口請求前(后)的 Insert 和 Delete 語句。
    • 已有測試用例執行
      • 比如當前測試用例的請求參數,需要使用另一條測試用例的返回結果,這時候就可以使用“執行測試用例”類型,寫上Lego上某條測試用例的ID編號,就可以在當前用例接口請求前(后)執行這條測試用例。
      • 前后置動作中測試用例的返回結果可以用于當前用例的參數,對測試用例返回結果內容的獲取上,也支持JsonPath和正則表達式兩種方式。
    • MQ消息發送
      • 在接口請求前(后)發送MQ消息。
    • HTTP請求
    • 等待時間
    • 自定義的Java方法
      • 如果上面的方法還滿足不了需求,還可以根據自己的需要,編寫自己的Java方法。
      • 可以在Lego-Kit項目中,編寫自己需要的Java方法,選擇“執行Java方法”,通過反射實現自定義Java方法的執行。

    這里的SQL同時支持Select操作,這里其實也是做了一些小的設計,會將查詢出來的全部的結果,放入到這個全局Map中。

    比如查詢一條SQL得到下表中的結果:

    id |    name    |    age    |    number    :–: | :–: | :–: | :–: | :–: 0 | 張三 | 18 | 1122 1 | 李四 | 30 | 3344

    那我們可以使用下面左邊的表達式,得到對應的結果:

    • ${pre.name} —- 得到 “張三”?
    • ${pre.age} —- 得到 18
    • ${pre.number} —- 得到 1122

    也可以用:

    • ${pre.name[0]} —- 得到 “張三”
    • ${pre.age[0]} —- 得到 18
    • ${pre.number[0]} —- 得到 1122
    • ${pre.name[1]} —- 得到 “李四”
    • ${pre.age[1]} —- 得到 30
    • ${pre.number[1]} —- 得到 3344

    這樣的設計,更加幫助在用例設計時,提供數據準備的操作。

    “前后置動作”實例

    (1) 首先我們在前后置維護頁面中新建一個動作,獲取庫存上限未賣光團單

    這個配置也是可以支持在線調試的,在調試中,可以看到可以使用的參數化:

    (2) 在測試用例中的前置動作,添加獲取庫存上限未賣光團單

    這樣就可以在整個測試用例中,使用${pre.ProductID},來替換掉原有的數據信息。

    (3) 最后請求接口,返回了執行成功

    Q & A

    Q:那如果同樣是獲取三個參數,使用3個“參數化的Select操作”和使用1個“前置動作的Select操作”又有什么不同呢?

    A: 不同在于執行時間上。 比如,我們查詢最新的有效團單的“單號”“下單人”和“手機號”三個字段。 使用3個“參數化的Select操作”:可能當執行${單號}的時候得到的訂單號是“10001”,但是當執行到${下單人}的時候,可能有誰又下了一單,可能取到的下單人變成了“10002”的“李四”而不是“10001”的“張三”了,最后可能“單號”“下單人”和“手機號”三個字段去的數據并非同一行的數據。 而使用“前置動作的Select操作”:就可以避免上面的問題,因為所有字段的數據是一次性查詢出來的,就不會出現錯位的情況。

    Q : 那“參數化的Select操作”和“前置動作的Select操作”這樣不同的取值時機又有什么好用之處呢?

    A : 由于“前置動作”一定是接口請求前執行,“參數化”一定是用到的時候才執行這樣的特性。 所以在檢查點中,如果要驗證一個數據庫字段在經過接口調用后發生了變更,那使用“前置動作”和“參數化”同時去查詢這個字段,然后進行比較,不一致就說明發生了變化。 所以根據使用場景,選擇合適的參數化方式,很重要,選擇對了,能大大提升測試用例的測試數據健壯性。

    3.5 執行各部分

    回到一開始的流程圖,可以按照一類一類來看執行過程。

    測試發起

    測試發起基本還是使用的Jenkins,穩定、成熟、簡單、公司工具組支持,也支持從Lego的Web頁面進行執行操作。

    數據 / 環境準備

    使用 @DataProvider 的方式,從DB數據庫中讀取測試用例,逐一執行進行測試。

    測試執行

    在正式執行測試用例之前,會先進行一波參數替換的動作,在調用接口之后,還會執行一次參數替換動作。

    參數替換后會進行前置動作的執行,然后在調用接口之后還會執行測試后動作,最后執行后置動作。

    接口請求這部分就沒什么好說的了,就是通過接口請求的參數,請求對應的接口,拿到返回結果。

    這里的話是為了方便通用,所以要求返回的結果都是使用的String類型。這樣做最大的好處就是。比如說我現在有一種新的接口類型需要接入。那只需要寫一個方法能夠請求到這個接口,并且拿到String類型的返回結果,就可以很快將新的接口類型接入Lego測試平臺進行接口測試。

    檢查點校驗

    檢查點部分是一條自動化測試用例的精髓,一條自動化測試用例是否能真正的發揮它的測試功能,就是看QA對這條測試用例的檢查點編寫是否做了良好設計。在Lego平臺上,目前我擁有的檢查點有6種不同的類型。

    • 異常檢查點
      • 當返回結果為異常時,則會報錯。
      • 但是有時候為了做異常測試,可以將這個檢查點關掉。
    • 不為空檢查點
      • 顧名思義,當出現”“、”[]“、”{}“、null 這樣的的結果,都會報錯。也可以根據自己用例的實際情況關閉。
    • 包含檢查點
    • 不包含檢查點
      • “包含”和“不包含”檢查點是將接口的返回結果作為一個String類型來看,檢查所有返回內容中是否“包含”或“不包含”指定的內容。
    • 數據庫參數檢查點
      • 顧名思義,不做過多的解釋了。
    • JsonPath檢查點
      • 這是我在Lego上設計的最具有特色的一種檢查點類型。

    JsonPath的基本寫法是{JsonPath語法}==value

    JsonPath的語法和XPath的語法差不多,都是根據路徑的方法找值。這里也是主要是針對返回結果為JSON數據的結果,進行檢查。

    具體的JsonPath語法可以參考:https://github.com/json-path/JsonPath

    說完了“JsonPath的語法”,現在說一下“JsonPath檢查點的語法”“JsonPath檢查點的語法”是我自己想的,主要針對以下幾種數據類型進行校驗:

    (1) 字符串類型結果檢驗

    • 等于:==
    • 不等于:!==
    • 包含:=
    • 不包含:!=

    例如:

    • {$.[1].name}==aa:檢查返回的JSON中第2個JSON的name字段是否等于aa。
    • {$..type}=='14':檢查返回的JSON中每一個JSON的name字段是否等于aa。
    • {$.[1].type}==14 && {$.[1].orderId}==106712:一條用例中多個檢查用&&連接。
    • {$..orderId}!==12:檢查返回的JSON中每個JSON的orderId字段是否不等于12。
    • {$..type}=1:檢查返回的JSON中每個JSON的type字段是否包含1。
    • {$.[1].type}!=chenyongda:檢查返回的JSON中第2個JSON的type字段是否不包含chenyongda。

    (2) 數值校驗

    • 等于:=
    • 大于:>
    • 大于等于:>=
    • 小于:<
    • 小于等于:<=

    例如:

    • {$.[0].value}<5:檢查返回的JSON中第1個JSON的value字段的列表是否小于3。
    • {$.[1].value}>4:檢查返回的JSON中第2個JSON的value字段的列表是否大于4。

    (3) List結果檢驗

    • list長度:.length
    • list包含:.contains(param)
    • list成員:.get(index)

    例如:

    • {$..value}.length=3:檢查返回的JSON中每個JSON的value字段的列表是否等于3。
    • {$.[0].value}.length<5:檢查返回的JSON中第1個JSON的value字段的列表是否小于3。
    • {$.[1].value}.length>4:檢查返回的JSON中第2個JSON的value字段的列表是否大于4。
    • {$..value}.contains('222'):檢查返回的JSON中每個JSON的value字段的列表是否包含222字符串。
    • {$.[0].value}.contains(1426867200000):檢查返回的JSON中第1個JSON的value字段的列表是否包含1426867200000。
    • {$.[0].value}.get(0)=='222':檢查返回的JSON中第1個JSON的value字段的列表中第1個內容是否等于222。
    • {$..value}.get(2)='22':檢查返回的JSON中每個JSON的value字段的列表中第3個內容是否包含22。

    (4) 時間類型處理

    時間戳轉日期時間字符串:.todate

    例如:

    • {$..beginDate}.todate==2015-12-31 23:59:59:檢查返回的JSON中beginDate這個時間戳轉換成日期后是否等于2015-12-31 23:59:59。
    當JsonPath返回的結果是列表的形式時
    檢查點檢查點等號左邊期望值驗證效果
    {$.value}==“good”[‘good’, ‘good’, ‘bad’, ‘good’]“good”作為4個檢查點,會拿列表里的每個對象逐一和“期望值”進行檢驗,每一次對比都是一個獨立的檢查點。
    {$.value}==[“good”][‘good’, ‘good’, ‘bad’, ‘good’][“good”]作為1個檢查點,作為一個整體做全量比對。
    {$.value}==[‘a’, ‘b’][[‘a’, ‘b’],[‘a’, ‘b’],[‘a’, ‘b’, ‘c’]][‘a’, ‘b’]作為3個檢查點,道理和1一樣,列表中的數據分別和期望值做比較。
    除此之外,還有非常多的花樣玩法

    JsonPath中的檢查支持“參數化”和“前后置動作”,所以會看到很多如:

    {$.param}=‘${param}’ && {$.param}==${pre.param}

    這樣的檢查點:

    “參數化”和“前后置動作”也支持遞歸配置,這些都是為了能夠讓接口自動化測試用例寫的更加靈活好用。

    測試結果

    使用ReportNG可以打印出很漂亮的報告。

    報告會自定義一些高亮等展示方式,只需要在ReportNG使用前加上下面的語句,就可以支持“輸出逃逸”,可使用HTML標簽自定義輸出樣式。

    System.setProperty("org.uncommons.reportng.escape-output", "false");

    后期優化

    當使用Jenkins執行后,通過Jenkins API 、和Base包中的一些方法,定時獲取測試結果,落數據庫,提供生成統計圖表用。

    四、網站功能

    4.1 站點開發

    既然打算做工具平臺了,就得設計方方面面,可惜人手和時間上的不足,只能我一人利用下班時間進行開發。也算是擔任了Lego平臺的產品、后端開發、前端開發、運維和測試等各種角色。

    Jenkins+TestNG+ReportNG+我自己開發的基本接口自動化測試Base jar包,基本上沒什么太大難度。但是站點這塊,在來美團之前,還真沒開發過這樣的工具平臺,這個算是我的第一個帶Web界面的工具。邊Google邊做,沒想到不久還真的架起來了一個簡易版本。

    使用 Servlet + Jsp 進行開發,前端框架使用Bootstrap,前端數據使用jstl,數據庫使用MySQL,服務器使用的公司的一臺Beta環境Docker虛擬機,域名是申請的公司內網域名,并開通北京上海兩側內網訪問權限。

    功能上基本都是要滿足的,界面上,雖然做不到驚艷吧,但是絕對不能丑,功能滿足,但是長得一副80年代的界面,我自己都會嫌棄去使用它,所以界面上我還是花了一些時間去調整和設計。熟練以后就快多了。

    4.2 整體組成

    目前Lego由五個不同的項目組成,分別是“測試腳本”、“Lego-web頁面項目”、“用于執行接口測試的base包”、“小工具集合Lego-kit”和“lego-job”,通過上圖可以看出各項目間的依賴關系。

    細化各個項目的功能,就是下圖:

    簡單來說,網站部分和腳本是分離的,中間的紐帶是數據庫。所以,沒有網站,腳本執行一點問題也沒有;同樣的,網站的操作,和腳本也沒有關系。

    4.3 使用-日常維護

    Step 1

    每天上班來會收到這樣的測試郵件,通過郵件能知道昨晚執行的情況。如果有報錯,可以點擊“詳細報告鏈接”,跳轉到在線報告。

    Step 2

    在現報告可以直接看到執行報錯的信息,然后點擊“LEGO維護傳送門”,可以跳轉到Lego站點上,進行用例維護。

    Step 3

    跳轉到站點上以后,可以直接展示出該條測試用例的所有信息。定位,維護、保存,維護用例,可以點擊“執行”查看維護后的執行結果,維護好后“保存”即可。

    僅僅3步,1~2分鐘即可完成對一條執行失敗的用例進行定位、調試和維護動作。

    4.4 用例編輯

    通過頁面,我們就可以對一條測試用例進行:

    • 新建
    • 復制
    • 編輯
    • 刪除
    • 是否放入每日構建中進行測試

    4.5 在線調試

    lego-web項目同樣的使用base進行的用例執行,所以執行結果和打印都與腳本執行的一致的。

    4.6 用例生成工具

    為了更方便的寫用例,針對部分接口開發了一鍵批量生成用例的小工具。

    4.7 執行結果分析

    通過Jenkins接口、Base包中基礎Test方法,將結果收集到數據庫,便于各組對測試結果進行分析。

    這是每天執行后成功率走勢圖:

    也可以按月進行統計,生成統計的圖表,幫助各個團隊進行月報數據收集和統計。

    4.8 失敗原因跟蹤

    有了能直觀看到測試結果的圖表,就會想要跟蹤失敗原因。

    所以在成功率數據的右邊,會有這樣的跟蹤失敗原因的入口,也可以很直觀地看到哪一些失敗的原因還沒有被跟蹤。點開后可以對失敗原因進行記錄。

    最后會有生成圖表,可以很清晰地看到失敗原因以及失敗類型的占比。

    4.9 代碼覆蓋率分析

    結合Jacoco,我們可以對接口自動化的代碼覆蓋率進行分析。

    在多臺Slave機器上配置Jacoco還是比較復雜的,所以可以開發覆蓋率配置輔助工具來幫助測試同學,提高效率。

    4.10 用例優化方向

    除了上面的圖表,還會給用例優化提供方向。

    通過用例數量統計的圖表,我們可以知道哪些服務用例還比較少,哪些環境的用例還比較少,可以比較有針對性的進行測試用例的補充。

    通過失敗原因的圖表,我們可以改善自己用例中的“參數化”和“前后置動作”的使用,增加測試用例的健壯性。

    通過線上接口調用量排序的圖表。我們可以有效的知道優先維護哪些服務的測試用例,通過表格中,我們可以看到,哪些服務已經覆蓋了測試用例,哪些沒有被覆蓋, 給各組的QA制定用例開發計劃,提供參考。

    同時在維護接口自動化測試的時候,都會看到用例評分的情況,來協助QA提高用例編寫的質量。

    4.11 收集反饋/學習

    還做了“需求白板”,用來收集使用者的需求和Bug。除此之外,Lego平臺已經不只是一個接口測試的平臺,還可以讓想學習開發的QA領任務,學習一些開發技巧,提高自己的代碼能力。

    五、總結

  • 為了減少開發成本,使用比較常見的Jenkins+TestNG的腳本形式。
  • 為了簡化code操作,使用DB進行測試用例存儲,并抽象出用例摸版。
  • 為了減低新建用例成本,開發“用例維護頁面”和“一鍵生成”等工具。
  • 為了減低維護成本,加跳轉鏈接,維護一條用例成本在幾分鐘內。
  • 為了增加用例健壯性,設計了“參數化”、“前后置動作”等靈活的參數替換。
  • 為了易用和兼容,統一“返回結果”類型,統一“檢查點”的使用。
  • 為了接口自動化用例設計提供方向,結合Jacoco做代碼覆蓋率統計,并開發相關配置工具
  • 為了便于分析數據,從DOM、CAT、Jenkins上爬各種數據,在頁面上用圖表展示。
  • 為了優化用例,提供“用例打分”、“線上調用量排行”等數據進行輔助。
  • 本文介紹了我們的接口自動化測試平臺Lego,歡迎感興趣的同學掃描“美團技術團隊”微信二維碼,通過后臺交流討論。

    總結

    以上是生活随笔為你收集整理的Lego-美团接口自动化测试实践的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。