Selenium [Web 自动化] Web 自动化的同时进行接口校验

bauul · February 27, 2019 · Last by bauul replied at March 05, 2019 · 2607 hits

缘由

当前做的项目中很多页面存在一定的共性,所以思考了一下Web自动化的可行性,
目前基本上做了一小块信息抽取的功能,目的是

  1. 给到产品验收
  2. 做版本对比
  3. 后续可以做PRD对比,即拿文档中的要求直接与开发出来的结果进行对比

在做UI自动化的过程中,脑子里迸出来一个想法,是不是可以同时对接口数据进行校验?
网上一搜,丫的还真有,还在6年多前就有了解决方案
于是有了本文

技术基础

  1. selenium
  2. xpath
  3. testNG
  4. browsermob-proxy
  5. java
  6. maven

Pom

<properties>
<aspectj.version>1.8.10</aspectj.version>
<allure.version>1.5.4</allure.version>
<testng.version>6.11</testng.version>
<okhttp3.version>3.10.0</okhttp3.version>
<lombok.version>1.16.18</lombok.version>
<slf4j.version>1.7.25</slf4j.version>
<logback.version>1.2.3</logback.version>
<assertj.version>3.8.0</assertj.version>
<fastjson.version>1.2.47</fastjson.version>
<mysql.connector.version>8.0.11</mysql.connector.version>
<jedis.version>2.9.0</jedis.version>
<java.version>1.8</java.version>
</properties>

<dependencies>

<dependency>
<groupId>net.lightbody.bmp</groupId>
<artifactId>browsermob-core</artifactId>
<version>2.1.5</version>
</dependency>

<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>3.0.6</version>
</dependency>

<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
</dependency>

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>

<dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.0.7</version>
</dependency>

<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
</dependency>

<dependency>
<groupId>ru.yandex.qatools.allure</groupId>
<artifactId>allure-testng-adaptor</artifactId>
<version>${allure.version}</version>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp3.version}</version>
</dependency>

<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>${okhttp3.version}</version>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>

</dependencies>

主要思路

import com.wz.pages.Login;
import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.client.ClientUtil;
import net.lightbody.bmp.core.har.Har;
import net.lightbody.bmp.proxy.CaptureType;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.Test;

import java.io.File;
import java.io.IOException;

public class Demo {

@Test
public void t1() throws IOException {
// System.setProperty ("jsse.enableSNIExtension", "false");
BrowserMobProxy browserMobProxy = new BrowserMobProxyServer();
browserMobProxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);
browserMobProxy.start();

Proxy seleniumProxy = ClientUtil.createSeleniumProxy(browserMobProxy);

System.setProperty("webdriver.chrome.driver", Demo.class.getResource("/chromedriver").getPath());
ChromeOptions chromeOptions = new ChromeOptions();

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);
capabilities.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS, false);
chromeOptions.merge(capabilities);

WebDriver driver = new ChromeDriver(chromeOptions);

browserMobProxy.newHar("https://wzzzzzzzzzzzz.com");
Login.loginAccount(driver, "https://wzzzzzzzzzzzz","01999888777", "Clark@01999888777");

Har har = browserMobProxy.getHar();
har.writeTo(new File("demo.har"));

driver.close();

}
}

还是直接上代码吧,可以看出来,

  1. 配置代理
  2. 设置需要抓取请求体,响应体 ==> 这里可以不设置,那么抓出来har包里面就没有请求体,响应体信息
  3. 配置chrome参数,启动chrome
  4. 进行web测试
  5. web测试结束后,保存抓包数据

结果

{
"pageref": "https://wzzzzzzzzzzzz.com",
"startedDateTime": "2019-02-27T13:25:31.188Z",
"request": {
"method": "POST",
"url": "https://wzzzzzzzzzzzz.com/tenant/v1/api/user/account/login",
"httpVersion": "HTTP/1.1",
"cookies": [

],
"headers": [

],
"queryString": [

],
"postData": {
"mimeType": "application/x-www-form-urlencoded",
"params": [
{
"name": "account",
"value": "01999888777",
"comment": ""
},
{
"name": "password",
"value": "Clark@01999888777",
"comment": ""
}
],
"comment": ""
},
"headersSize": 505,
"bodySize": 48,
"comment": ""
},
"response": {
"status": 0,
"statusText": "",
"httpVersion": "unknown",
"cookies": [

],
"headers": [

],
"content": {
"size": 0,
"mimeType": "",
"comment": ""
},
"redirectURL": "",
"headersSize": -1,
"bodySize": -1,
"comment": "",
"_error": "No response received"
},
"cache": {

},
"timings": {
"comment": "",
"dns": 0,
"connect": 84,
"send": 0,
"wait": 0,
"receive": 0,
"blocked": 30,
"ssl": 45
},
"serverIPAddress": "139.198.176.127",
"comment": "",
"time": 115
}

有了har包,再对其进行解析,就可以做响应校验,更多的数据校验了

问题

  1. 有看到BrowserMobProxy可以设置过滤器,但是暂时没实践出来,也没有搜索到相关的例子, github官网上的不像是过滤器,是拦截器,而我想要XHR,或是按url地址进行正则过滤 ==> 暂时的解决方法:可以对Har的内容进行过滤
  2. 之前还有一个想法是通过selenium 调用javascript方法或chrome的api来获取XHR请求数据,没试成功
  3. 看到别人写好的Har代码,再看看自己的,我日,咋没早点发现呢,花了自己好几天时间,直接引他的包就完了, 当然在这过程中也踩了坑学习到了如何对枚举类进行反序列化
  4. 当前的测试环境是HTTPS协议的,在日志中报SSL的错误,虽然不影响测试,但是就是感觉别扭 io.netty.handler.codec.DecoderException: javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name

参考

  1. https://github.com/lightbody/browsermob-proxy
  2. https://sites.google.com/a/chromium.org/chromedriver/system/app/pages/search?scope=search-site&q=Request
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 12 条回复 时间 点赞

我们这边web后台自动化也是要考虑这块,我希望最好还是实时的检验,这样更好的确保当前请求响应的数据跟页面展示的数据是否一致,确保ui这层没有调错数据

CC 回复

嗯嗯,可以搞的,我也是基于okhttp封装的请求😁

我们SDK打点自动化方案,是专门做request和response校验的,只不过是移动端方案

simple 回复

我理解的话这个web和移动端应该差不多

之前用了 Browsermob ,不过后来放弃换 AnyProxy 了
Browsermob-proxy 验证埋点和下载功能

bauul #6 · March 01, 2019 作者
黑水 回复

嗯,看过你的帖子了,论坛中唯一的一篇,想要了解一下,为什么换AnyProxy的?
目前来看,拿到Har数据,是比较方便解析的,其中还有一些性能数据后续可以用起来

simple 回复

移动端有对应的代理方案吗?我这边相当需要

CC 回复

你看看这篇文章,是不是你想要的

bauul 回复

其实不是一定要anyproxy,只不过刚好在社区里看到阿里开源的这个代理很好用,我们的抓包都是https加密的,所以需要在抓包过程中自动解密request参数和response body,因此开源代理更灵活一些;拿Har数据我们也用到了,用了mitmproxy来抓的,做性能分析用

bauul 回复
  1. Browsermob,用自签名 HTTPS 证书的时候解析不了(没找到原因,也许我用的方法不对)
  2. AnyProxy 有 UI 界面,手工测试、调试的时候可以用同样的工具、代理规则、准备好的测试模板数据
  3. Browsermob 断点调试的时候,一个页面有 10 个请求,只想断其中一个请求,其余 9 个也会被断住,界面判断超时就几秒,这样享受不到断点的好处了。如果都要改代码重启,AnyProxy + 动态语言方便多了
  4. 接口都是 JSON 的,JavaScript 处理 JSON 相比 Java 方便超级多
  5. 接口都是 HTTP 的,JavaScript 处理 HTTP 相比 Java 方便超级多

代理还有这两个,不过写的挺舒服就没去尝试了
https://github.com/mitmproxy/mitmproxy/
https://github.com/snail007/goproxy

bauul #12 · March 05, 2019 作者
黑水 回复

感谢推荐👍
之前下过anyproxy,感觉不是太友好,可能我还没摸熟😜
browsermob就先踩个坑,暂时还没有那么多精力搞脚本,主要还在搞业务的功能测试

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up