如何确保API 的稳定性与正确性?你只需要这一招

188 篇文章 0 订阅
183 篇文章 1 订阅

一、什么是rest-assured
现在,越来越多的 Web 应用转向了RESTful的架构,很多产品和应用暴露给用户的往往就是一组 REST API,这 样有一个好处,用户可以根据需要,调用不同的 API,整合出自己的应用出来。从这个角度来讲,Web 开发的成本会越来越低,人们不必再维护自己的信息孤岛,而是使用 REST API 这种组合模式。

那么,作为 REST API 的提供者,如何确保 API 的稳定性与正确性呢?全面系统的测试是必不可少的。Java 程 序员常常借助于 JUnit 来测试自己的 REST API,不,应该这样说,Java 程序员常常借助于JUnit 来测试 REST API的实现!从某种角度来说,这是一种“白盒测试”,Java 程序员清楚地知道正在测试的是哪个类、哪个方 法,而不是从用户的角度出发,测试的是哪个REST API。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eaTJP3AB-1648447983167)(https://ceshiren.com/uploads/default/original/3X/c/0/c0f2baadfa15e0549eee87abdce4560ff4b995d6.jpeg)]

Rest-Assured 是一套由 Java 实现的 REST API测试框架,它是一个轻量级的REST API 客户端,可以直接编写代码向服务器端发起 HTTP请求,并验证返回结果;它的语法非常简洁,是一种专为测试 REST API 而设计的 DSL。使用 Rest-Assured 测试 REST API,就和真正的用户使用 REST API 一样,只不过 Rest-Assured 让这一切变得自动化了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bKETC3BK-1648447984359)(https://ceshiren.com/uploads/default/original/3X/d/9/d96ab7b08ba1e34b27d14e766df78ea4e0fdc5d8.jpeg)]

二、模拟get请求
雪球网是一个股票投资网站,你可以使用网站的搜索功能来查询股票信息,比如我们想查询sougou的信息,下 面利用了charles分析工具来查看请求和回答:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YzkpM9hX-1648447985130)(https://ceshiren.com/uploads/default/original/3X/8/6/86bf76ba843c63c133b985178b5019b1e37066f5.gif)]

这是一个Get请求,返回的内容格式如下:

现在,我们使用 Rest-Assured 来编写一个简单的测试程序调用相同的Get请求:

  • 第一步,我们要判断这是什么格式数据:json
    • 第二步,确定请求地址:从charles的结果中获取y为https://xueqiu.com/stock/search.json
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bv8KYxST-1648447987043)(https://ceshiren.com/uploads/default/original/3X/9/a/9af5988eb450cfb9e7f227ea03d0ba8e2c6c1589.png)]
    • 第三步,填写表单:从chrome浏览器检查结果中查询request的query信息是code:sougou
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BX2Qx4kI-1648447988171)(https://ceshiren.com/uploads/default/original/3X/2/b/2b60684f2cd10aa568fd867b1bc8ddd3cdb0fe2a.png)]
    我们的代码也很简单:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mdaf7eyg-1648447989319)(https://ceshiren.com/uploads/default/original/3X/a/e/ae31cd8cc9695ecd0a688f2e10d845e09f7adb42.jpeg)]

返回的结果却很残酷:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gqVo8WYF-1648447990073)(https://ceshiren.com/uploads/default/original/3X/c/7/c795ce1740844b7788ee188a683b729a1cfef136.png)]

与登陆账号,刷新页面有关的话,我首先想到了cookie,网站都用cookie来保存账号相关信息,于是加入 cookie:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-naIWscef-1648447991145)(https://ceshiren.com/uploads/default/original/3X/d/1/d1df68fbf7180f7bfbd7b3acff147b5022eb3814.jpeg)]

返回结果正确,你问我惊不惊喜,老实回答,不惊喜。因为我搞不明白为什么一个查询需要cookie验证,如果 不加cookie,返回的信息却是没有登陆!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H6AVKlpM-1648447992328)(https://ceshiren.com/uploads/default/original/3X/0/0/00c1b4a7507dea6da3f25b774a461a104d493029.jpeg)]
显然,我的cookie并不包含登陆信息,因为我压根就没有登陆,当然这是网站的设计,与rest-assured无关。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jov1gaib-1648447993529)(https://ceshiren.com/uploads/default/original/3X/2/2/228ad26e63af1d8f7b5dc43398407476dd02848d.jpeg)]

更进一步
怎么区别xml与json
答:你看就知道了嘛,xml长这个样子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qTM6s3j4-1648447994771)(https://ceshiren.com/uploads/default/original/3X/d/f/df983a4855195118be403cadd4618c34f578c4c3.jpeg)]

json长这个样子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zlcOoaEo-1648447995541)(https://ceshiren.com/uploads/default/original/3X/f/2/f25e6517cf216e63694d30fb25585d51ac57d0c3.png)]

given,when,then分别是什么
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EpheEikw-1648447996500)(https://ceshiren.com/uploads/default/original/3X/c/9/c9dcd136879fcafbe460ffc855e09b6b984c1c10.jpeg)]

答:given用于放置需要的参数,比如上面例子中,我将访问参数:code和cookie放到了given里;when用于填 写要访问的url;then进行断言,来来判断结果是否正确。

三、模拟post请求
有的时候,我们想提交表单,这种情况下使用get会非常被动,于是post登场了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2YIn0Zks-1648447997956)(https://ceshiren.com/uploads/default/original/3X/a/6/a6c59e7a4617a35691a62a4cfcacf7436da5a36e.png)]

下面是代码。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZqAUeAZw-1648447998933)(https://ceshiren.com/uploads/default/original/3X/0/f/0f72e88d7032bbf9b95ff0e901a396fe4ce74504.png)]

我相信此时你的内心是这样的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-StaIYY2J-1648448000024)(https://ceshiren.com/uploads/default/original/3X/f/c/fcd91fba88bfea85f370326592c56a114ce02b1f.jpeg)]

别着急,下面我会讲清楚…
在我大万维网世界中,TCP就像汽车,我们用TCP来运输数据,它很可靠,从来不会发生丢件少件的现象。但是 如果路上跑的全是看起来一模一样的汽车,那这个世界看起来是一团混乱,非常紧急的警车可能被前面的汽车拦堵在路上,整个交通系统一定会瘫痪。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dYfavaE7-1648448001752)(https://ceshiren.com/uploads/default/original/3X/f/a/fa69658788575d72c2efcbc6d8af51251cfad02d.jpeg)]

为了避免这种情况发生,交通规则HTTP诞生了。HTTP给汽车运输设定了好几个服务类别,有GET, POST, PUT, DELETE等等,HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求 把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放 在车厢里。当然,你也可以在GET的时候往车厢内偷偷藏点货物,但是这是很不光彩;也可以在POST的时候在车顶上也放一些数据,让人觉得傻乎乎的。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ArPIedIn-1648448004285)(https://ceshiren.com/uploads/default/original/3X/c/8/c8598f075e6bc26226bbaa7d96945f6224e8f6fb.jpeg)]

四、使用断言
使用equalTo
在前面,我们使用了equalTo判断值是否是“搜狗”:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kCGKFmbz-1648448006489)(https://ceshiren.com/uploads/default/original/3X/2/f/2fc174ce3b1208a8dc4dec84579eecdc6e7a99ce.png)]

它的作用显而易见:判断值是否相同。比如下面的例子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V7e6Ct26-1648448007988)(https://ceshiren.com/uploads/default/original/3X/b/1/b13bfd3e19dc7ae87f68c63e770d4b70050237b8.jpeg)]

如果你想验证lottoId是否等于5,你可以这样做:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QLq1cVQw-1648448009678)(https://ceshiren.com/uploads/default/original/3X/2/0/20443dbaf6e1c330a4e1575f20daafe4a77e15e7.png)]

使用hasItems
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Ml7f8cY-1648448011477)(https://ceshiren.com/uploads/default/original/3X/5/6/5676349b1cba7b62e4e0c390a3f89126cbce25d5.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8tblmlAc-1648448012940)(https://ceshiren.com/uploads/default/original/3X/b/9/b928ded901cf25312160ed8328a7042d1452b0a1.jpeg)]
你可以用再次equalTo(),对winnerId[0]用一次,对winnerId[1]用一次。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8cvLVcT5-1648448015561)(https://ceshiren.com/uploads/default/original/3X/6/7/67e357530fb6eae535c2e6c1ad28d5417c0c0935.jpeg)]
哈哈,当然不是。你可以使用hasItems,它是这么使用的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jITPe4Fq-1648448018529)(https://ceshiren.com/uploads/default/original/3X/7/5/7572f65cf4ee8b461d4a7a2da1a74555031d97cf.png)]

从根开始定位
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ameXTtQL-1648448019345)(https://ceshiren.com/uploads/default/original/3X/f/9/f941f210c8b3a4622f6f663ff78aa9c352762852.jpeg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9S6nIupj-1648448020211)(https://ceshiren.com/uploads/default/original/3X/8/8/8808d34eb4b4fa9fc475d2a83392bfdb1848f0a0.png)]
额…请教王师傅。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2pIdAF55-1648448021370)(https://ceshiren.com/uploads/default/original/3X/7/5/7572849345bf1e7e80038aeabef21ae139e51692.jpeg)]

比如下面的代码,我们可以这么验证:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iGTUCeD1-1648448022425)(https://ceshiren.com/uploads/default/original/3X/d/0/d0997a1ff9af9b03ed408c1113985ee3255926df.png)]

使用find
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1o4P6u68-1648448023721)(https://ceshiren.com/uploads/default/original/3X/3/8/383e3d242fd09c654bd950f607c27a1a002f1692.jpeg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CGtPjjiu-1648448024965)(https://ceshiren.com/uploads/default/original/3X/2/3/23601168d0bebd721882a1220907d64822c8a11d.jpeg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-huh1ttRj-1648448025833)(https://ceshiren.com/uploads/default/original/3X/e/b/eb676155427c2987d39624ae51c8aa09e3ec5414.jpeg)]
答对了,请一定要记住xml和json的区别,不要混谈,那么你能编写一个测试来验证杂货(groceries)的类别是 否包含巧克力(Chocolate)和咖啡(Coffe)吗?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jy77PUTx-1648448027280)(https://ceshiren.com/uploads/default/original/3X/f/0/f0492217c9211cff2bd7f4f6e07650cfde3a5646.jpeg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Clag1yqs-1648448028657)(https://ceshiren.com/uploads/default/original/3X/5/3/532a78533aba238546f60e12e0371596479bad32.jpeg)]

这确实达到了我的要求,但代码明显有很多bug,如果我更改了category的位置,像下面这样,你的代码就不 适用了,我不难为你了,请王师傅来解答吧:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z9536Xng-1648448029936)(https://ceshiren.com/uploads/default/original/3X/1/0/103acbc8194b303b04c3a2366fbf825ee2612fb4.jpeg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Xyt5gne-1648448031136)(https://ceshiren.com/uploads/default/original/3X/6/1/61ea63c3492e55622ab6d393eb72547c078c2d36.jpeg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IwIyPFGJ-1648448032571)(https://ceshiren.com/uploads/default/original/3X/8/f/8fd0632c7b3c4bb3b31036d580ddfeee942acb5f.png)]

find的用法展示的很清楚,不需要我多讲,当然还有一点要注意,你可以这么使用find:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lwYuma3P-1648448034072)(https://ceshiren.com/uploads/default/original/3X/b/9/b9fe9a18b3f8a943ff329ab2ad926e8c84120f40.png)]
**是个特殊用法,它从xml文档根部开始,进行深度搜索,直到找到符合我们需要的项。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d3PsXbM3-1648448035873)(https://ceshiren.com/uploads/default/original/3X/5/2/52bc05833244af550b3e614fae46d2e03ffb023e.jpeg)]
使用findAll
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SOJl4bhL-1648448038136)(https://ceshiren.com/uploads/default/original/3X/d/5/d5c5ef624eacc70a8d979ae86faae045c1d9bd2c.jpeg)]
现在我手头只有20块钱,我只能买两本书,我更喜欢世纪的谚语和白鲸记,现在的任务是:挑选出格低于10的书籍,并且标题是“世纪的谚语(Sayings of the Century)”和“白鲸记(Moby Dick)”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o44FJwIV-1648448041964)(https://ceshiren.com/uploads/default/original/3X/b/d/bd74c87b6baf6b02726dda375b192569cb191812.jpeg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C3nTO02F-1648448043394)(https://ceshiren.com/uploads/default/original/3X/7/e/7e91ddbb086b439dcde1e2e978528627f3209d2b.jpeg)]

对的,这时候应该使用findAll,可以粗鲁的认为多个find的叠加。findAll可以筛选出一批符合要求的数据,而 find只能筛选出一个符合要求的数据,这就像是我们只能挑出一个人领取一等奖,但有很多人可以拿参与奖, 两个方法都有自己的用武之地。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AoqoCjlx-1648448045651)(https://ceshiren.com/uploads/default/original/3X/8/5/8586cafacb388a578b7f3d71fc1c746b453233ab.jpeg)]
下面的代码展示了findAll的用法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T4IjYn5z-1648448048251)(https://ceshiren.com/uploads/default/original/3X/2/f/2fee65c1240bd52dedb28c7fcfd5c93cbfb4c4ec.png)]

五、提取想要的值
有时候,我们并不想验证是否正确,我们只想取出这个值以进行下一步处理,比如我想取出next的链接:/title?page=2,这种情况怎么办呢?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i0WVbs1x-1648448050082)(https://ceshiren.com/uploads/default/original/3X/c/6/c6559f3080ae0ea15336d9607e2754ad8bde4253.png)]
下面的代码判断内容是不是JSON,并且标题是My Title的话,就返回href链接/title?page=2,这个值被存放在nextTitleLink中,以供我们以后使用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DLVJUPKa-1648448051766)(https://ceshiren.com/uploads/default/original/3X/8/b/8b92c71f4e540b8b37095a0adef8364e8823c567.png)]

当然,有两点需要注意:

  • 返回类型是Response,我们可以用Response.xxx来二次提取想要的值。
    • extract().后面是response()方法,不要写错了。
      六、更改默认值
      rest-assured有很多默认值,也正因为如此,需要我们的填的参数可以很少,也可以很多,就像画画一样,可以很精致,也可以很简洁。

      修改端口
      rest-assured发起请求时,默认使用的host为localhost,端口为8080,如果你想使用不同的端口,你可以这样做:

或者是这样

或者

修改baseURI和basePath
你也可能改变默认的baseURI、basePath

这就意味着,类似 get("/hello") 这样的一个请求,其实完整的请求为:http://myhost.com:80/resource/hello , 并且使用基础授权认证"username" and “password”。

其他
其他的默认值可以参考下面:

重置
你也可以重置为标准的baseURL(localhost)、basePath(空)、标准端口port(8080)、标准根路径root path(" "),默 认的认证scheme(none)以及URL编码(true),通过下面的方法重置:

七、specification
在不同的测试用例当中,我们可能会有重复的响应断言或者是请求参数,那么我们可以将重复的这一部分提取出来定义一个规范或者模板,这样的话在后续的测试用例当中就可以使用这个规范模板了。

为了达到这个效果,我们可以使用RequestSpecBuilder或 ResponseSpecBuilder来实现,它们之间的区别 是,前者用在请求中,后者则用在body中。

ResponseSpecification重用
例如,你想在多个测试用例中,都使用这样的断言:判断响应状态码是否为200,并且Json数组"x.y"的大小是否 等于2。你可以定义一个ResponseSpecBuilder来实现这个功能:

在这个例子中,需要重用的两个断言数据被定义在"responseSpec",并且与另外一个body断言合并,组成了这 个测试用例中全部的断言,那么这个测试用例需要全部断言都通过用例结果才会通过,一旦其中一个断言失 败,则测试用例的测试结果为失败。

RequestSpecification重用
同样,假如你想在多个测试用例中重用请求数据,可以通过下面的代码来实现:

这里的请求数据被合并在"requestSpec"中,所以这个请求包含了两个参数(“parameter1"和"parameter2”)以及一 个头部(“header1”)。

总结
本文就rest-assured的基本功能进行举例说明,其中例子大多来自于官方文档,同时我也建议大家多去阅读该开 发文档,其中有很多我们没有讲到的东西。 本文参考: rest-assured官网:https://github.com/rest-assured/rest-assured/wiki/Usage rest-assured介绍:https://www.ibm.com/developerworks/cn/java/j-lo-rest-assured/ get与post的区别:https://www.cnblogs.com/logsharing/p/8448446.htm
使用specification:https://www.cnblogs.com/lwjnicole/p/8277468.html

获取更多技术文章分享

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值