有正在从事web测试和APP测试工作或想从事此行业的测友们,欢迎与我联系,相互交流! 长期招聘不同级别测试工程师(WEB\APP\性能)有意者请与本人联系!

自动化测试工具Diffy

上一篇 / 下一篇  2020-03-15 10:15:25 / 个人分类:自动化测试

文章来源
  • 文章来源:【转载】

集成测试的挑战

随着软件系统的复杂性逐渐增加,微服务、面向服务的架构(Service-oriented architectures, SOA)等概念,越来越多的被应用到系统的设计当中,一同伴随的结果就是系统组件逐渐增加。

q"fjT1O8D.]+K&{5o0

对于测试活动而言,最底层的单元测试,主要测试目标是单一的功能模块。它能够确保每个组件自身业务逻辑的正确性,但是随着系统组件依赖的增加,对单一模块的单元测试难度和成本都会上升。同时,单元测试覆盖率的提升,只能确保系统各个组件的正确性,组件之间的集成测试仍然是必不可少的。51Testing软件测试网!c(i n9f5T ` k

传统集成测试的难点在于,对于每一个模块,都会有几个需要测试覆盖的分支,随着模块的增加,这些测试分支的组合,将会呈现几何级的增长(如图1所示)。

W{V*V'V"U6w] E*~@0

51Testing软件测试网)m'P"n$\ D~@ a-o

https://res.infoq.com/articles/diffy-twitter-open-source-automation-testing-tool/zh/resources/1024002.png

51Testing软件测试网:W6B q+vGb

图1:随着模块增加,测试复杂度指数级增加51Testing软件测试网$hC xSdn

Twitter公司发布的自动化测试工具Diffy,就是为了降低开发人员对这种复杂系统的测试成本。

:D {j5lSy K%U0

Diffy简介

Diffy是一个开源的自动化测试工具,它能够自动检测基于Apache Thrift或者基于HTTP的服务。使用Diffy,只需要进行简单的配置,之后不需要再编写测试代码。

!VD0H gUlV)f_0j!g6u0

Diffy主要基于稳定版本和它的副本的输出,对候选版本的输出进行比较,以检查候选版本是否正确。因此,Diffy首先假设候选版本应该和稳定版本有“相似”的输出。即不论候选版本和稳定版本系统模块是否相同,他们的最终输出应该是“相似”的。

4s}y%Qy s+R*K3@0

这里一直使用“相似”,而不是使用相同,这是因为相同请求可能会有一些Diffy不需要关心的干扰。比如:

yA@'K4x'i0
  • 响应中包含服务器生成的时间戳

    tD;jM s ?1j0
  • 代码中使用了随机数51Testing软件测试网6mt,Bu5~%y`

  • 系统服务间有条件竞争51Testing软件测试网 iH`_n

Diffy有自己的噪声清理方式,确保这些噪声不会影响最终的结果。51Testing软件测试网e n"`!q6N4o;RJ

Diffy工作原理

在测试过程中,Diffy充当一个代理,它能够将来源请求分发到不同版本的系统中去,通过对各个版本系统的输出进行对比,做出最终的结论。

4Ah7?a#w*E5uH0

Diffy需要三个版本的系统,以实现它的噪声过滤和对比功能,它们分别是:

m \a,g7`n0
  1. 候选版本:该版本是待测版本,相对于生产环境版本有着跟新的代码51Testing软件测试网j6uJFL5J

  2. 稳定版本:该版本通常是已经上线版本,或者是已知功能正常的版本

    l]/`$dTN3g N,A/L9H0
  3. 稳定版本副本:该版本是稳定版本的副本,和稳定版本运行相同的代码,主要用于排除噪声

    9l9o,V.N(R6m P0

整个运行流程为:

/CEk2` |:Yq/P0

4O ?$h5hFHo[B(sA0
https://res.infoq.com/articles/diffy-twitter-open-source-automation-testing-tool/zh/resources/1024003.png

51Testing软件测试网e y)cL$s7Z@

其中:51Testing软件测试网(L+M~0Z ]"},x

  • 原始区别为候选版本和稳定版本之间输出的区别,其中可能会包含上述的噪声51Testing软件测试网_G_D4X-\R^*S t

  • 噪声从稳定版本和其副本中获得,如果两个运行相同代码的系统输入相同输出却不同,则Diffy会认为这是开发人员不需要关心的噪声。

    ucd&iH8k0

基于上述两个区别集合,Diffy可以识别出候选版本和稳定版本真实的区别,这些区别很有可能就是一个缺陷。

-M [DNR#CSu4J0

当然,对于一个概率性出现随机值,仅仅一次请求的结论可能是不准确的。例如对于一个50%概率出现true或者false的布尔值,则有50%的概率会出现候选版本和稳定版本的不同,同时又会有50%的概率出现稳定版本和其副本出现不同(即将这个值认定为噪声),最终会有25%的概率认为这是一个缺陷。因为此时稳定版本和其副本值相同,候选版本和稳定版本值不同。因此,Diffy还会聚合原始区别和噪声,当发现二者出现的概率类似的时候,会认定之前识别出来的缺陷属于误报。51Testing软件测试网] y ]Q \9d ]+L

示例

最后,通过Diffy仓库中的示例,来大致了解下Diffy的运行方式和过程:51Testing软件测试网C9Y$z7{p

步骤1:克隆源码,并进行构建:51Testing软件测试网D ~ayns[

git clone https://github.com/twitter/diffy.git
cd diffy
./sbt assembly

国内如果下载速度很慢,可以修改下sbt的镜像,使用国内的镜像:51Testing软件测试网4@L z&LqO3\]lZ

#cat ~/.sbt/repositories
[repositories]
local
osc: http://maven.oschina.net/content/groups/public/
oschina-ivy:http://maven.oschina.net/content/groups/public/,
 [organization]/[module]/(scala_[scalaVersion]/)(sbt_[sbtVersion]/)[revision]/
[type]s/[artifact](-[classifier]).[ext]
sonatype-oss-releases
maven-central
sonatype-oss-snapshots

步骤2:启动候选服务。这里直接使用example.sh,因此对应的候选服务地址为:http-candidate.herokuapp.com:80

#L'F*}C;E Z?;c0

步骤3:启动基准服务(稳定版本)。这里直接使用example.sh,因此对应的候选服务地址为:http-primary.herokuapp.com:80

9[ l1[m*d-_"M0

步骤4:启动稳定版本副本。这里对应的是:http-secondary.herokuapp.com:8051Testing软件测试网P%A1_ n-O2^Y

步骤5:使用以下命令运行Diffy(example.sh):51Testing软件测试网,?#r"_"y$h

java -jar diffy-server.jar \
-candidate='http-candidate.herokuapp.com:80' \
-master.primary='http-primary.herokuapp.com:80' \
-master.secondary='http-secondary.herokuapp.com:80' \
-service.protocol='http' \
-serviceName='My Service' \
-proxy.port=:8880 \
-admin.port=:8881 \
-http.port=:8888 \
-rootUrl='localhost:8888'

该命令指定了Diffy需要的三个版本对应的访问地址,同时在8880端口开启代理,8888端口开启了结果访问服务。现在可以通过访问8880端口,Diffy会将请求同时分发到三个版本的http服务上,然后记录这三个http服务的返回值。通过访问8888端口,就可以看见对这三个返回内容的对比结果。命令执行输出如下:

nb^bI:_ la0
coolex scala-2.11 # java -jar diffy-server.jar \
> -candidate='http-candidate.herokuapp.com:80' \
> -master.primary='http-primary.herokuapp.com:80' \
> -master.secondary='http-secondary.herokuapp.com:80' \
> -service.protocol='http' \
> -serviceName='My Service' \
> -proxy.port=:8880 \
> -admin.port=:8881 \
> -http.port=:8888 \
> -rootUrl='localhost:8888'
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
I 0908 13:09:41.130 THREAD1: HttpMuxer[/admin/metrics.json]
 = com.twitter.finagle.stats.MetricsExporter()
I 0908 13:09:41.189 THREAD1: HttpMuxer[/admin/per_host_metrics.json]
 = com.twitter.finagle.stats.HostMetricsExporter()
I 0908 13:09:41.393 THREAD1: /admin 
 => com.twitter.server.handler.SummaryHandler
I 0908 13:09:41.394 THREAD1: /admin/server_info 
 => com.twitter.finagle.Filter$$anon$2
I 0908 13:09:41.394 THREAD1: /admin/contention 
 => com.twitter.finagle.Filter$$anon$2
I 0908 13:09:41.394 THREAD1: /admin/threads => com.twitter.server.handler.ThreadsHandler
I 0908 13:09:41.394 THREAD1: /admin/threads.json 
 => com.twitter.server.handler.ThreadsHandler
I 0908 13:09:41.394 THREAD1: /admin/announcer 
 => com.twitter.finagle.Filter$$anon$2
I 0908 13:09:41.395 THREAD1: /admin/dtab 
 => com.twitter.finagle.Filter$$anon$2
I 0908 13:09:41.395 THREAD1: /admin/pprof/heap 
 => com.twitter.server.handler.HeapResourceHandler
I 0908 13:09:41.395 THREAD1: /admin/pprof/profile 
 => com.twitter.server.handler.ProfileResourceHandler
I 0908 13:09:41.395 THREAD1: /admin/pprof/contention 
 => com.twitter.server.handler.ProfileResourceHandler
I 0908 13:09:41.395 THREAD1: /admin/ping 
 => com.twitter.server.handler.ReplyHandler
I 0908 13:09:41.396 THREAD1: /admin/shutdown 
 => com.twitter.server.handler.ShutdownHandler
I 0908 13:09:41.396 THREAD1: /admin/tracing 
 => com.twitter.server.handler.TracingHandler
I 0908 13:09:41.396 THREAD1: /admin/events
 => com.twitter.server.handler.EventsHandler
I 0908 13:09:41.396 THREAD1: /admin/logging
 => com.twitter.server.handler.LoggingHandler
I 0908 13:09:41.397 THREAD1: /admin/metrics
 => com.twitter.server.handler.MetricQueryHandler
I 0908 13:09:41.397 THREAD1: /admin/clients/
 => com.twitter.server.handler.ClientRegistryHandler
I 0908 13:09:41.397 THREAD1: /admin/servers/
 => com.twitter.server.handler.ServerRegistryHandler
I 0908 13:09:41.397 THREAD1: /admin/files/
 => com.twitter.server.handler.ResourceHandler
I 0908 13:09:41.397 THREAD1: /admin/registry.json
 => com.twitter.server.handler.RegistryHandler
I 0908 13:09:41.403 THREAD1: Serving admin http on 0.0.0.0/0.0.0.0:8881
I 0908 13:09:41.478 THREAD1: Finagle version 6.28.0
 (rev=de123b8f9d074c4e345ebd67e1a0e870bb921544) built at 20150827-162434
I 0908 13:09:43.010 THREAD1: networkaddress.cache.ttl
 is not set, DNS cache refresh turned off
I 0908 13:09:43.507 THREAD1: Tracer:
 com.twitter.finagle.zipkin.thrift.SamplingTracer
I 0908 13:09:43.810 THREAD1: zipkin-tracer
 resolved to Addr.Bound, current size=1
I 0908 13:09:43.811 THREAD1: candidate resolved to Addr.Bound, current size=1
I 0908 13:09:43.811 THREAD1: primary resolved to Addr.Bound, current size=1
I 0908 13:09:43.811 THREAD1: secondary resolved to Addr.Bound, current size=1
I 0908 13:09:43.885 THREAD1: Scheduling com.twitter.diffy.workflow.
FunctionalReport at 2015-09-08 13:09:43 +0000

步骤6:发送一些请求,让Diffy来记录和分析:

mz \}8d4f0
curl localhost:8880/json
curl localhost:8880

步骤7:通过localhost:8888查看结果:
可以看见刚才访问的两个地址都已经被记录,同时由于第二个地址增加了时间戳,所以原始对比结果认为他们是不相同的。

@r bo#j*l&`q2z0

],fm0a.|e Rb0
https://res.infoq.com/articles/diffy-twitter-open-source-automation-testing-tool/zh/resources/1024004.png

:oSH,WL0

点击对比失败的地方,可以展示出两次对比不同之处:51Testing软件测试网l)?DGdfx5P

\6j VPa0
https://res.infoq.com/articles/diffy-twitter-open-source-automation-testing-tool/zh/resources/1024005.png

51Testing软件测试网+W_*mRG5^#?

可以看见,该请求两个版本的不同是由时间戳导致的。如果选择“排除噪声”,那么最终结论会变成相同。51Testing软件测试网2b#vvi9G,m

微软雅黑,="" sans-serif="" !important;="" -webkit-font-smoothing:="" antialiased;="" margin:="" 0px;="" padding:="" text-decoration:="" none;="" color:="" rgb(66,="" 133,="" 244);="" max-width:="" 100%;="" font-size:="" 16px;="" word-break:="" break-all;="" border:="" outline:=""

TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar