Loading [MathJax]/jax/output/HTML-CSS/jax.js

AspectJ在测试中的应用

简介:

1. 介绍
1.1面向切面的编程
面向切面的编程(AOP,Aspect Oriented Programming),主要实现的目的是针对业务处理过程中的切面进行提取,它所面对是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。
软件设计的一个重要原则,就是要清晰分离各种关注点,然后分而治之,各个击破,最后形成同一的解决方案。然而在目前的技术框架下,通常系统级关注点在逻辑上相互独立,在实现上趋向于和若干核心模块交织。就如下图所示,业务逻辑和安全,日志,一致性交织在了一块,源程序变成一些为不同目的而编写在一起的混乱物。
 



AOP专为关注点而生,其目标使设计和代码更加模块化、更具结构性,使关注点局部化而不是分散在整个系统中,同时和系统其它部分保持良好定义的接口,从而真正达到不仅在设计上分离,实现上也分离的目的。AOP被认为是后面向对象时代的一种新的重要的程序设计技术。
 




1.2 AspectJ
AspectJ是一个面向切面编程的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
编织(weave),是将核心关注点和横切关注点有机融合的过程。其中,核心关关注点表示业务功能和业务逻辑,横切关注点表示业务功能的功能约束。AspectJ目前支持以下三种编织的方式:
※ 编译时编织(compile-time weaving):在编译的过程中进行编织
※ 编译后编织(post-compile weaving):对已经编译好的字节码进行编织
※ 加载时编织(load-time weaving):在类被加载进JVM的时候进行编织,在加载时通过aop.xml对编织的对象进行控制

AspectJ中引入下列这些概念
连接点(Join Point):程序执行过程中明确定义的可以被识别的点或位置。
切入点(Pointcut):连接点的集合,通过连接点标识明确定义需要收集的连接点和有关参数值,它是联系方面和类的桥梁。比如:
pointcut callSetter( ): call (public void HelloWorld.set*(..))
其中:
pointcut说明声明的是一个切入点,命名 callSetter,后面的空括号表示该切入点不需要上下文信息。 
call表示该切入点捕获的是对指定方法的调用,指定的方法是在类HelloWorld中声明的公有的、返回值为空、以set开头、拥有任意参数的方法。
通知(Advice):在符合特定条件的情况下执行具体动作的代码的语言构造子称为通知,即声明在连接点被调用时应该执行的动作。依据切入点的语义,将通知分为以下三类:
※ Before advice:在连接点之前执行;
※ After advice :在连接点之后执行;
※ Around advice :代替原连接点处方法的执行。
方面(Aspect):一个方面是封装横切关注点的一个独立的标准单元,类似于面向对象编程中的类。其中包括通知和切入点的定义。

以下是一个简单的例子,例如有一个类HelloWorld, 
public class HelloWorld {
public void sayHello() {
System.out.println("Hello, world!");
}

public static void main(String[] argv) {
HelloWorld hw = new HelloWorld();
hw.sayHello();
}
}

现在想在sayHello方法被调用之前和之后多打印一行输出,可编写如下的代码
public aspect SayAspect {
pointcut say():call(void HelloWorld.sayHello());

before():say() {
System.out.println("before say hello....");
}
after():say() {
System.out.println("after say hello....");
}


也可以采用标记的方法编写
@Aspect
public class SayAspect {
@Pointcut(“execution(void HelloWorld.sayHello())”)
public void say() {}

@Before(“say()”)
public before(){
System.out.println("before say hello....");
}

@After(“say()”)
public after(){
System.out.println("after say hello....");
}


2. 在测试中的使用
2.1测试需求
在测试中测试人员需要构造各种各样的测试场景。但是在一些系统中,特别是在一个复杂的系统中,一些测试场景不能够容易地被创建,比如:
※ 随机性事件,比如需要测试条件A下,程序分别在条件B和条件C下的运行情况。但由于产生条件A在程序中是随机的,测试人员要么需要修改代码,要么只能重复地执行这个用例,直到程序产生条件A为止;
※ 异常,通常测试人员需要求助于不同的第三方的工具来模拟不同的异常,另外有时异常的触发不够直接,时机不好掌握;
※ 复杂的流程,一些bug在特定的交互时序下才会实现,而特定的时序从程序外部无法控制,这时测试人员只有改动程序的代码才能重现。

这里以HDFS中的写流程为例,讲讲在测试过程中遇到的一些问题。下图是一个典型的客户端写3副本的流程。
 




首先,在测试中需要构造异常在第一个DataNode触发,中间DataNode触发和最后一个DataNode触发的情况。但是,每次客户端构造pipeline中的3个DataNode的顺序是随机的。
其次,目前异常的触发是通过apihook来进行,apihook可以在写指定文件和接收发送来自指定端口的消息时产生异常。但是就如上图所示,create和stream时用的是同一个socket,但是apihook无法区分create和stream过程。
2.2使用AspectJ进行测试
对于测试而言,AspectJ为测试人员提供了一种注入代码的方法,从而可以在不改变原有代码的情况下,对指定方法的行为进行控制,更方便地构造出测试人员想要的场景。并且可以不依赖于其它的工具。
下面我们来看看如何使用AspectJ来解决2.1中提到的hdfs写流程问题,在这里采用加载时编织的方式。
1. 首先根据2.1中提到的问题,编写三个Asepct,然后编译并打成一个jar包,如inject.jar

OrderAspect.java 在Client从NameNode获取到DataNode时,对这些DataNode依据机器名进行重排序
public aspect OrderAspect {
pointcut order():call(* DFSClient.DFSOutputStream.locateFollowingBlock(..));

LocatedBlock around():order() {
LocatedBlock locateBlock = proceed();
/* DataNode的信息存在loacteBlock中,在此进行重排序 */
return locateBlock;
}
}

CreateAspect.java在创建pipeline的时候抛出IOException异常
public aspect CreateAspect {
pointcut pipeline():call(* DataXceiver.writeBlock(..));

before() throws IOException :pipeline() {
throw new IOException("by aspectj");
}
}

StreamAspect.java在传输数据的时候抛出IOException异常
public aspect StreamAspect {
pointcut write():call( * BlockReceiver.receivePacket());

after() throws IOException : write() {
throw new IOException("by aspectj");
}
}

2. 之后就可以通过更改对应结点的aop.xml的配置来控制要注入的代码。例如,现在想测试当中间的DataNode在传输数据的过程中抛出异常的情况,对应结点的aop.xml可以如下图配置。由于通过OrderAspect在建立pipeline之前对DataNode进行了排序,因此我们可以明确哪个DataNode处于pipeline中间的位置。配置好好重启集群,配置项就可以生效了。
 


3. 在hadoop中,我们可以采取类似的方法使用AsepctJ进行测试。
a) 平常我们可以把对应的测试中要注入的代码合到项目中,在编译整个项目时,这些注入的代码都被打包到一个jar包中,比如hadoop-2-inject.jar。
b) 在执行一个测试用例前,根据测试的需要配置aop.xml(使用加载时编织的方法)控制要注入的代码,并发送到相应的节点上,然后启动集群进行测试。

由于每个测试流程都是一样的,修改aop.xml,分发到对应结点上,启动集群,测试,所以也可以方便的自动化。
apihook是通过一种间接的方式触发我们需要的代码逻辑,而AspectJ提供了一种更直接、方便的方法控制代码逻辑。

3. 使用指南
这里以1.2中HelloWorld为例子,介绍如何使用AspectJ
首先从http://www.eclipse.org/aspectj/下载最新的jar包,并进行解包,并设置变量
ASPECT_LIB =”解包路径/lib”
3.1编译时编织
如果采用编译时编织的方法,则使用以下命令进行编译
java –classpath ASPECTLIB/aspectjrt.jar:ASPECT_LIB/aspectjtools.jar:CLASSPATHorg.aspectj.tools.ajc.Main.javajavaclasspathASPECT_LIB/aspectjrt.jar:$CLASSPATH HelloWorld

3.2加载时编织
如果采用加载时编织的方法,首先对HelloWorld.java进行编译
Javac HelloWorld.java
然后对SayAspect.java进行编译,并输出一个aop.xml的文件
java –classpath ASPECTLIB/aspectjrt.jar:ASPECT_LIB/aspectjtools.jar:CLASSPATHorg.aspectj.tools.ajc.MainoutxmlSayAspect.javaMETAINFaopajc.xml使javaclasspathASPECT_LIB/aspectjrt.jar:CLASSPATHjavaagent:ASPECT_LIB/aspectjweaver.jar HelloWorld

 (作者:pyjin)

 












本文转自百度技术51CTO博客,原文链接:http://blog.51cto.com/baidutech/744424,如需转载请自行联系原作者

相关文章
|
4月前
|
敏捷开发 测试技术 持续交付
探索自动化测试在敏捷开发中的应用与挑战
本文深入探讨了自动化测试在现代软件开发流程,特别是敏捷开发环境中的重要作用和面临的挑战。通过分析自动化测试的基本原理、实施策略以及在实际项目中的应用案例,揭示了其在提高软件质量和加速产品交付方面的巨大潜力。同时,文章也指出了自动化测试实施过程中可能遇到的技术难题、成本考量及团队协作问题,并提出了相应的解决策略,为软件开发团队提供了有价值的参考和指导。
|
3月前
|
Java 测试技术 数据安全/隐私保护
软件测试中的自动化策略与工具应用
在软件开发的快速迭代中,自动化测试以其高效、稳定的特点成为了质量保证的重要手段。本文将深入探讨自动化测试的核心概念、常见工具的应用,以及如何设计有效的自动化测试策略,旨在为读者提供一套完整的自动化测试解决方案,帮助团队提升测试效率和软件质量。
|
4月前
|
编解码 测试技术 开发工具
测试 iPhone 应用在不同屏幕尺寸和分辨率下的响应式效果
【10月更文挑战第23天】测试 iPhone 应用在不同屏幕尺寸和分辨率下的响应式效果是确保应用质量和用户体验的重要环节。通过手动测试、自动化测试、视觉效果评估、性能测试、用户体验测试等多种方法的综合运用,能够全面地发现应用在响应式效果方面存在的问题,并及时进行解决和优化。同时,持续的测试和优化也是不断提升应用质量和用户满意度的关键。
|
16天前
|
算法
MATLAB在风险管理中的应用:从VaR计算到压力测试
本文介绍如何使用MATLAB进行风险管理,涵盖风险度量(如VaR)、压力测试和风险分解。通过历史模拟法、参数法和蒙特卡洛模拟法计算VaR,评估投资组合在极端市场条件下的表现,并通过边际VaR和成分VaR识别风险来源。结合具体案例和代码实现,帮助读者掌握MATLAB在风险管理中的应用,确保投资组合的稳健性。
|
2月前
|
搜索推荐 测试技术 API
探秘电商API:从测试到应用的深度解析与实战指南
电商API是电子商务背后的隐形引擎,支撑着从商品搜索、购物车更新到支付处理等各个环节的顺畅运行。它通过定义良好的接口,实现不同系统间的数据交互与功能集成,确保订单、库存和物流等信息的实时同步。RESTful、GraphQL和WebSocket等类型的API各自适用于不同的应用场景,满足多样化的需求。在测试方面,使用Postman、SoapUI和jMeter等工具进行全面的功能、性能和安全测试,确保API的稳定性和可靠性。未来,随着人工智能、大数据和物联网技术的发展,电商API将进一步智能化和标准化,为用户提供更个性化的购物体验,并推动电商行业的持续创新与进步。
67 4
|
4月前
|
监控 安全 测试技术
如何在实际项目中应用Python Web开发的安全测试知识?
如何在实际项目中应用Python Web开发的安全测试知识?
123 61
|
4月前
|
jenkins 测试技术 持续交付
探索自动化测试在持续集成中的应用与挑战
本文深入探讨了自动化测试在现代软件开发流程,特别是持续集成(CI)环境中的关键作用。通过分析自动化测试的优势、实施策略以及面临的主要挑战,旨在为开发团队提供实用的指导和建议。文章不仅概述了自动化测试的基本原理和最佳实践,还详细讨论了如何克服实施过程中遇到的技术难题和管理障碍,以实现更高效、更可靠的软件交付。
109 19
|
4月前
|
机器学习/深度学习 人工智能 测试技术
探索自动化测试框架在软件开发中的应用与挑战##
本文将深入探讨自动化测试框架在现代软件开发过程中的应用,分析其优势与面临的挑战。通过具体案例分析,揭示如何有效整合自动化测试以提升软件质量和开发效率。 ##
|
4月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
107 1
|
4月前
|
敏捷开发 监控 jenkins
探索自动化测试框架在敏捷开发中的应用与优化##
本文深入探讨了自动化测试框架在现代敏捷软件开发流程中的关键作用,分析了其面临的挑战及优化策略。通过对比传统测试方法,阐述了自动化测试如何加速软件迭代周期,提升产品质量,并针对实施过程中的常见问题提出了解决方案。旨在为读者提供一套高效、可扩展的自动化测试实践指南。 ##
69 9

热门文章

最新文章