測試用例管理與Jenkins集成

https://testerhome.com/topics/15170

https://github.com/reese0329/rest_assured

 

與Jenkins集成(2)

https://testerhome.com/topics/15294

 

 

接口測試進階使用 

發送json請求

 

 

java: -source 1.5 中不支持 diamond 運算符 (請使用 -source 7 或更高版本以啓用 diamond 運算符)

https://blog.csdn.net/qq_35792598/article/details/74935475

添加依賴

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.2</version>
</dependency>
package restassured;

import io.restassured.http.ContentType;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

import static io.restassured.RestAssured.given;

public class Json_request {
    @Test
    public void Testbaidu(){
        Map<String,Object> data=new HashMap<>();
        data.put("x",1);
        data.put("y","xxxx");
        given()
                .proxy("10.231.21.240",8888)
                .contentType(ContentType.JSON)
                .body(data)
                .when()
                .post("http://www.baidu.com/s")
                .then()
        .statusCode(200);
    }
}

 

 

 

 

 

響應時間斷言

 

 

超時驗證

package restassured;

import org.junit.BeforeClass;
import org.junit.Test;

import static io.restassured.RestAssured.given;
import static io.restassured.RestAssured.useRelaxedHTTPSValidation;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.core.IsEqual.equalTo;

public class Json_Testerhome_timeout {

    @BeforeClass
    public static void BeforeClass(){
        useRelaxedHTTPSValidation();
    }

    @Test
    public void topic(){
        given()
                .when()
                .get("https://testerhome.com/api/v3/topics.json")
                .then()
                .body("topics.find{it.id==18752}.title",
                equalTo("記一次基於 Robotium 改造的測試實踐"))   //頁面修改
                .time(lessThan(3000L));
    }
}

 


19'

schema校驗

 

 

schema自動校驗

  • RestAssured有一套自己的schema自動校驗機制
    • schema的生成藉助於在線服務
    • 使用schema api斷言
  • schema自動生成方法
    • 每次運行的時候自動保存當前的schema
    • 下次運行對比上次的schema如果發現變更就報錯
    • saveSchema + diffSchema

 

 

 

20‘s

對response做多次解析

get(“/x”)

  • .then()
  • .body("href", response -> equalTo("http://localhost:8080/" + response.path("userId"));

 

21‘’

導出數據

 

 

21‘

基本http認證

 

 

多種認證API方法

 

 

 

 

 

 

業務數據依賴

❖ 通過extract導出第一個接口的response

❖ 取出結果值

❖ 傳遞給後面的api請求

 

 

token變動取值

package restassured;

import io.restassured.response.Response;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.lessThan;

public class Json_token {
    public static String token;
    @Test
    public void baidu() {
        Response response =given()
                .log().all()
                .queryParam("wd", "mp3")
                .when()
                .get("http://www.baidu.com/s")
                .then()
                .log().all()
                .statusCode(200)
                .body("html.head.title", equalTo("mp3_百度搜索"))
                .time(lessThan(2L), TimeUnit.SECONDS)
                .extract().response();
        token = response.path("topics.id[0]");
        //從導出數據中讀取topics,id獲取token值
    }
    @Test
    public void  Test2(){
        given().
                param("token",token);
                //在其他方法中引用
    }
}

 

 

全局封裝

❖  全局RestAssured對象

    • baseURI
    • proxy
  • spec方法
    • 通用的請求封裝
    • 通用的結果斷
  • filter方法
    • 全局加解密封裝

BaseURI

package restassured;

import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.hasItems;
import static org.junit.Assert.assertEquals;

public class Variable {

    @Test
    public void topic(){
        RestAssured.baseURI="https://testerhome.com";
        Response response = given()
                .when()
                .get("/api/v3/topics.json")
                .then()
                .body("topics.id",hasItems(18392,18756))
                .extract().response();
        Integer id1=response.path("topics.id[0]");
        Integer id2=response.path("topics.id[1]");
        assertEquals(id1,id2);
    }
}

 

 

33‘

 

filter機制

利用filter機制實現自動解密

https://github.com/rest-assured/rest-assured/wiki/Usage#filters

 

  • filter可以應用於所有全局請求
  • request處理
    • 記錄所有的request數據
    •  動填充token
  • response處理
    • 重新構建新的response
    • filter( (req, res, ctx)-> { //重新 成response})
    • new ResponseBuilder().clone(originalResponse)

 

 

修改request

❖ 可以修改請求內容

❖自動帶上cookie

❖ 通用的請求數據記錄

❖ 記錄所有的請求和響應

 

 

 

    @Test
    public void topic(){
            Response response =given()
                    .proxy("10.231.21.240",8888)
                    .filter((req, res, ctx)->{
                        req.cookie("testerhome","severniruby");
                        return ctx.next(req,res);})
                    .contentType(ContentType.JSON)
                    .when()
                    .post("http://www.baidu.com/s")
                    .then()
                    .statusCode(200).extract().response();
        }

 

在beforeclass中添加filter,之後的所有請求都走filter邏輯

    @BeforeClass
    public static void BeforeClass(){
        useRelaxedHTTPSValidation();
        RestAssured.filters((req, res, ctx)->{
            req.cookie("testerhome","severniruby");
            return ctx.next(req,res);});
        RestAssured.proxy("10.231.21.240",8888);
    }

 

 

 

45‘

修改response

創建一個base64加密的json串

eyJ0b3BpY3MiOlt7ImlkIjoxODcxNywidGl0bGUiOiLnur/kuIrnrKzkuZ3mnJ9fTGludXgg5LiJ5YmR5a6i6L+b6Zi2XzIwMTkwNDEwIiwiY3JlYXRlZF9hdCI6IjIwMTktMDQtMTBUMjA6MDQ6NDMuNjg3KzA4OjAwIiwidXBkYXRlZF9hdCI6IjIwMTktMDQtMTNUMTk6MDg6MDQuMTUzKzA4OjAwIiwicmVwbGllZF9hdCI6IjIwMTktMDQtMTNUMTk6MDg6MDQuMTI1KzA4OjAwIiwicmVwbGllc19jb3VudCI6NTcsIm5vZGVfbmFtZSI6IkxpbnV4Iiwibm9kZV9pZCI6NjUsImxhc3RfcmVwbHlfdXNlcl9pZCI6NDIzNjksImxhc3RfcmVwbHlfdXNlcl9sb2dpbiI6InN1bW1lcjIzMjUiLCJleGNlbGxlbnQiOjAsImxpa2VzX2NvdW50Ijo5LCJzdWdnZXN0ZWRfYXQiOm51bGwsImNsb3NlZF9hdCI6bnVsbCwiZGVsZXRlZCI6ZmFsc2UsInVzZXIiOnsiaWQiOjEwNCwibG9naW4iOiJzZXZlbmlydWJ5IiwibmFtZSI6IuaAneWvkl9zZXZlbmlydWJ5IiwiYXZhdGFyX3VybCI6Ii91cGxvYWRzL3VzZXIvYXZhdGFyLzEwNC5qcGchbGFyZ2UiLCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2V9fSwiaGl0cyI6MTI3OCwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlLCJiYW4iOmZhbHNlLCJleGNlbGxlbnQiOmZhbHNlLCJ1bmV4Y2VsbGVudCI6ZmFsc2UsImNsb3NlIjpmYWxzZSwib3BlbiI6ZmFsc2V9fSx7ImlkIjoxODY5OSwidGl0bGUiOiLkvZzkuLrkuIDkuKrlm6LpmJ8gbGVhZGVy77yM5oKo5piv5ZCm5pyJ6YGH5Yiw77yfIiwiY3JlYXRlZF9hdCI6IjIwMTktMDQtMDlUMTk6NTk6MDEuNTIyKzA4OjAwIiwidXBkYXRlZF9hdCI6IjIwMTktMDQtMTNUMTg6NDU6NDAuNTgyKzA4OjAwIiwicmVwbGllZF9hdCI6IjIwMTktMDQtMTNUMTg6NDU6NDAuNTY0KzA4OjAwIiwicmVwbGllc19jb3VudCI6MTQsIm5vZGVfbmFtZSI6IuS6kuW4ruS6kuWKqSIsIm5vZGVfaWQiOjEyNSwibGFzdF9yZXBseV91c2VyX2lkIjo2MDUsImxhc3RfcmVwbHlfdXNlcl9sb2dpbiI6ImNoZW5oZW5namllMTIzIiwiZXhjZWxsZW50IjowLCJsaWtlc19jb3VudCI6MTAsInN1Z2dlc3RlZF9hdCI6bnVsbCwiY2xvc2VkX2F0IjpudWxsLCJkZWxldGVkIjpmYWxzZSwidXNlciI6eyJpZCI6MzI5NSwibG9naW4iOiJhbjE2OGdlIiwibmFtZSI6ImNoZW55b3VhbiIsImF2YXRhcl91cmwiOiIvdXBsb2Fkcy91c2VyL2F2YXRhci8zMjk1LmpwZyFsYXJnZSIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZX19LCJoaXRzIjoxMTE3LCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2UsImJhbiI6ZmFsc2UsImV4Y2VsbGVudCI6ZmFsc2UsInVuZXhjZWxsZW50IjpmYWxzZSwiY2xvc2UiOmZhbHNlLCJvcGVuIjpmYWxzZX19LHsiaWQiOjE3OTg2LCJ0aXRsZSI6IuWfuuS6jiBKbWV0ZXIg55qEIHdlYiDnq6/mjqXlj6Poh6rliqjljJbmtYvor5XlubPlj7AiLCJjcmVhdGVkX2F0IjoiMjAxOS0wMS0yOFQxMDoyNzoyMS44MDUrMDg6MDAiLCJ1cGRhdGVkX2F0IjoiMjAxOS0wNC0xM1QxODoyMjo1OC43OTErMDg6MDAiLCJyZXBsaWVkX2F0IjoiMjAxOS0wNC0xM1QxODoyMjo1OC43NjkrMDg6MDAiLCJyZXBsaWVzX2NvdW50Ijo3Miwibm9kZV9uYW1lIjoi5o6l5Y+j5rWL6K+VIiwibm9kZV9pZCI6NjIsImxhc3RfcmVwbHlfdXNlcl9pZCI6NDI1OTQsImxhc3RfcmVwbHlfdXNlcl9sb2dpbiI6InNob3lhbmNoZXVuZyIsImV4Y2VsbGVudCI6MSwibGlrZXNfY291bnQiOjkwLCJzdWdnZXN0ZWRfYXQiOm51bGwsImNsb3NlZF9hdCI6bnVsbCwiZGVsZXRlZCI6ZmFsc2UsInVzZXIiOnsiaWQiOjY4NTksImxvZ2luIjoidDg4MDIxNnQiLCJuYW1lIjoiODHigJQxIiwiYXZhdGFyX3VybCI6Ii91cGxvYWRzL3VzZXIvYXZhdGFyLzY4NTkuanBnIWxhcmdlIiwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlfX0sImhpdHMiOjk5ODUsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZSwiYmFuIjpmYWxzZSwiZXhjZWxsZW50IjpmYWxzZSwidW5leGNlbGxlbnQiOmZhbHNlLCJjbG9zZSI6ZmFsc2UsIm9wZW4iOmZhbHNlfX0seyJpZCI6MTg3MTIsInRpdGxlIjoiWWFwaSDpm4bmiJAgamVua2lucyDpl67popjvvIzmsYLlpKfnpZ7mjIfngrkiLCJjcmVhdGVkX2F0IjoiMjAxOS0wNC0xMFQxNjoxNDoyNS4zMDArMDg6MDAiLCJ1cGRhdGVkX2F0IjoiMjAxOS0wNC0xM1QxODoxODozOC41MzUrMDg6MDAiLCJyZXBsaWVkX2F0IjoiMjAxOS0wNC0xM1QxODoxODozOC41MDIrMDg6MDAiLCJyZXBsaWVzX2NvdW50Ijo0LCJub2RlX25hbWUiOiLmjqXlj6PmtYvor5UiLCJub2RlX2lkIjo2MiwibGFzdF9yZXBseV91c2VyX2lkIjo2MDUsImxhc3RfcmVwbHlfdXNlcl9sb2dpbiI6ImNoZW5oZW5namllMTIzIiwiZXhjZWxsZW50IjowLCJsaWtlc19jb3VudCI6MCwic3VnZ2VzdGVkX2F0IjpudWxsLCJjbG9zZWRfYXQiOm51bGwsImRlbGV0ZWQiOmZhbHNlLCJ1c2VyIjp7ImlkIjoyMzIxMSwibG9naW4iOiJncmFjZV96aGFuZyIsIm5hbWUiOiLkvJjpm4XnmoTmtYvor5XlqpsiLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvMjMyMTEvMjdjYzZkLmpwZyFsYXJnZSIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZX19LCJoaXRzIjozMjUsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZSwiYmFuIjpmYWxzZSwiZXhjZWxsZW50IjpmYWxzZSwidW5leGNlbGxlbnQiOmZhbHNlLCJjbG9zZSI6ZmFsc2UsIm9wZW4iOmZhbHNlfX0seyJpZCI6MTg3MDMsInRpdGxlIjoiW29rSHR0cF0g57uf6K6h5o6l5Y+j5ZON5bqU55So5pe2IFRURkIiLCJjcmVhdGVkX2F0IjoiMjAxOS0wNC0xMFQwOTo0MzoyMy40MjcrMDg6MDAiLCJ1cGRhdGVkX2F0IjoiMjAxOS0wNC0xM1QxNzowNzoxOS40ODIrMDg6MDAiLCJyZXBsaWVkX2F0IjoiMjAxOS0wNC0xM1QxNzowNzoxMS44MzArMDg6MDAiLCJyZXBsaWVzX2NvdW50Ijo1LCJub2RlX25hbWUiOiLmjqXlj6PmtYvor5UiLCJub2RlX2lkIjo2MiwibGFzdF9yZXBseV91c2VyX2lkIjoyNTYyLCJsYXN0X3JlcGx5X3VzZXJfbG9naW4iOiJjYXJsIiwiZXhjZWxsZW50IjowLCJsaWtlc19jb3VudCI6MCwic3VnZ2VzdGVkX2F0IjpudWxsLCJjbG9zZWRfYXQiOm51bGwsImRlbGV0ZWQiOmZhbHNlLCJ1c2VyIjp7ImlkIjoyNTYyLCJsb2dpbiI6ImNhcmwiLCJuYW1lIjoiYmF1dWwiLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvMjU2Mi5qcGchbGFyZ2UiLCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2V9fSwiaGl0cyI6MjY0LCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2UsImJhbiI6ZmFsc2UsImV4Y2VsbGVudCI6ZmFsc2UsInVuZXhjZWxsZW50IjpmYWxzZSwiY2xvc2UiOmZhbHNlLCJvcGVuIjpmYWxzZX19LHsiaWQiOjE4NzU4LCJ0aXRsZSI6IuKAmFNvY2tldCBjb25uZWN0aW9uIHdhcyBsb3N04oCZIOmXrumimOWSqOivoiIsImNyZWF0ZWRfYXQiOiIyMDE5LTA0LTEyVDE4OjIzOjE3LjA5MSswODowMCIsInVwZGF0ZWRfYXQiOiIyMDE5LTA0LTEyVDIzOjQ1OjAxLjk2MSswODowMCIsInJlcGxpZWRfYXQiOiIyMDE5LTA0LTEyVDIzOjQ1OjAxLjkyMCswODowMCIsInJlcGxpZXNfY291bnQiOjIsIm5vZGVfbmFtZSI6IlNURiIsIm5vZGVfaWQiOjEzNywibGFzdF9yZXBseV91c2VyX2lkIjo0MDI2NSwibGFzdF9yZXBseV91c2VyX2xvZ2luIjoiTGllYmVLcmFrZSIsImV4Y2VsbGVudCI6MCwibGlrZXNfY291bnQiOjAsInN1Z2dlc3RlZF9hdCI6bnVsbCwiY2xvc2VkX2F0IjpudWxsLCJkZWxldGVkIjpmYWxzZSwidXNlciI6eyJpZCI6NDAyNjUsImxvZ2luIjoiTGllYmVLcmFrZSIsIm5hbWUiOiLku4rlpKnkuZ/mmK/mlLbojrfmu6Hmu6HnmoTkuIDlpKnllYoiLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvNDAyNjUvNjVmYjU3LmpwZyFsYXJnZSIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZX19LCJoaXRzIjoxMjEsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZSwiYmFuIjpmYWxzZSwiZXhjZWxsZW50IjpmYWxzZSwidW5leGNlbGxlbnQiOmZhbHNlLCJjbG9zZSI6ZmFsc2UsIm9wZW4iOmZhbHNlfX0seyJpZCI6MTg3NDQsInRpdGxlIjoi5rWL6K+V5Zui6Zif5pyN5Yqh5YyW6K+l5aaC5L2V5Lqn5Ye65Lu35YC877yfIiwiY3JlYXRlZF9hdCI6IjIwMTktMDQtMTJUMTE6MzY6NTEuMDUzKzA4OjAwIiwidXBkYXRlZF9hdCI6IjIwMTktMDQtMTJUMjM6MTA6MDIuOTQzKzA4OjAwIiwicmVwbGllZF9hdCI6IjIwMTktMDQtMTJUMjM6MTA6MDIuOTIyKzA4OjAwIiwicmVwbGllc19jb3VudCI6OCwibm9kZV9uYW1lIjoi54GM5rC0Iiwibm9kZV9pZCI6MTEsImxhc3RfcmVwbHlfdXNlcl9pZCI6MTcwNiwibGFzdF9yZXBseV91c2VyX2xvZ2luIjoieWFuZ2NoZW5ndGVzdCIsImV4Y2VsbGVudCI6MCwibGlrZXNfY291bnQiOjAsInN1Z2dlc3RlZF9hdCI6bnVsbCwiY2xvc2VkX2F0IjpudWxsLCJkZWxldGVkIjpmYWxzZSwidXNlciI6eyJpZCI6NTI1NywibG9naW4iOiJ3b2RldGEzMyIsIm5hbWUiOiLppqzmiY7nvoUiLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvNTI1Ny5qcGchbGFyZ2UiLCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2V9fSwiaGl0cyI6NDUwLCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2UsImJhbiI6ZmFsc2UsImV4Y2VsbGVudCI6ZmFsc2UsInVuZXhjZWxsZW50IjpmYWxzZSwiY2xvc2UiOmZhbHNlLCJvcGVuIjpmYWxzZX19LHsiaWQiOjE4NTQzLCJ0aXRsZSI6IuWkp+WutuaYr+aAjuS5iOi3kSBtb25rZXkg55qE77yf77yf77yfIiwiY3JlYXRlZF9hdCI6IjIwMTktMDMtMTVUMTE6MzY6MDYuMDM1KzA4OjAwIiwidXBkYXRlZF9hdCI6IjIwMTktMDQtMTJUMjI6MzE6MTAuNzA4KzA4OjAwIiwicmVwbGllZF9hdCI6IjIwMTktMDQtMTJUMjI6MzE6MTAuNjkwKzA4OjAwIiwicmVwbGllc19jb3VudCI6Niwibm9kZV9uYW1lIjoi56e75Yqo5rWL6K+V5Z+656GAIiwibm9kZV9pZCI6MzMsImxhc3RfcmVwbHlfdXNlcl9pZCI6OTgyLCJsYXN0X3JlcGx5X3VzZXJfbG9naW4iOiJzYW5kbWFuIiwiZXhjZWxsZW50IjowLCJsaWtlc19jb3VudCI6MCwic3VnZ2VzdGVkX2F0IjpudWxsLCJjbG9zZWRfYXQiOm51bGwsImRlbGV0ZWQiOmZhbHNlLCJ1c2VyIjp7ImlkIjozNzI4NCwibG9naW4iOiJ5aXpoaXhpYW55dSIsIm5hbWUiOiLkuIDlj6rlkrjpsbwiLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvMzcyODQvZDQ0ZDg0LnBuZyFsYXJnZSIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZX19LCJoaXRzIjo3OTAsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZSwiYmFuIjpmYWxzZSwiZXhjZWxsZW50IjpmYWxzZSwidW5leGNlbGxlbnQiOmZhbHNlLCJjbG9zZSI6ZmFsc2UsIm9wZW4iOmZhbHNlfX0seyJpZCI6MTg3NTIsInRpdGxlIjoi6K6w5LiA5qyh5Z+65LqOIFJvYm90aXVtIOaUuemAoOeahOa1i+ivleWunui3tSIsImNyZWF0ZWRfYXQiOiIyMDE5LTA0LTEyVDE0OjUzOjE4LjA1MCswODowMCIsInVwZGF0ZWRfYXQiOiIyMDE5LTA0LTEyVDIyOjAzOjE5LjI2MiswODowMCIsInJlcGxpZWRfYXQiOiIyMDE5LTA0LTEyVDIyOjAzOjE5LjIzOSswODowMCIsInJlcGxpZXNfY291bnQiOjUsIm5vZGVfbmFtZSI6IuS4k+agj+aWh+eroCIsIm5vZGVfaWQiOjE0NSwibGFzdF9yZXBseV91c2VyX2lkIjoyNTYyLCJsYXN0X3JlcGx5X3VzZXJfbG9naW4iOiJjYXJsIiwiZXhjZWxsZW50IjowLCJsaWtlc19jb3VudCI6MCwic3VnZ2VzdGVkX2F0IjpudWxsLCJjbG9zZWRfYXQiOm51bGwsImRlbGV0ZWQiOmZhbHNlLCJ1c2VyIjp7ImlkIjozODQwOSwibG9naW4iOiJ5b3V6YW5jb2RlciIsIm5hbWUiOiLmnInotZ7mtYvor5Xlm6LpmJ8iLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvMzg0MDkvYzU5ZDIzLnBuZyFsYXJnZSIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZX19LCJoaXRzIjoyMzQsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZSwiYmFuIjpmYWxzZSwiZXhjZWxsZW50IjpmYWxzZSwidW5leGNlbGxlbnQiOmZhbHNlLCJjbG9zZSI6ZmFsc2UsIm9wZW4iOmZhbHNlfX0seyJpZCI6MTg2NTcsInRpdGxlIjoiSmVua2lucyDmnoTlu7rkuIDkuKrlpJrphY3nva7pobnnm64gKOS6jCkiLCJjcmVhdGVkX2F0IjoiMjAxOS0wNC0wNVQxMzoyNTowMi43NDkrMDg6MDAiLCJ1cGRhdGVkX2F0IjoiMjAxOS0wNC0xMlQyMTowMjoxNi45MTYrMDg6MDAiLCJyZXBsaWVkX2F0IjoiMjAxOS0wNC0xMlQyMTowMjoxNi44OTIrMDg6MDAiLCJyZXBsaWVzX2NvdW50Ijo0LCJub2RlX25hbWUiOiLmjIHnu63pm4bmiJAiLCJub2RlX2lkIjo0NiwibGFzdF9yZXBseV91c2VyX2lkIjozODIxMiwibGFzdF9yZXBseV91c2VyX2xvZ2luIjoiZmVubnkucmVuIiwiZXhjZWxsZW50IjowLCJsaWtlc19jb3VudCI6MCwic3VnZ2VzdGVkX2F0IjpudWxsLCJjbG9zZWRfYXQiOm51bGwsImRlbGV0ZWQiOmZhbHNlLCJ1c2VyIjp7ImlkIjozODIxMiwibG9naW4iOiJmZW5ueS5yZW4iLCJuYW1lIjoiZmVubnkiLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvMzgyMTIvNmU3MjM3LmpwZWchbGFyZ2UiLCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2V9fSwiaGl0cyI6NDcwLCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2UsImJhbiI6ZmFsc2UsImV4Y2VsbGVudCI6ZmFsc2UsInVuZXhjZWxsZW50IjpmYWxzZSwiY2xvc2UiOmZhbHNlLCJvcGVuIjpmYWxzZX19LHsiaWQiOjE4NzU3LCJ0aXRsZSI6IumYv+mHjOW3tOW3tC3pq5jlvrfkuovkuJrpg6gt5a6i5oi356uv5rWL6K+V5byA5Y+R5bel56iL5biIIC8g5LiT5a62IiwiY3JlYXRlZF9hdCI6IjIwMTktMDQtMTJUMTc6MDc6MTcuMTY0KzA4OjAwIiwidXBkYXRlZF9hdCI6IjIwMTktMDQtMTJUMTc6MzQ6MDMuNTQ4KzA4OjAwIiwicmVwbGllZF9hdCI6bnVsbCwicmVwbGllc19jb3VudCI6MCwibm9kZV9uYW1lIjoi5oub6IGYIiwibm9kZV9pZCI6MTksImxhc3RfcmVwbHlfdXNlcl9pZCI6bnVsbCwibGFzdF9yZXBseV91c2VyX2xvZ2luIjpudWxsLCJleGNlbGxlbnQiOjAsImxpa2VzX2NvdW50IjowLCJzdWdnZXN0ZWRfYXQiOm51bGwsImNsb3NlZF9hdCI6bnVsbCwiZGVsZXRlZCI6ZmFsc2UsInVzZXIiOnsiaWQiOjUwNCwibG9naW4iOiJkZW5nd2VpNzI5IiwibmFtZSI6IiIsImF2YXRhcl91cmwiOiIvdXBsb2Fkcy91c2VyL2F2YXRhci81MDQuanBnIWxhcmdlIiwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlfX0sImhpdHMiOjE2MSwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlLCJiYW4iOmZhbHNlLCJleGNlbGxlbnQiOmZhbHNlLCJ1bmV4Y2VsbGVudCI6ZmFsc2UsImNsb3NlIjpmYWxzZSwib3BlbiI6ZmFsc2V9fSx7ImlkIjoxNzg5MiwidGl0bGUiOiLkvb/nlKggQWlydGVzdCDotoXlv6vpgJ/lvIDlj5EgQXBwIOeIrOiZqyIsImNyZWF0ZWRfYXQiOiIyMDE5LTAxLTIxVDIwOjM4OjEwLjE2MCswODowMCIsInVwZGF0ZWRfYXQiOiIyMDE5LTA0LTEzVDE3OjUzOjMxLjE4OCswODowMCIsInJlcGxpZWRfYXQiOiIyMDE5LTA0LTEyVDE3OjMyOjM1LjUzMSswODowMCIsInJlcGxpZXNfY291bnQiOjExLCJub2RlX25hbWUiOiJBaXJ0ZXN0Iiwibm9kZV9pZCI6MTM5LCJsYXN0X3JlcGx5X3VzZXJfaWQiOjM2OTkyLCJsYXN0X3JlcGx5X3VzZXJfbG9naW4iOiJwaWthcWl1YWJjIiwiZXhjZWxsZW50IjowLCJsaWtlc19jb3VudCI6MjAsInN1Z2dlc3RlZF9hdCI6bnVsbCwiY2xvc2VkX2F0IjpudWxsLCJkZWxldGVkIjpmYWxzZSwidXNlciI6eyJpZCI6MjU4ODMsImxvZ2luIjoieWltZWxpYSIsIm5hbWUiOiJ6aGFuZ3FpIiwiYXZhdGFyX3VybCI6Ii91cGxvYWRzL3VzZXIvYXZhdGFyLzI1ODgzLzdjMWVmNS5wbmchbGFyZ2UiLCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2V9fSwiaGl0cyI6MTk1OSwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlLCJiYW4iOmZhbHNlLCJleGNlbGxlbnQiOmZhbHNlLCJ1bmV4Y2VsbGVudCI6ZmFsc2UsImNsb3NlIjpmYWxzZSwib3BlbiI6ZmFsc2V9fSx7ImlkIjoxODc1NiwidGl0bGUiOiIgW+W5v+W3nl0g6Zi/6YeM5be05be0LVVDIOaLm+iBmOWuouaIt+err+mrmOe6p+a1i+ivleW8gOWPkeW3peeoi+W4iCAvIOa1i+ivleW8gOWPkeS4k+Wuti3lm73lhoXkuJrliqHpg6ggKOWkp+WOgu+8jOepuumXtOWkp++8jOWPr+iDveaAp+WkmikiLCJjcmVhdGVkX2F0IjoiMjAxOS0wNC0xMlQxNjoyNTo1MS40MDArMDg6MDAiLCJ1cGRhdGVkX2F0IjoiMjAxOS0wNC0xMlQxOTozNDozOS42ODgrMDg6MDAiLCJyZXBsaWVkX2F0IjpudWxsLCJyZXBsaWVzX2NvdW50IjowLCJub2RlX25hbWUiOiLmi5vogZgiLCJub2RlX2lkIjoxOSwibGFzdF9yZXBseV91c2VyX2lkIjpudWxsLCJsYXN0X3JlcGx5X3VzZXJfbG9naW4iOm51bGwsImV4Y2VsbGVudCI6MCwibGlrZXNfY291bnQiOjAsInN1Z2dlc3RlZF9hdCI6bnVsbCwiY2xvc2VkX2F0IjpudWxsLCJkZWxldGVkIjpmYWxzZSwidXNlciI6eyJpZCI6MTg5NjUsImxvZ2luIjoiaHVnb3plcmtlbiIsIm5hbWUiOiJodWdoIGxlZSIsImF2YXRhcl91cmwiOiIvdXBsb2Fkcy91c2VyL2F2YXRhci8xODk2NS80YTc4MzQucG5nIWxhcmdlIiwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlfX0sImhpdHMiOjE4MCwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlLCJiYW4iOmZhbHNlLCJleGNlbGxlbnQiOmZhbHNlLCJ1bmV4Y2VsbGVudCI6ZmFsc2UsImNsb3NlIjpmYWxzZSwib3BlbiI6ZmFsc2V9fSx7ImlkIjoxODM5MiwidGl0bGUiOiJb5rex5ZyzXSBzaG9wZWUg6YeR6J6N57q/ICsg5L6b5bqU6ZO+57q/77yM5rWL5byAICjkuK3pq5jnuqcgK2xlYWRlcikg77yM5aSn6YePIGhjIOetieS9oOadpSAo5YaF5o6oKe+8jOWPpuWkluW8gOWPkeWyl+WPr+WGheaOqCIsImNyZWF0ZWRfYXQiOiIyMDE5LTAzLTA1VDA4OjEwOjUwLjkyMCswODowMCIsInVwZGF0ZWRfYXQiOiIyMDE5LTA0LTEyVDE2OjA4OjQ0LjE3OCswODowMCIsInJlcGxpZWRfYXQiOiIyMDE5LTA0LTEyVDE2OjA4OjQ0LjE2MSswODowMCIsInJlcGxpZXNfY291bnQiOjEyLCJub2RlX25hbWUiOiLmi5vogZgiLCJub2RlX2lkIjoxOSwibGFzdF9yZXBseV91c2VyX2lkIjo2NTgxLCJsYXN0X3JlcGx5X3VzZXJfbG9naW4iOiJpZGxlZ29vc2UiLCJleGNlbGxlbnQiOjAsImxpa2VzX2NvdW50IjoxLCJzdWdnZXN0ZWRfYXQiOm51bGwsImNsb3NlZF9hdCI6bnVsbCwiZGVsZXRlZCI6ZmFsc2UsInVzZXIiOnsiaWQiOjY1ODEsImxvZ2luIjoiaWRsZWdvb3NlIiwibmFtZSI6IiIsImF2YXRhcl91cmwiOiIvdXBsb2Fkcy91c2VyL2F2YXRhci82NTgxL2I4Yzg4OC5wbmchbGFyZ2UiLCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2V9fSwiaGl0cyI6MTA0MywiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlLCJiYW4iOmZhbHNlLCJleGNlbGxlbnQiOmZhbHNlLCJ1bmV4Y2VsbGVudCI6ZmFsc2UsImNsb3NlIjpmYWxzZSwib3BlbiI6ZmFsc2V9fSx7ImlkIjoxODc1NSwidGl0bGUiOiLnu5kgQXBwaXVtIOWGhee9ruezu+e7n+WvueivneahhuiHquWKqOWkhOeQhiAtIGFwcGl1bS11aWF1dG9tYXRvcjItZHJpdmVyIOevhyAiLCJjcmVhdGVkX2F0IjoiMjAxOS0wNC0xMlQxNTo0MjoxOS40NTErMDg6MDAiLCJ1cGRhdGVkX2F0IjoiMjAxOS0wNC0xMlQxNTo0NjozMy44MDcrMDg6MDAiLCJyZXBsaWVkX2F0IjpudWxsLCJyZXBsaWVzX2NvdW50IjowLCJub2RlX25hbWUiOiLkuJPmoI/mlofnq6AiLCJub2RlX2lkIjoxNDUsImxhc3RfcmVwbHlfdXNlcl9pZCI6bnVsbCwibGFzdF9yZXBseV91c2VyX2xvZ2luIjpudWxsLCJleGNlbGxlbnQiOjAsImxpa2VzX2NvdW50IjowLCJzdWdnZXN0ZWRfYXQiOm51bGwsImNsb3NlZF9hdCI6bnVsbCwiZGVsZXRlZCI6ZmFsc2UsInVzZXIiOnsiaWQiOjQyMzEwLCJsb2dpbiI6ImNtbGFuY2hlLWdpdGh1YiIsIm5hbWUiOiJjbWxhbmNoZSIsImF2YXRhcl91cmwiOiIvdXBsb2Fkcy91c2VyL2F2YXRhci80MjMxMC9mMDg4ODIucG5nIWxhcmdlIiwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlfX0sImhpdHMiOjQ2LCJhYmlsaXRpZXMiOnsidXBkYXRlIjpmYWxzZSwiZGVzdHJveSI6ZmFsc2UsImJhbiI6ZmFsc2UsImV4Y2VsbGVudCI6ZmFsc2UsInVuZXhjZWxsZW50IjpmYWxzZSwiY2xvc2UiOmZhbHNlLCJvcGVuIjpmYWxzZX19LHsiaWQiOjE4NDkxLCJ0aXRsZSI6IlvmoKHmi5sgb3Ig56S+5oubXSDpmL/ph4zlt7Tlt7Qg5oub6IGYIOa1i+ivleW8gOWPkeW3peeoi+W4iCAiLCJjcmVhdGVkX2F0IjoiMjAxOS0wMy0xMlQyMDowMzowOS4xNDErMDg6MDAiLCJ1cGRhdGVkX2F0IjoiMjAxOS0wNC0xMlQxNTo0MjoxMy45NTUrMDg6MDAiLCJyZXBsaWVkX2F0IjoiMjAxOS0wNC0xMlQxNTo0MjoxMy45MzIrMDg6MDAiLCJyZXBsaWVzX2NvdW50IjoxNiwibm9kZV9uYW1lIjoi5oub6IGYIiwibm9kZV9pZCI6MTksImxhc3RfcmVwbHlfdXNlcl9pZCI6MjY0MTMsImxhc3RfcmVwbHlfdXNlcl9sb2dpbiI6InB3eTAwMTE5OSIsImV4Y2VsbGVudCI6MCwibGlrZXNfY291bnQiOjEsInN1Z2dlc3RlZF9hdCI6bnVsbCwiY2xvc2VkX2F0IjpudWxsLCJkZWxldGVkIjpmYWxzZSwidXNlciI6eyJpZCI6MjY0MTMsImxvZ2luIjoicHd5MDAxMTk5IiwibmFtZSI6InB3eSIsImF2YXRhcl91cmwiOiIvdXBsb2Fkcy91c2VyL2F2YXRhci8yNjQxMy9hNTg1MzMucG5nIWxhcmdlIiwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlfX0sImhpdHMiOjEzMjIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZSwiYmFuIjpmYWxzZSwiZXhjZWxsZW50IjpmYWxzZSwidW5leGNlbGxlbnQiOmZhbHNlLCJjbG9zZSI6ZmFsc2UsIm9wZW4iOmZhbHNlfX0seyJpZCI6MTg3NTQsInRpdGxlIjoi5oKo6KaB5bqU55So56iL5bqPIOKAnFhDVGVzdFdEVUlUZXN0cy1SdW5uZXIuYXBw4oCdIOaOpeWPl+S8oOWFpee9kee7nOi/nuaOpeWQl++8nyIsImNyZWF0ZWRfYXQiOiIyMDE5LTA0LTEyVDE1OjM5OjQ4LjM3MSswODowMCIsInVwZGF0ZWRfYXQiOiIyMDE5LTA0LTEyVDE1OjM5OjQ4LjM3MSswODowMCIsInJlcGxpZWRfYXQiOm51bGwsInJlcGxpZXNfY291bnQiOjAsIm5vZGVfbmFtZSI6ImlPUyDmtYvor5UiLCJub2RlX2lkIjo1MSwibGFzdF9yZXBseV91c2VyX2lkIjpudWxsLCJsYXN0X3JlcGx5X3VzZXJfbG9naW4iOm51bGwsImV4Y2VsbGVudCI6MCwibGlrZXNfY291bnQiOjAsInN1Z2dlc3RlZF9hdCI6bnVsbCwiY2xvc2VkX2F0IjpudWxsLCJkZWxldGVkIjpmYWxzZSwidXNlciI6eyJpZCI6Mzg1MTUsImxvZ2luIjoiU3RlZmYiLCJuYW1lIjoiU3RlZmYiLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvMzg1MTUvZjRjNWQ2LnBuZyFsYXJnZSIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZX19LCJoaXRzIjoyOSwiYWJpbGl0aWVzIjp7InVwZGF0ZSI6ZmFsc2UsImRlc3Ryb3kiOmZhbHNlLCJiYW4iOmZhbHNlLCJleGNlbGxlbnQiOmZhbHNlLCJ1bmV4Y2VsbGVudCI6ZmFsc2UsImNsb3NlIjpmYWxzZSwib3BlbiI6ZmFsc2V9fSx7ImlkIjoxODc1MSwidGl0bGUiOiLmnInotZ7liY3nq6/otKjph4/kv53pmpzkvZPns7siLCJjcmVhdGVkX2F0IjoiMjAxOS0wNC0xMlQxNDo0OTo1Mi41OTErMDg6MDAiLCJ1cGRhdGVkX2F0IjoiMjAxOS0wNC0xM1QxMDoyMDo1MS45NjArMDg6MDAiLCJyZXBsaWVkX2F0IjoiMjAxOS0wNC0xMlQxNTozMTowMi45NTgrMDg6MDAiLCJyZXBsaWVzX2NvdW50IjoxLCJub2RlX25hbWUiOiLkuJPmoI/mlofnq6AiLCJub2RlX2lkIjoxNDUsImxhc3RfcmVwbHlfdXNlcl9pZCI6MTYyODAsImxhc3RfcmVwbHlfdXNlcl9sb2dpbiI6ImZ1ZGF4IiwiZXhjZWxsZW50IjowLCJsaWtlc19jb3VudCI6Miwic3VnZ2VzdGVkX2F0IjpudWxsLCJjbG9zZWRfYXQiOm51bGwsImRlbGV0ZWQiOmZhbHNlLCJ1c2VyIjp7ImlkIjozODQwOSwibG9naW4iOiJ5b3V6YW5jb2RlciIsIm5hbWUiOiLmnInotZ7mtYvor5Xlm6LpmJ8iLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvMzg0MDkvYzU5ZDIzLnBuZyFsYXJnZSIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZX19LCJoaXRzIjozMTEsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZSwiYmFuIjpmYWxzZSwiZXhjZWxsZW50IjpmYWxzZSwidW5leGNlbGxlbnQiOmZhbHNlLCJjbG9zZSI6ZmFsc2UsIm9wZW4iOmZhbHNlfX0seyJpZCI6MTgxNjIsInRpdGxlIjoiUHl0aG9uK3NlbGVuaXVtIOaAjuS5iOiwg+eUqCBDaHJvbWUg55qE5aSa55So5oi3566h55CG6YeM55qE6YWN572u77yM5a6e546w5aSa5Liq6LSm5Y+35YWN55m76ZmG55qE5pWI5p6c77yfIiwiY3JlYXRlZF9hdCI6IjIwMTktMDItMThUMTI6NTE6NDMuODIyKzA4OjAwIiwidXBkYXRlZF9hdCI6IjIwMTktMDQtMTJUMTU6MDI6NDMuMzk2KzA4OjAwIiwicmVwbGllZF9hdCI6IjIwMTktMDQtMTJUMTU6MDI6NDMuMzc4KzA4OjAwIiwicmVwbGllc19jb3VudCI6Mywibm9kZV9uYW1lIjoiU2VsZW5pdW0iLCJub2RlX2lkIjo3MywibGFzdF9yZXBseV91c2VyX2lkIjo0MjU2OCwibGFzdF9yZXBseV91c2VyX2xvZ2luIjoibmV3dGVzdGVyMTk5OCIsImV4Y2VsbGVudCI6MCwibGlrZXNfY291bnQiOjAsInN1Z2dlc3RlZF9hdCI6bnVsbCwiY2xvc2VkX2F0IjpudWxsLCJkZWxldGVkIjpmYWxzZSwidXNlciI6eyJpZCI6NDEyMTgsImxvZ2luIjoiamFuc2FuY2hhbiIsIm5hbWUiOiJqYW5zYW4iLCJhdmF0YXJfdXJsIjoiL3VwbG9hZHMvdXNlci9hdmF0YXIvNDEyMTgvMjczMDdhLnBuZyFsYXJnZSIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZX19LCJoaXRzIjo0MzEsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZSwiYmFuIjpmYWxzZSwiZXhjZWxsZW50IjpmYWxzZSwidW5leGNlbGxlbnQiOmZhbHNlLCJjbG9zZSI6ZmFsc2UsIm9wZW4iOmZhbHNlfX0seyJpZCI6MTg3NTMsInRpdGxlIjoi5aaC5L2V5omT6YCg5Lic5Y2K55CDIE5vMSDnmoTmtYvor5XmiqXlkYrlmagiLCJjcmVhdGVkX2F0IjoiMjAxOS0wNC0xMlQxNDo1OToyOC43OTIrMDg6MDAiLCJ1cGRhdGVkX2F0IjoiMjAxOS0wNC0xMlQxNToyOToyOS4zNDIrMDg6MDAiLCJyZXBsaWVkX2F0IjpudWxsLCJyZXBsaWVzX2NvdW50IjowLCJub2RlX25hbWUiOiJNYWNhY2EiLCJub2RlX2lkIjo2OCwibGFzdF9yZXBseV91c2VyX2lkIjpudWxsLCJsYXN0X3JlcGx5X3VzZXJfbG9naW4iOm51bGwsImV4Y2VsbGVudCI6MCwibGlrZXNfY291bnQiOjAsInN1Z2dlc3RlZF9hdCI6bnVsbCwiY2xvc2VkX2F0IjpudWxsLCJkZWxldGVkIjpmYWxzZSwidXNlciI6eyJpZCI6MTk1MzMsImxvZ2luIjoieWxseml2IiwibmFtZSI6InppdnlhbmdsbCIsImF2YXRhcl91cmwiOiIvdXBsb2Fkcy91c2VyL2F2YXRhci8xOTUzMy81ZTY3MzQuanBlZyFsYXJnZSIsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZX19LCJoaXRzIjoyMTEsImFiaWxpdGllcyI6eyJ1cGRhdGUiOmZhbHNlLCJkZXN0cm95IjpmYWxzZSwiYmFuIjpmYWxzZSwiZXhjZWxsZW50IjpmYWxzZSwidW5leGNlbGxlbnQiOmZhbHNlLCJjbG9zZSI6ZmFsc2UsIm9wZW4iOmZhbHNlfX1dfQ==

 

    @Test
    public void testBase64(){
        given().auth().basic("hogwarts","123456").log().all()
                .filter((req,res,ctx)->{
                    Response response0ri=ctx.next(req,res);
                    ResponseBuilder responseBuilder=new ResponseBuilder().clone(response0ri);
//                    System.out.println(response0ri.getBody().asString());
                    responseBuilder.setBody(Base64.getDecoder().decode(response0ri.getBody().asString().trim().replace("\n","")));
                    responseBuilder.setContentType(ContentType.JSON);
                    return responseBuilder.build();})
                .when()
                .get("http://localhost:8000/demo.json").then()
                .log().all()
                .statusCode(200)
                .body("topics.id[0]",equalTo(18717));
    }

 

抓包工具中仍爲未解密的數據

 

 

部分用例不用filter:

RestAssured.reset();  //清除filter

 

 

將base64信息解密後的json傳送給服務器

   @Test
    public void testBase64(){
        RestAssured.reset(); //fileter等
        given().auth().basic("hogwarts","123456").log().all()
                .filter((req,res,ctx)->{
//
                    req.getQueryParams()  
                    Response response0ri=ctx.next(req,res);
                    ResponseBuilder responseBuilder=new ResponseBuilder().clone(response0ri);
//                    System.out.println(response0ri.getBody().asString());
                    responseBuilder.setBody(Base64.getDecoder().decode(response0ri.getBody().asString().trim().replace("\n","")));
                    responseBuilder.setContentType(ContentType.JSON);
                    return responseBuilder.build();})
                .when()
                .get("http://localhost:8000/demo.json").then()
                .log().all()
                .statusCode(200)
                .body("topics.id[0]",equalTo(18717));
    }

 

 

 

session filter

  • session name
  • session filter

 

以Jenkins登錄爲例  自動化處理token session

 

 

@Test
    public void testJenkinsLogin(){
        //保存一個有效的session值,登錄憑證
        RestAssured.config = RestAssured.config().sessionConfig(
                new SessionConfig().sessionIdName("JSESSIONID.ae379626"));
        SessionFilter sessionFilter = new SessionFilter();
        given().log().all()
                .filter(sessionFilter)
                .queryParam("j_username","reese")
                .queryParam("j_password","123456")
                .queryParam("Submit","Sign in")
                .when()
                .post("http://localhost:8080/j_acegi_security_check")
                .then()
                .statusCode(302);
        given().log().all()
                .filter(sessionFilter)
                .when().get("http://localhost:8080/login").prettyPeek()
                .then().statusCode(200);
    }

 

課後作業

利用SessionFilter或者自己定義的Filter實現Jenkins的登陸和帶token觸發job

 

 

 

 

Jenkins(2)

22‘

6‘’

測試用例管理

基於xUnit的用例維護

xUnit體系

Java:JUnit、TestNG
Python:UnitTest、PyTest

 

測試用例的管理概念

測試用例 testcase
測試類 class
測試套件 suite

 

測試用例

測試用例核心元素

❖ 測試用例名字
❖ 測試過程
❖ 單元測試
❖ UI自動化測試 Appium Selenium
❖ 接口自動化測試 RestAssured
❖ 。。。
❖ 斷言
❖ JUnit Assert
❖ hamcrest (python)

 

 

基本的測試用例

用例+註解

 

 

 

用例間的執行順序


❖ Default 取決於反射方法獲得的列表,順序固定
❖ @FixMethodOrder(MethodSorters.JVM) 順序可能變化
❖ @FixMethodOrder(MethodSorters.NAME_ASCENDING) 按照名字排序
❖ 大部分情況不會遇到問題,如果出現順序問題,請設置對應的排序方法

可按jvm排序或ASCE碼排序

 

 

初始化順序支持

  • 類級別初始化
    • @BeforeClass
    • @AfterClass
  • 方法級別的初始化
    • @Before
    • @After

 

登錄後執行其餘測試用例 類級別初始化

方法級別的初始化,執行完數據後清除數據

 

 

 

用例初始化執行順序

  • @BeforeClass setUpClass
    • @Before setUp
      • @Test test1()
    • @After tearDown
    • @Before setUp
      • @Test test2()
    • @After tearDown
  • @AfterClass tearDownClass

package restassured;

import org.junit.*;

public class order {
    @BeforeClass
    public static void  setUpClass(){
        System.out.println("BeforeClass setUpClass");
    }
    @AfterClass
    public static void  tearDownClass(){
        System.out.println("AfterClass tearDownClass");
    }

    private void println(String string){
        System.out.println(string);
    }

    @Before
    public void setUp(){
        this.println("Before setUp");
    }

    @After
    public void tearDown(){
        this.println("After tearDown");
    }

    @Test
    public void test1(){
        this.println("Test1");
    }

    @Test
    public void test2(){
        this.println("Test2");
    }

}

 

 

 

 

繼承關係下的執行流程

  • @BeforeClass
  • @BeforeClass
  • @Before
  • @Test
  • @After
  • @AfterClass
  • @AfterClass

 

注意:方法不能重名,重名會被覆蓋掉

 

父類

package restassured;

import org.junit.*;

public class order_inheritance {
    @BeforeClass
    public static void beforeClass(){
        System.out.println("BeforeClass");
    }

    @AfterClass
    public static void afterClass(){
        System.out.println("AfterClass");
    }

    @Before
    public void before(){
        System.out.println("Before");
    }


//    @After
//    public void after(){
//        System.out.println("After");
//    }



    @Test
    public void demo0(){
        System.out.println("demo");
    }
    @Test
    public void demo1(){
        System.out.println("demo1");
    }
    @Test
    public void demo2(){
        System.out.println("demo2");
    }



}

 

子類繼承父類

package restassured;

import org.junit.*;

public class order_children extends order_inheritance {
    @BeforeClass
    public static void beforeClass_children(){
        System.out.println("BeforeClass_children");
    }

    @AfterClass
    public static void afterClass_children(){
        System.out.println("AfterClass_children");
    }

    @Before
    public  void before_children(){
        System.out.println("Before_children");
    }


//    @After
//    public  void after_children(){
////        System.out.println("After_children");
//    }

    @Test
    public void demo0_children(){
        System.out.println("demo_children");
    }
    @Test
    public void demo1_children(){
        System.out.println("demo1_children");
    }
    @Test
    public void demo2_children(){
        System.out.println("demo2_children");
    }

}

 

 

執行子類

 

 

 

 

 

 

22‘

@FixMethodOrder(MethodSorters.NAME_ASCENDING) 按照名字排序

實例

package restassured;

import org.junit.*;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class order_children_asce extends order_inheritance {
    @BeforeClass
    public static void beforeClass_children(){
        System.out.println("BeforeClass_children");
    }

    @AfterClass
    public static void afterClass_children(){
        System.out.println("AfterClass_children");
    }

    @Before
    public  void before_children(){
        System.out.println("Before_children");
    }


//    @After
//    public  void after_children(){
////        System.out.println("After_children");
//    }

    @Test
    public void demo0_children(){
        System.out.println("demo_children");
    }
    @Test
    public void demo1_children(){
        System.out.println("demo1_children");
    }
    @Test
    public void demo2_children(){
        System.out.println("demo2_children");
    }

}

 

 

 

26‘

Appium測試用例管理

  • @BeforeClass
    • 配置Capability
    • 初始化driver
    • 安裝app
  • @Before
    • 啓動並進入特定界面
  • @After
    • 關閉app
  • @AfterClass
    • driver.quit

 

 

RestAssured接口測試用例管理

  • @BeforeClass
    • 數據加載,模塊的初始化
  • @Before
    • 方法初始化
  • @After
  • @AfterClass
    • 數據清理

 

 

27'

定義測試套件

  • RunWith
  • SuiteClasses
  • class

對測試用例集合進行排序

並行執行測試用例

 

 

執行順序

登錄 搜索 添加 關注 等

 

創建

package restassured;

import org.junit.*;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class order_suite extends order_inheritance {
    @BeforeClass
    public static void beforeClass_order_suite(){
        System.out.println("BeforeClass_order_suite");
    }

    @AfterClass
    public static void afterClass_order_suite(){
        System.out.println("AfterClass_order_suite");
    }

    @Before
    public  void before_order_suite(){
        System.out.println("Before_order_suite");
    }


//    @After
//    public  void after_children(){
////        System.out.println("After_children");
//    }

    @Test
    public void demo0_order_suite(){
        System.out.println("demo_order_suite");
    }
    @Test
    public void demo1_order_suite(){
        System.out.println("demo1_corder_suite");
    }
    @Test
    public void demo2_order_suite(){
        System.out.println("demo2_order_suite");
    }

}

 

package restassured;


import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
        order_suite.class,order_children.class
})
public class order_suite_demo {
}

 

 

 

分組

帶有標籤的測試類

  • 方法級別的標籤
  • 類級別的標籤

Junit 根據Category進行區分

 

 

 

package restassured;

import org.junit.*;

public class order_tag1 extends order_inheritance {
    @BeforeClass
    public static void beforeClass_children(){
        System.out.println("BeforeClass_children");
    }

    @AfterClass
    public static void afterClass_children(){
        System.out.println("AfterClass_children");
    }

    @Before
    public  void before_children(){
        System.out.println("Before_children");
    }


//    @After
//    public  void after_children(){
////        System.out.println("After_children");
//    }
    @Ignore("just for show")
    @Test
    public void demo0_children(){
        System.out.println("demo_children");
    }
    @Test
    public void demo1_children(){
        System.out.println("demo1_children");
    }
    @Test
    public void demo2_children(){
        System.out.println("demo2_children");
    }

}

 

package restassured;

import org.junit.*;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class order_tag2 extends order_inheritance {
    @BeforeClass
    public static void beforeClass_order_suite(){
        System.out.println("BeforeClass_order_suite");
    }

    @AfterClass
    public static void afterClass_order_suite(){
        System.out.println("AfterClass_order_suite");
    }

    @Before
    public  void before_order_suite(){
        System.out.println("Before_order_suite");
    }


//    @After
//    public  void after_children(){
////        System.out.println("After_children");
//    }

    @Test
    public void demo0_order_suite(){
        System.out.println("demo_order_suite");
    }
    @Test
    public void demo1_order_suite(){
        System.out.println("demo1_corder_suite");
    }
    @Test
    public void demo2_order_suite(){
        System.out.println("demo2_order_suite");
    }

}

 

package restassured;


import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
        order_tag1.class,order_tag2.class
})
public class order_tag_demo {
}

 


創建標籤

測試環境及正式環境

package restassured;

public class order_tag_product {
}

 

package restassured;

public class order_tag_stage {
}

 

給測試用例添加標籤

package restassured;

import org.junit.*;
import org.junit.experimental.categories.Category;

public class order_tag1 extends order_inheritance {
    @BeforeClass
    public static void beforeClass_children(){
        System.out.println("BeforeClass_children");
    }

    @AfterClass
    public static void afterClass_children(){
        System.out.println("AfterClass_children");
    }

    @Before
    public  void before_children(){
        System.out.println("Before_children");
    }


//    @After
//    public  void after_children(){
////        System.out.println("After_children");
//    }
    @Ignore("just for show")
    @Test
    public void demo0_children(){
        System.out.println("demo_children");
    }
    @Test
    @Category(order_tag_stage.class)
    public void demo1_children(){
        System.out.println("demo1_children");
    }

    @Test
    @Category(order_tag_product.class)
    public void demo2_children(){
        System.out.println("demo2_children");
    }

}

 

package restassured;

import org.junit.*;
import org.junit.experimental.categories.Category;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class order_tag2 extends order_inheritance {
    @BeforeClass
    public static void beforeClass_order_suite(){
        System.out.println("BeforeClass_order_suite");
    }

    @AfterClass
    public static void afterClass_order_suite(){
        System.out.println("AfterClass_order_suite");
    }

    @Before
    public  void before_order_suite(){
        System.out.println("Before_order_suite");
    }


//    @After
//    public  void after_children(){
////        System.out.println("After_children");
//    }

    @Test
    public void demo0_order_suite(){
        System.out.println("demo_order_suite");
    }
    @Test
    @Category(order_tag_product.class)
    public void demo1_order_suite(){
        System.out.println("demo1_corder_suite");
    }


    @Test
    @Category(order_tag_stage.class)
    public void demo2_order_suite(){
        System.out.println("demo2_order_suite");
    }

}

 

基於標籤運行

  • include
  • exclude

基於suite分類,增加註解

 

執行測試用例

測試用例分類

example1:用於線上測試分類

package restassured;


import org.junit.experimental.categories.Categories;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Categories.class)
@Categories.IncludeCategory(order_tag_product.class)
@Suite.SuiteClasses({
        order_tag1.class,order_tag2.class
})
public class order_tag_demo_product {
}

 

 

example2:用於測試環境分類

 

package restassured;


import org.junit.experimental.categories.Categories;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Categories.class)
@Categories.IncludeCategory(order_tag_stage.class)
@Suite.SuiteClasses({
        order_tag1.class,order_tag2.class
})
public class order_tag_demo_stage {
}

 

 

Exclude

package restassured;


import org.junit.experimental.categories.Categories;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Categories.class)
@Categories.ExcludeCategory(order_tag_product.class)
@Suite.SuiteClasses({
        order_tag1.class,order_tag2.class
})
public class order_tag_demo_product_exclude {
}

 

 

用途

 

  • 冒煙測試集合
  • 線上巡檢集合

 

1‘30(1)

數據驅動

參數化

 

  • RunWith
  • Parameterized
  • static Parameters
  • Parameter

 

 

 

需要修改junit版本爲4.12即可運行方法2

package restassured;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.Arrays;

import static com.jayway.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;


@RunWith(Parameterized.class)
//參數化運行類
public class data_driven {
    @Parameterized.Parameters(name ="{0}vs{1}")
    //創建一個靜態方法,用於提供數據
    public static Iterable<Object[]> data(){
        return Arrays.asList(new Integer[][]{
                {0,0},{1,1},{2,3}
        });
    }


    //方法2!!!
//    @Parameterized.Parameters
//    //創建一個靜態方法,用於提供數據
//    public static Integer [][] data(){
//        return new Integer[][]{
//                {0,0},{1,1},{2,3}
//        };
//    }

    //藉助parameter對於數據進行命名
    @Parameterized.Parameter
    public int first;

    @Parameterized.Parameter(1)
    public int second;

    @Test
    public void testDemo(){
        assertThat(first,equalTo(second));
    }

    //用於接口測試的實例
    @Test
    public void testBaidu(){
        given()
                .get("http://www.baidu.com/s?wd=201"+first).then().statusCode(200)
                .body("html.head.title",equalTo("201"+second+"_百度搜索"));
    }
}

 

 

 

1'44

數據驅動

  • 數據來源:csvyamlxmldbexceljson
  • 讀取數據源返回數組:
    • 基於schemaList<Class>
    • 純數據:Array<Array<String, Object>>
  • 利用參數化進行數據與變量的對應

 

 

jackson  讀取數據源的庫

 

 

 

Excel CSV 數據

添加依賴


        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.7.0</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-csv</artifactId>
            <version>2.7.3</version>
        </dependency>


        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>1.3</version>
        </dependency>

        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-library</artifactId>
            <version>1.3</version>
        </dependency>

引入jar包

import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;

 

3,"3"
4,"5"
package restassured;

import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

@RunWith(Parameterized.class)
//參數化運行類
public class DataDriverByExcel {
    @Parameterized.Parameters
    //創建一個靜態方法,用於提供數據
    public static List<DataClass> data() throws IOException {
        ArrayList<DataClass> data = new ArrayList<DataClass>();

        CsvMapper mapper = new CsvMapper();
        CsvSchema schema = mapper.schemaFor(DataClass.class);
        File csvFile = new File(DataDriverByExcel.class.getResource("../data/input.csv").getFile());
        MappingIterator<DataClass> it = mapper.readerFor(DataClass.class).with(schema).readValues(csvFile);
        while (it.hasNext()) {
            DataClass row = it.next();
            data.add(row);
        }
        return data;
    }


    @Parameterized.Parameter
    public DataClass data;


    @Test
    public void testDemo(){
        assertThat(data.getCount(),equalTo(Integer.parseInt(data.getKey())));
    }


}

 

QA:

 

https://m.imooc.com/wenda/detail/329935

 

Yaml

添加依賴

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-yaml</artifactId>
    <version>2.7.3</version>
</dependency>

 

- count: 3
  key: "22"
- count: 4
  key: "4"
- count: 6
  key: "888"

 

package restassured;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.File;
import java.io.IOException;
import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;

@RunWith(Parameterized.class)
//參數化運行類
public class DataDriverByYaml {
    @Parameterized.Parameters
    //創建一個靜態方法,用於提供數據
    public static List<DataClass> data() throws IOException {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
//        ArrayList<DataClass> data = new ArrayList<DataClass>();
        List<DataClass> data=mapper.readValue(
                new File(DataDriverByYaml.class.getResource("../data/input.yaml").getFile()),
                new TypeReference<List<DataClass>>() {}
                );
        return data;
    }

    @Parameterized.Parameter
    public DataClass data;

    @Test
    public void testDemo(){
        assertThat(data.getCount(),equalTo(Integer.parseInt(data.getKey())));
    }
}

 

 

用於登錄測試較多,搜索等功能

 

數據格式的選擇

 

 

數據驅動邏輯

  • 結構化數據驅動:
    • 根據表格數據解釋執行,Excel、YAML、XML
    • 將行爲也數據化
  • 高層抽象
    • ATDD:驗收測試驅動開發,藉助於數據與DSL實現用例描述,代表作是框架 RobotFramework
    • BDD:行爲驅動開發,基於自然語言描述用例,實現仍然是基於傳統的編程方式,代表作Cucumber

 

  • 犧牲靈活性,無法大規模應用,維護成本較高

 

 

 

 

Test Rule

測試用例規則test rule

 

  • 用於在測試用例執行時重定義行爲
  • TestWatcher
  • TestName Rule
  • Timeout Rule
  • Class Rule
  • 自定義Rule

 

運行時獲得當前用例名字

suite級別的初始化順序

 

 

 

用例組織

按照業務分包管理

  • 不同的產品和模塊進行分包
    • com.xx.featureA
    • com.xx.featureB
  • 不同包下要有對應的用途相關的運行套件
    • com.xx.featureASuite
  • 考慮儘可能並行

 

 

按照用途分組並用Suite管理

  • 分組
    • 冒煙測試
    • 巡檢測試
    • 異常測試
    • 安全測試
  • 分Suite
    • 不同的用途直接用Suite管理

 

 

並行執行

  • 藉助於Jenkins的多進程運行
  • 藉助於maven的多線程運行

 

擴展

  • https://github.com/junit-team/junit4/wiki/Custom- runners

 

  • 並行
  • 數據驅動
  • mock
  • BDD

 

 

 

maven結合

maven項目

  • 創建maven項目
  • 添加依賴
  • search.maven.org
  • 在src/test下創建用例

 

 

mvn執行用例

 

  • mvn -Dtest=TestCircle test
  • mvn -Dtest=TestSquare,TestCi*le test
  • mvn -Dtest=TestCircle#testOne+testTwo test

 

  • mvn -Dsurefire.rerunFailingTestsCount=2 test  
  • (用例執行失敗將會重新執行)

 

mvn test 默認執行全部的測試用例


mvn -Dtest=order_tag2 test

 

 

 

 

58'

部署到Jenkins上執行

創建一個包 junit,導入測試用例order_children2

執行測試用例
D:\Tool\demo>mvn -Dtest=order_children2 test

package junit;

import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import restassured.order_inheritance;

import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;

public class order_children2 extends order_inheritance {
    @BeforeClass
    public static void beforeClass_children(){
        System.out.println("BeforeClass_children");
    }

    @AfterClass
    public static void afterClass_children(){
        System.out.println("AfterClass_children");
    }

    @Before
    public  void before_children(){
        System.out.println("Before_children");
    }


//    @After
//    public  void after_children(){
////        System.out.println("After_children");
//    }

    @Test
    public void demo0_children2(){
        System.out.println("demo_children");
    }
    @Test
    public void demo1_children2(){
        System.out.println("demo1_children");
        assertThat(1,equalTo(2));
    }
    @Test
    public void demo2_children2(){
        System.out.println("demo2_children");
    }

}

跳到測試用例報告

 

 

 

 

調試測試用例

  • mvn -Dmaven.surefire.debug test
  • mvn -Dmaven.surefire.debug="-Xdebug - Xrunjdwp:transport=dt_socket,server=y,suspend=y,add ress=8000 -Xnoagent -Djava.compiler=NONE" test

 

 

maven並行配置

http://maven.apache.org/surefire/maven-surefire-plugin/examples/fork-options-and-parallel-execution.html

 

並行執行機制

  • 多線程
    • parallel決定並行維度
      • methods, classes, both, suites,
      • suitesAndClasses, suitesAndMethods, classesAndMethods or  all
    • threadCount決定並行數量
  • 多進程
    • forkCount 基於class進行進程併發
    • reuseForks 是否複用進程資源

 

59

 

 

 

 

測試結果

  • mvn test  默認所有測試用例的class必須是Test開頭
  • xml結果 ${basedir}/target/surefire-reports/TEST-*.xml

 

  •  

 

 

 

在pom.xml中添加插件

        <plugin>
            <artifactId>maven-project-info-reports-plugin</artifactId>
            <version>2.7</version>
        </plugin>
  • mvn site   下載插件
  • mvn surefire-report:report-only
  • html結果:target/site/surefire-report.html

參考:http://maven.apache.org/surefire/maven-surefire-report-plugin/

http://maven.apache.org/surefire/dependency-info.html

添加插件

<dependency>
  <groupId>org.apache.maven.surefire</groupId>
  <artifactId>surefire</artifactId>
  <version>3.0.0-M3</version>
  <type>pom</type>
</dependency>

mvn surefire-report:report -Dtest=order_children2 test

 

 

html報告

 

 

 

 

 

 

Jenkins

 

 

創建節點

https://blog.csdn.net/lee2315/article/details/82758988

選擇節點

 

 

 

 

 

1'34

 

生成測試報告

 

 

運行結束後查看運行結果

問題:不能生成測試報告

 

 

Recording test results
Build step 'Publish JUnit test result report' changed build result to UNSTABLE
Finished: UNSTABLE

 

HTTP ERROR 404

Problem accessing /job/Restassured0416/28/testReport/junit/order_children2/demo1_children2//summary. Reason:

    Not Found

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章