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 {@Testpublic 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 {@BeforeClasspublic static void BeforeClass(){useRelaxedHTTPSValidation();}@Testpublic 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校验

  • https://jsonschema.net/
  • 生成schema文件
  • 手工编辑增强
  • 调用matchesJsonSchemaInClasspath等系列 法

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;@Testpublic 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值}@Testpublic 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 {@Testpublic 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

❖ 通用的请求数据记录

❖ 记录所有的请求和响应

    @Testpublic 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逻辑

    @BeforeClasspublic 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==
    @Testpublic 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传送给服务器

   @Testpublic 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

@Testpublic 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 {@BeforeClasspublic static void  setUpClass(){System.out.println("BeforeClass setUpClass");}@AfterClasspublic static void  tearDownClass(){System.out.println("AfterClass tearDownClass");}private void println(String string){System.out.println(string);}@Beforepublic void setUp(){this.println("Before setUp");}@Afterpublic void tearDown(){this.println("After tearDown");}@Testpublic void test1(){this.println("Test1");}@Testpublic void test2(){this.println("Test2");}}

继承关系下的执行流程

  • 父类@BeforeClass
  • 子类@BeforeClass
  • @Before
  • @Test
  • @After
  • 子类@AfterClass
  • 父类@AfterClass

注意:方法不能重名,重名会被覆盖掉

父类

package restassured;import org.junit.*;public class order_inheritance {@BeforeClasspublic static void beforeClass(){System.out.println("BeforeClass");}@AfterClasspublic static void afterClass(){System.out.println("AfterClass");}@Beforepublic void before(){System.out.println("Before");}//    @After
//    public void after(){
//        System.out.println("After");
//    }@Testpublic void demo0(){System.out.println("demo");}@Testpublic void demo1(){System.out.println("demo1");}@Testpublic void demo2(){System.out.println("demo2");}}

子类继承父类

package restassured;import org.junit.*;public class order_children extends order_inheritance {@BeforeClasspublic static void beforeClass_children(){System.out.println("BeforeClass_children");}@AfterClasspublic static void afterClass_children(){System.out.println("AfterClass_children");}@Beforepublic  void before_children(){System.out.println("Before_children");}//    @After
//    public  void after_children(){System.out.println("After_children");
//    }@Testpublic void demo0_children(){System.out.println("demo_children");}@Testpublic void demo1_children(){System.out.println("demo1_children");}@Testpublic 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 {@BeforeClasspublic static void beforeClass_children(){System.out.println("BeforeClass_children");}@AfterClasspublic static void afterClass_children(){System.out.println("AfterClass_children");}@Beforepublic  void before_children(){System.out.println("Before_children");}//    @After
//    public  void after_children(){System.out.println("After_children");
//    }@Testpublic void demo0_children(){System.out.println("demo_children");}@Testpublic void demo1_children(){System.out.println("demo1_children");}@Testpublic 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 {@BeforeClasspublic static void beforeClass_order_suite(){System.out.println("BeforeClass_order_suite");}@AfterClasspublic static void afterClass_order_suite(){System.out.println("AfterClass_order_suite");}@Beforepublic  void before_order_suite(){System.out.println("Before_order_suite");}//    @After
//    public  void after_children(){System.out.println("After_children");
//    }@Testpublic void demo0_order_suite(){System.out.println("demo_order_suite");}@Testpublic void demo1_order_suite(){System.out.println("demo1_corder_suite");}@Testpublic 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 {@BeforeClasspublic static void beforeClass_children(){System.out.println("BeforeClass_children");}@AfterClasspublic static void afterClass_children(){System.out.println("AfterClass_children");}@Beforepublic  void before_children(){System.out.println("Before_children");}//    @After
//    public  void after_children(){System.out.println("After_children");
//    }@Ignore("just for show")@Testpublic void demo0_children(){System.out.println("demo_children");}@Testpublic void demo1_children(){System.out.println("demo1_children");}@Testpublic 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 {@BeforeClasspublic static void beforeClass_order_suite(){System.out.println("BeforeClass_order_suite");}@AfterClasspublic static void afterClass_order_suite(){System.out.println("AfterClass_order_suite");}@Beforepublic  void before_order_suite(){System.out.println("Before_order_suite");}//    @After
//    public  void after_children(){System.out.println("After_children");
//    }@Testpublic void demo0_order_suite(){System.out.println("demo_order_suite");}@Testpublic void demo1_order_suite(){System.out.println("demo1_corder_suite");}@Testpublic 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 {@BeforeClasspublic static void beforeClass_children(){System.out.println("BeforeClass_children");}@AfterClasspublic static void afterClass_children(){System.out.println("AfterClass_children");}@Beforepublic  void before_children(){System.out.println("Before_children");}//    @After
//    public  void after_children(){System.out.println("After_children");
//    }@Ignore("just for show")@Testpublic 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 {@BeforeClasspublic static void beforeClass_order_suite(){System.out.println("BeforeClass_order_suite");}@AfterClasspublic static void afterClass_order_suite(){System.out.println("AfterClass_order_suite");}@Beforepublic  void before_order_suite(){System.out.println("Before_order_suite");}//    @After
//    public  void after_children(){System.out.println("After_children");
//    }@Testpublic 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.Parameterpublic int first;@Parameterized.Parameter(1)public int second;@Testpublic void testDemo(){assertThat(first,equalTo(second));}//用于接口测试的实例@Testpublic void testBaidu(){given().get("http://www.baidu.com/s?wd=201"+first).then().statusCode(200).body("html.head.title",equalTo("201"+second+"_百度搜索"));}
}

1'44

数据驱动

  • 数据来源:csv、yaml、xml、db、excel、json
  • 读取数据源返回数组:
    • 基于schema:List<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.Parameterpublic DataClass data;@Testpublic 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: 3key: "22"
- count: 4key: "4"
- count: 6key: "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.Parameterpublic DataClass data;@Testpublic 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 {@BeforeClasspublic static void beforeClass_children(){System.out.println("BeforeClass_children");}@AfterClasspublic static void afterClass_children(){System.out.println("AfterClass_children");}@Beforepublic  void before_children(){System.out.println("Before_children");}//    @After
//    public  void after_children(){System.out.println("After_children");
//    }@Testpublic void demo0_children2(){System.out.println("demo_children");}@Testpublic void demo1_children2(){System.out.println("demo1_children");assertThat(1,equalTo(2));}@Testpublic 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

测试用例管理与Jenkins集成相关推荐

  1. Windows 环境 Jenkins集成构建SonarQube

    关于Windows搭建SonarQube_Mysql的相关操作先点击下面的链接,进行跳转. 操作手册: Windows搭建SonarQube_Mysql 启动Jenkins有2种方式: 第1种:jav ...

  2. python测试用例管理工具_三款开源测试管理工具推荐

    测试管理包括测试过程中的测试计划,测试执行以及执行结果的存储和分析. 具体来说就是和其它工具比如需求管理工具,功能测试工具比如Selenium和Cucumber,持续集成工具比如Jenkins和Tea ...

  3. jenkins 插件目录_Windows下allure+pytest+jenkins集成手册!

    Pytest是什么 pytest是python的一款测试框架,拥有unittest的功能并比它更丰富. Allure是什么 有非常多的优秀的测试框架,但却是有非常少优秀的报告工具可以展示非常清楚的用例 ...

  4. SonarQube安装配置,与jenkins集成、查看检查结果,solr和idea进行集成使用

    1.Sonar简介 Sonar是一个用于代码质量管理的开源平台,用于管理源代码的质量,可以从七个维度检测代码质量,通过插件形式,可以支持包括java,C#,C/C++,PL/SQL,Cobol,Jav ...

  5. 除 svn、Testlink 外,还有哪些不错的测试用例管理工具?

    类似 TestLink的 9 大测试用例管理平台:1.PingCode:2.TestRail:3.Xray:4.Jira:5.PractiTest:6.PractiTest:7. Zephyr Ent ...

  6. 测试用例管理工具SynapseRT(jira插件)的具体使用(一)

    话说我们测试团队使用Zephyr进行测试用例管理一段时间后,得到大家的认可,反馈还不错,但我还是觉得它功能太单一,缺点较多(例如提供信息较少.无法记录和跟踪需求.管理人员无法直观了解测试进度等等),为 ...

  7. [6] 测试用例管理工具的需求整理

    昨天整理的测试用例管理工具的需求,因为公司准备在test link的基础上进行修改,所以根据使用 TestLink 进行测试管理 『转载』中提到的功能进行了一些对比,文中灰色字体部分都是摘自 使用 T ...

  8. ldap配置系列二:jenkins集成ldap

    ldap配置系列二:jenkins集成ldap jenkins简介 jenkins是一个独立的.开放源码的自动化服务器,它可以用于自动化与构建.测试.交付或部署软件相关的各种任务. jenkins官方 ...

  9. 基于docker使用jenkins集成sonar

    前言 基于jenkins可以完成项目的可持续集成,同时由于jenkins强大的插件管理功能,可以集成众多的其他插件完成项目管理中的其他功能,比如可以使用jenkins集成sonar完成对项目构建的时候 ...

最新文章

  1. JS: 关于元素大小和距离的有关的属性总结
  2. 2014年百度之星程序设计大赛 - 资格赛 1004 Labyrinth(Dp)
  3. [SAP ABAP开发技术总结]动态语句、动态程序
  4. 0201小型封装ESD二极管,型号汇总
  5. python--Websocket实现, 加密 sha1,base64
  6. 【远程办公】5分钟一拍照、10分钟一截屏 ?
  7. 多闪实名举报河南法院;ofo 内部发反腐文件;库克访华点赞故宫 App | 极客头条...
  8. ASP.NET案例--新闻模块设计
  9. SQL 2008R2 安装失败问题
  10. Can‘t exec “aclocal“: 没有那个文件或目录 at /usr/share/autoconf/Autom4te/FileUtils.pm line 326.
  11. Unity--使用反编译软件ILSpy查看dll中的代码
  12. 白盒测试-条件组合覆盖
  13. CPU(中央处理器)和GPU(图像处理器)区别
  14. matlab泊松分布随机数和图像,基于Matlab的Poisson分布随机数的Monte carlo模拟
  15. Unity3d Platformer Pro 2D游戏开发框架使用教程
  16. php程序员述职材料_求一个PHP程序员的试用期转正的述职报告 要求详细一点的 分数不够可以再加,在线急等...
  17. 试题 算法训练 翻转旋转变换
  18. google相机android10,三星S10+/S10/S10e谷歌相机移植版下载:支持夜视,体验强大算法...
  19. C语言——scanf()函数的具体详解
  20. 使用百度人工智能识别表格

热门文章

  1. Matlab的Notebook软件工具设置及程序运行
  2. pycharm怎么改成中文(汉化插件 pycharm自带)
  3. 2017年美国数学建模MCM/ICM ABCDEF试题分析
  4. 人工智能助力新零售,无人售货柜降至6000元
  5. java 日历备忘录_Java日历及备忘录
  6. Win10正常安装Matlab7.0后,运行出现Runtime Error错误解决方法
  7. 联瑞网卡获得银河麒麟操作系统适配认证证书
  8. 一个简单的python程序实例(通讯录)
  9. 数据改版 | CnOpenData中国工业企业基本信息扩展数据
  10. Python网络爬虫实战项目代码大全(长期更新,欢迎补充)