Selenium 必了解—如何测试REST API

news2024/11/18 1:24:34

目录

前言:

Web UI测试存在的问题:

REST API测试:

依赖包

程序示例:

1-获取联系人

2-GET Request:

3-POST Request:

4- 编辑请求

5- 删除请求


前言:

Selenium WebDriver 可以用于测试 Web 应用的前端界面和功能,但是对于 Web 应用的后台接口,如 REST API,Selenium 无法直接进行测试。不过,Selenium WebDriver 也提供了相应的方法来发送 HTTP 请求和处理响应,从而进行 REST API 测试。

如果你只需要测试api,那么建议浏览这篇文章:Jmeter如何测试REST API /微服务

Web UI测试存在的问题:

  • 慢(这是因为你的浏览器首先向服务器发送一个请求以获取某些信息,一旦获得所需数据,可能需要一些时间来处理数据,并通过下载的图片和应用样式使其显示在表格中/或者以适配的格式显示,所以你必须等待整个过程完成之后才能与应用程序进行交互);

  • 费时;

  • 对于测试不同的浏览器,可能必须重复相同的测试集;

  • 浏览器是独立于selenium脚本的进程。所以同步总是一个问题;

  • UI测试有很多依赖项,比如Browsers/Versions/Grid/Driver等等。

因此,这并不意味着我们应该总是做API级别的测试并发布产品; 我们应该尝试尽可能的进行API级别测试。 我们可以只为UI测试提供较小覆盖率。

REST API测试:

与Selenium WebDriver UI测试相比,REST API测试并不难,大多数api都是GET / POST / PUT / PATCH / DELETE请求之一:

  • GET 用于从后端获取信息以显示在UI中;

  • POST 用于在后端添加新信息;

  • PUT用于更新/替换任何现有信息;

  • PATCH 用于部分更新;

  • DELETE 用于从后端删除信息。

假设你使用testNG/Junit这样的框架,并使用Selenium进行应用程序UI测试 --而现在希望在相同的框架中也包含API测试 --可能需要快速设置数据或断言等,那么接下来就让我们看看如何在本文中完成。

依赖包

在maven文件中添加如下依赖:

<dependency>
    <groupId>com.mashape.unirest</groupId>
    <artifactId>unirest-java</artifactId>
    <version>1.4.9</version>
</dependency>
<dependency>
    <groupId>org.jtwig</groupId>
    <artifactId>jtwig-core</artifactId>
    <version>5.87.0.RELEASE</version>
</dependency>
  • Unirest是一个简单的轻量级流畅式HTTP请求库

  • JTwig是一个非常简单的模板引擎

程序示例:

使用Rest API列出所有可用的联系人,添加/编辑/删除联系人;它还使用Angular构建了比较友好的UI界面;你可以克隆并部署到你的本地运行。

一旦上述应用程序部署成功并启动,就可以使用API GET请求获取联系人列表,显示在UI界面上。

1-获取联系人

当您访问应用程序的主页时,它会列出所有可用的联系人。

如果监视Chrome-network中的Network,可以看到发送了一些API GET请求来获取联系人列表。

  • 如果你不确定在哪里检查,在Chrome页面按下F12,Chrome开发工具将会出现。

  • 检查API url的header部分

本地部署的地址
https://localhost:4200/api/contacts?q=
而本文例子使用如下Live Demo链接:
https://restool-sample-app.herokuapp.com/

你可以看到以下格式的JSON Response:
[
    {
        "id": "xiyydaS9CLqV",
        "thumbnail": "https://www.hbo.com……",
        "name": "Tyrion Lannister",
        "realName": "Peter Dinklage",
        "location": "Winterfell",
        "isAlive": true
    }
]

你可以通过应用程序添加联系人,修改联系人,删除联系人等

2-GET Request:

一旦应用程序启动,可以使用API GET请求获取联系人列表,以便在应用程序中显示数据。可以使用Unirest发出上面说到的GET请求,如下所示:

String searchQueryApi = "https://restool-sample-app.herokuapp.com/api/character?search=";
JsonNode body = Unirest.get(searchQueryApi)
                        .asJson()
                        .getBody();
System.out.println(body);         // 打印完整的json响应信息
System.out.println(body.getArray().length());  // 打印item编号

其请求如下图所示:

也可以在测试框架中进行简单的断言。

例如下面的示例代码确认API响应中的所有数据是否都显示在UI中:

driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://restool-sample-app.herokuapp.com/");
List<WebElement> contacts = driver.findElements(By.cssSelector("tbody > tr"));
Assert.assertEquals(contacts.size(), body.getArray().length(), "The contacts not equals with Body length");

3-POST Request:

每当我们试图添加新的联系人时,就会发送POST请求并携带如下格式JSON作为Body:

{
"thumbnail": "https://www.hbo.com……",
"name": "Test Name",
"realName": "Test Real Name",
"location": "Test location",
"isAlive": false
}

如果你的目标是自己发送请求,那么您可能不希望在JSON文件中硬编码任何值。这就是我们使用JTwig模板引擎的地方。

首先,我在模板下面创建。

{
  "thumbnail": "{{URL}}",
  "name": "{{name}}",
  "realName": "{{realName}}",
  "location": "{{location}}",
  "isAlive": true
}

我将上面的JSON保存在一个名为“contact.json”的文件中。现在我可以读取模板并在运行时替换这些值,如下所示:

JtwigTemplate template = JtwigTemplate.classpathTemplate("contact.json");
JtwigModel model = JtwigModel.newModel()
.with("URL", "http://n.sinaimg.cn/ent/transform/20160502/n4qY-fxrunru8640821.png")
.with("name", "TestName")
.with("realName", "TestRailName")
.with("location", "Winterfell");
template.render(model);//用上述的值替换模板表达式中的值

接下来可以发送POST请求创建新的联系人了(发送POST请求之后,在这里还可以通过UI界面进行检查联系人是否成功显示在UI界面,此处不做详细Demo)

String postApi = "https://restool-sample-app.herokuapp.com/api/character";
Unirest.post(postApi)
.header("accept", "application/json")
.header("Content-Type", "application/json")
.body(template.render(model))
.asJson();

使用上面这个方法,我们可以在应用程序中快速的添加联系人。

假设页面最多只能显示50个联系人,你需要点击翻页按钮查看更多联系人,但是在本地/QA环境中,当你启动一个新的应用程序时,可能没有足够的联系人来测试该显示功能;

如果页面对象公开了一个方法来添加联系人,则需要调用50多次,通过UI界面添加联系人可能非常耗时,由于同步问题,它可能随时会失败,并且还需要处理:比如当用例重试失败或者退出导致测试失败等情况。

但是使用Api,您可以轻松地修改页面对象,如下所示,现在你可以用它来建立数据等等。它应该比UI方法快得多,而且更不容易出错。

class ContactsPage{
    //all find bys
    //methods for interacting with web elements
    public void addContacts(int numberOfContacts){
        String postApi = "https://restool-sample-app.herokuapp.com/api/character";
        for(int i = 0; i<numberOfContacts; i++){
            Unirest.post(postApi)
                    .header("accept", "application/json")
                    .header("Content-Type", "application/json")
                    .body(template.render(model)) 
                    .asJson();
        }
    }
}

Unirest可以很容易地在page对象中使用,如上面的示例所示。

4- 编辑请求

要编辑联系人,我们需要发送如下所示的PUT请求。

String editApi = "https://restool-sample-app.herokuapp.com/api/character/{contact_id}";
JtwigModel model = JtwigModel.newModel()
.with("name", "Snow")
        .with("location", "Winterfell");
Unirest.put(editApi)
        .routeParam("contact_id", "T2S6kHv4cS1A")
        .header("accept", "application/json")
        .header("Content-Type", "application/json")
        .body(template.render(model))
        .asJson();

更新了Name:

5- 删除请求

删除就这就更简单了。

String editApi = "https://restool-sample-app.herokuapp.com/api/character/{contact_id}";
Unirest.delete(editApi)
        .routeParam("contact_id", "T2S6kHv4cS1A")
        .asJson();

我们可以使用这个API来清理测试是新建的数据,这样就保持测试之后的数据清洁,不会过多的新建无用甚至垃圾数据。

public class ContactsPageTest{  
    private String editApi = "https://localhost:4200/api/contacts/{contact_id}";
    @Test
    public void someUItest1(){
        //
    }
    @Test
    public void someUItest2(){
        //
    }
    @AfterTest
    public void teardown(){
        for(String contactid: listOfContacts){
            Unirest.delete(editApi)
            .routeParam("contact_id", contactid)
            .asJson();
        }
    }
}

总结:

通过在现有的测试框架/页面对象中使用Unirest,可以和REST api进行交互,还可以使用这些api在应用程序中进行快速设置数据,以便进行快速功能验证;

正如上面的示例中所提到的,只要可能,就尽量使用api进行测试。

完整Demo代码(请配合上述介绍使用):

package com.morningstar.automation.pdf.Download;
import org.jtwig.JtwigModel;
import org.jtwig.JtwigTemplate;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
public class testRestAPI {
WebDriver driver;
@Test
public void testOne() throws Exception {
//GET Request:
String searchQueryApi = "https://restool-sample-app.herokuapp.com/api/character?search=";
JsonNode body = Unirest.get(searchQueryApi).asJson().getBody();
System.out.println(body); // 打印完整的json响应信息
System.out.println(body.getArray().length()); // 打印item编号
//验证联系人数量与UI界面显示的数量
//driver = new ChromeDriver();
//driver.manage().window().maximize();
//driver.get("https://restool-sample-app.herokuapp.com/");
//List<WebElement> contacts = driver.findElements(By.cssSelector("tbody > tr"));
//Assert.assertEquals(contacts.size(), body.getArray().length(), "The contacts not equals with Body length");
//添加一个新的联系人
JtwigTemplate template = JtwigTemplate.classpathTemplate("contact.json");
//JtwigModel model = JtwigModel.newModel()
//.with("URL", "http://n.sinaimg.cn/ent/transform/20160502/n4qY-fxrunru8640821.png")
//.with("name", "TestName")
//        .with("realName", "TestRailName")
//        .with("location", "Winterfell");
//template.render(model); //gives the json in the above format by replacing the template expressions
//GET Request:
//String postApi = "https://restool-sample-app.herokuapp.com/api/character";
//Unirest.post(postApi)
//        .header("accept", "application/json")
//        .header("Content-Type", "application/json")
//        .body(template.render(model))
//        .asJson();
//编辑请求, PUT
String editApi = "https://restool-sample-app.herokuapp.com/api/character/{contact_id}";
JtwigModel model = JtwigModel.newModel()
.with("name", "Snow")
        .with("location", "Winterfell");
Unirest.put(editApi)
        .routeParam("contact_id", "T2S6kHv4cS1A")
        .header("accept", "application/json")
        .header("Content-Type", "application/json")
        .body(template.render(model))
        .asJson();
//删除请求 Delete
//String editApi = "https://restool-sample-app.herokuapp.com/api/character/{contact_id}";
//Unirest.delete(editApi)
//        .routeParam("contact_id", "T2S6kHv4cS1A")
//        .asJson();
}
@AfterClass
public void tearDown() {
// driver.quit();
}
}

contact.json文件就放置于根目录下斜体样式:

{
  "thumbnail": "http://n.sinaimg.cn/ent/transform/20160502/n4qY-fxrunru8640821.png",
  "name": "{{name}}",
  "realName": "{{realName}}",
  "location": "{{location}}",
  "isAlive": true
}

 作为一位过来人也是希望大家少走一些弯路,在这里我给大家分享一些自动化测试前进之路的必须品,希望能对你带来帮助。(WEB自动化测试、app自动化测试、接口自动化测试、持续集成、自动化测试开发、大厂面试真题、简历模板等等),相信能使你更好的进步!

留【自动化测试】即可【自动化测试交流】:574737577(备注ccc)icon-default.png?t=N4P3http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=eSv73sPKaVXpq9JeRq1Kboh1D-w19xXu&authKey=Qs1Sduo9tp2wfkOYvRyyFCoblyT7fBhH4PPisEb1G63n1UckS6wQU50e9ar1LAOz&noverify=0&group_code=574737577

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/634202.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习框架(Pytorch)学习第1步:包管理系统Anaconda的安装

PyTorch是一种开源的深度学习框架&#xff0c;以出色的灵活性和易用性著称。 并且与机器学习开发者和数据科学家喜欢的Python高级编程语言兼容。 什么是PyTorch PyTorch是一种构建深度模型功能完备的框架。通常用于图像识别和语言处理等。 使用Python编写&#xff0c;学习和…

UI自动化测试之Airtest让你的测试工作如虎添翼!

本文我们讲解下Airtest的使用&#xff0c;主要学习目标有以下几点&#xff1a; &#xff08;1&#xff09;认识Airtest &#xff08;2&#xff09;了解Airtest能做什么 &#xff08;3&#xff09;Airtest安装及环境搭建 &#xff08;4&#xff09;掌握Airtest图形化api使用 &am…

【MySQL】记录的基本操作

文章目录 插入数据为表中所有字段插入数据为表中指定字段插入数据同时插入多条数据 更新数据删除数据TRUNCATE和DETELE的区别 查询数据 插入数据 为表中所有字段插入数据 基本语法 INSERT INTO 表名&#xff08;字段名1,字段名2,…) VALUES (值 1,值 2,…); 示例 # 准备一张表…

算法模板(4):动态规划(4) 做题积累(2)

动态规划 9. 单调队列优化DP 1. 1088. 旅行问题 John 打算驾驶一辆汽车周游一个环形公路。 公路上总共有 n 个车站&#xff0c;每站都有若干升汽油&#xff08;有的站可能油量为零&#xff09;&#xff0c;每升油可以让汽车行驶一千米。 John 必须从某个车站出发&#xff…

接口自动化-让你了解数据库相关知识

目录 python接口自动化实战 数据库 写一个对数据库操作的类 python接口自动化实战 目标 学习数据库相关&#xff0c;用例增加对数据库校验 利用数据库完成对数据查询 如何校验数据库数据&#xff0c;怎样添加校验让程序自己校验&#xff08;充值、提现、投资接口对金额的…

VMware ESXi 7.0 Update 3m - 领先的裸机 Hypervisor (All OEM Customized Installer CDs)

VMware ESXi 7.0 Update 3m - 领先的裸机 Hypervisor (All OEM Customized Installer CDs) ESXi 7.0 U3m Standard (标准版) ESXi 7.0 U3m Dell (戴尔) 定制版 OEM Custom Installer CD ESXi 7.0 U3m HPE (慧与) 定制版 OEM Custom Installer CD ESXi 7.0 U3m Lenovo (联想) 定…

分布式项目17 订单order,用dubbo来实现

说明&#xff1a;只要当一个订单生成时&#xff0c;处理订单的信息之外&#xff0c;还有订单中包含的订单商品数据以及订单物流信息&#xff0c;而订单的信息封装在“tb_order”表中&#xff0c;关于tb_order表结构如下图所示&#xff1a; 订单商品数据封装在“tb_order_item”…

STM32使用PWM实现led亮度变化

原理及代码讲解 1.序言2.频率3.占空比4.控制led亮度变化原理5.代码实例5.1 初始化引脚5.2 配置定时器15.3配置输出PWM 6.结语 1.序言 这里我以stm32F103c8te为例&#xff0c;讲解一下pwm如何输出&#xff0c; pwm又是如何控制led灯的亮度变化&#xff0c;以及具体代码又是 如何…

53、基于51单片机蓄电池充电器过充过放保护LCD液晶屏显示系统设计(程序+原理图+PCB源文件+参考论文+参考PPT+元器件清单等)

方案选择 单片机的选择 方案一&#xff1a;AT89C52是美国ATMEL公司生产的低电压&#xff0c;高性能CMOS型8位单片机&#xff0c;器件采用ATMEL公司的高密度、非易失性存储技术生产&#xff0c;兼容标准MCS-51指令系统&#xff0c;片内置通用8位中央处理器(CPU)和Flash存储单元&…

STL之Stack与queue的模拟实现与duque的底层结构(3千字长文详解)

STL之Stack与queue的模拟实现与duque的底层结构 文章目录 STL之Stack与queue的模拟实现与duque的底层结构设计模式的概念适配器模式 stack的实现queue的实现双端队列——dequedeque的底层结构 设计模式的概念 设计模式像是古代的兵法&#xff0c;是以前的人总结出来的一些在特定…

TClientDataSet 模拟 EXCEL表

日常处理数据时&#xff0c;经常需要&#xff0c;从EXCEL表格中&#xff0c;批量导入数据&#xff0c;通过 XLSReadWriteII编程&#xff0c;会很快导入。 但是&#xff0c;客户提供的EXCEL表的字段&#xff0c;数据格式&#xff0c;字段的排序&#xff0c;有很大的区别。因此&a…

PostmanScript脚本功能使用详解!

目录 前言&#xff1a; 一、Pre-requestScript 二、TestScript 三、随机参数&#xff1a; 前言&#xff1a; Postman 是一个强大的 API 工具&#xff0c;可以用于构建、测试和文档化 Web API。Postman 还提供了一个名为 PostmanScript 的功能&#xff0c;它可以用于自动化…

【5】Midjourney Prompt

Prompt 是Midjourney Bot解释以生成图像的简短文本短语。 Midjourney Bot将Prompt 中的单词和短语分解成为Token的较小部分&#xff0c;可以将其与训练数据进行比较&#xff0c;然后用于生成图像。 精心制作的 Prompt可以帮助生成独特且令人兴奋的图像。 Structure 结构 基本…

Spring Boot + Vue3前后端分离实战wiki知识库系统<八>--分类管理功能开发二

接着上一次Spring Boot Vue3 前后端分离 实战 wiki 知识库系统&#xff1c;七&#xff1e;--分类管理功能开发的分类功能继续完善。 分类编辑功能优化&#xff1a; 概述&#xff1a; 现在分类编辑时的界面长这样&#xff1a; 很明显目前的父分类的展现形式不太人性&#xf…

【JVM】JVM常用指令

文章目录 1、jps2、jinfo3、jstat4、jstack5、jmap6、jhat 1、jps jps&#xff08;java process status tool&#xff09;&#xff0c; 用于查看java进程及相关信息&#xff0c;如果你想找到一个java进程的pid&#xff0c;可以使用jps命令代替linux的ps命令。 命令格式&#…

ansible常见模块应用简介

目录 command, shell, raw模块file 模块copy 模块fetch 模块lineinfile模块unarchive解包解压缩 模块user 模块yum_repository 仓库管理yum/dnf模块Service/systemd模块firewalld 模块nmcli 模块get_url 模块mount模块 注意&#xff1a;该文档需要有 Linux 基础的看 command, s…

【架构基础】高内聚低耦合

软件设计目标&#xff1a;实现需求、易于重用、易于理解、没有冗余。 Dont reinvent the wheel, just realign it. --Anthony J D’ Angelo 高内聚低耦合&#xff0c;是软件工程中判断软件设计好坏的标准。主要评判模块或类的内聚性是否高&#xff0c;耦合度是否低。目的是使…

【图像处理】基于双目视觉的物体体积测量算法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

TCP的安全和效率机制

目录 0.TCP协议格式 ​编辑 一.确认应答(安全机制) 二.超时重传(安全机制) 1.SYN丢包 2.ACK丢包 三.连接管理(安全机制) 1.三次握手建立连接 ​编辑 2.四次挥手断开连接 3.建立和断开连接 四.滑动窗口(效率机制) 五.流量控制(效率机制) 六.拥塞控制(安全机制) 七…

算法扩展第一次:收集雪花 【hash表,双指针,stl中的map】

算法详解 这道题需要新学的知识一个是双指针&#xff0c;一个是c库中的unordered_map容器 双指针 双指针原先我写过很多这方面的题&#xff0c;但是这道题我一开始是低估了它的难度&#xff0c;而且压根没有想到要用双指针&#xff0c;属于是长见识了&#xff0c;这道题的双…